Moved programs out of plugins
Programs use a different system to operations so it makes sense not to have them combined
@ -5,10 +5,10 @@ import webbrowser
|
|||||||
|
|
||||||
from amulet.api.errors import LoaderNoneMatched
|
from amulet.api.errors import LoaderNoneMatched
|
||||||
from amulet_map_editor.amulet_wx.world_select import WorldSelectWindow
|
from amulet_map_editor.amulet_wx.world_select import WorldSelectWindow
|
||||||
from amulet_map_editor import lang, config, version, log, IMG_DIR
|
from amulet_map_editor import lang, version, log, IMG_DIR
|
||||||
from amulet_map_editor.plugins.programs import WorldManagerUI
|
from amulet_map_editor.programs import WorldManagerUI
|
||||||
from amulet_map_editor.amulet_wx import simple
|
from amulet_map_editor.amulet_wx import simple
|
||||||
from amulet_map_editor.plugins.programs import BaseWorldUI
|
from amulet_map_editor.programs import BaseWorldUI
|
||||||
|
|
||||||
|
|
||||||
class AmuletMainWindow(wx.Frame):
|
class AmuletMainWindow(wx.Frame):
|
||||||
|
@ -39,7 +39,7 @@ def load_extensions():
|
|||||||
_extensions.extend(_fixed_extensions)
|
_extensions.extend(_fixed_extensions)
|
||||||
for _, name, _ in pkgutil.iter_modules([os.path.join(os.path.dirname(__file__))]):
|
for _, name, _ in pkgutil.iter_modules([os.path.join(os.path.dirname(__file__))]):
|
||||||
# load module and confirm that all required attributes are defined
|
# load module and confirm that all required attributes are defined
|
||||||
module = importlib.import_module(f'amulet_map_editor.plugins.programs.{name}')
|
module = importlib.import_module(f'amulet_map_editor.programs.{name}')
|
||||||
|
|
||||||
if hasattr(module, 'export'):
|
if hasattr(module, 'export'):
|
||||||
export = getattr(module, 'export')
|
export = getattr(module, 'export')
|
@ -9,7 +9,7 @@ from amulet.world_interface.formats import Format
|
|||||||
from amulet_map_editor import lang, log
|
from amulet_map_editor import lang, log
|
||||||
from amulet_map_editor.amulet_wx.simple import SimplePanel
|
from amulet_map_editor.amulet_wx.simple import SimplePanel
|
||||||
from amulet_map_editor.amulet_wx.world_select import WorldSelectWindow, WorldUI
|
from amulet_map_editor.amulet_wx.world_select import WorldSelectWindow, WorldUI
|
||||||
from amulet_map_editor.plugins.programs import BaseWorldProgram, MenuData
|
from amulet_map_editor.programs import BaseWorldProgram, MenuData
|
||||||
|
|
||||||
|
|
||||||
thread_pool_executor = ThreadPoolExecutor(max_workers=1)
|
thread_pool_executor = ThreadPoolExecutor(max_workers=1)
|
@ -7,13 +7,13 @@ This means that any chunks that exist in the source world will be overwritten in
|
|||||||
|
|
||||||
If there is a chunk in the destination world and there is no chunk in the source world at that location then the chunk will be left as it was.
|
If there is a chunk in the destination world and there is no chunk in the source world at that location then the chunk will be left as it was.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
- Make sure that any world you wish to open is not open in game or another program.
|
- Make sure that any world you wish to open is not open in game or another program.
|
||||||
- Backup both the world you want to convert from and the world you want to convert to in case there are any corruptions.
|
- Backup both the world you want to convert from and the world you want to convert to in case there are any corruptions.
|
||||||
- [Open your source world](../../../readme.md#open-world). This should bring up a screen which looks similar to the image above with "convert" on the left.
|
- [Open your source world](../../readme.md#open-world). This should bring up a screen which looks similar to the image above with "convert" on the left.
|
||||||
- Click on the convert tab on the left if it is not enabled. This should make the screen look the same as the image above with the world imformation populated with your source world information.
|
- Click on the convert tab on the left if it is not enabled. This should make the screen look the same as the image above with the world imformation populated with your source world information.
|
||||||
- Click the select output world button and select the destination world in a similar way to how you selected the source world.
|
- Click the select output world button and select the destination world in a similar way to how you selected the source world.
|
||||||
- Check that the worlds shown are the world you want to convert from and the world that you want to convert into.
|
- Check that the worlds shown are the world you want to convert from and the world that you want to convert into.
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -12,7 +12,7 @@ from amulet.api.chunk import Chunk
|
|||||||
from amulet.api.structure import Structure
|
from amulet.api.structure import Structure
|
||||||
from amulet.api.errors import ChunkLoadError
|
from amulet.api.errors import ChunkLoadError
|
||||||
|
|
||||||
from amulet_map_editor.opengl.mesh.world_renderer.world import RenderWorld, sin, cos, asin, acos, tan, atan
|
from amulet_map_editor.opengl.mesh.world_renderer.world import RenderWorld, sin, cos, tan, atan
|
||||||
from amulet_map_editor.opengl.mesh.selection import RenderSelection
|
from amulet_map_editor.opengl.mesh.selection import RenderSelection
|
||||||
from amulet_map_editor.opengl.mesh.structure import RenderStructure
|
from amulet_map_editor.opengl.mesh.structure import RenderStructure
|
||||||
from amulet_map_editor.opengl import textureatlas
|
from amulet_map_editor.opengl import textureatlas
|
||||||
@ -20,7 +20,7 @@ from amulet_map_editor import log
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from amulet.api.world import World
|
from amulet.api.world import World
|
||||||
from amulet_map_editor.plugins.programs.edit.edit import EditExtension
|
from amulet_map_editor.programs.edit.edit import EditExtension
|
||||||
|
|
||||||
|
|
||||||
class EditCanvas(glcanvas.GLCanvas):
|
class EditCanvas(glcanvas.GLCanvas):
|
@ -1,9 +1,8 @@
|
|||||||
from typing import TYPE_CHECKING, Optional, Tuple, Union
|
from typing import TYPE_CHECKING, Tuple, Union
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
from .canvas import EditCanvas
|
from .canvas import EditCanvas
|
||||||
from amulet_map_editor.opengl.mesh.world_renderer.world import sin, cos
|
from amulet_map_editor.opengl.mesh.world_renderer.world import sin, cos
|
||||||
from amulet_map_editor.amulet_wx.simple import SimpleDialog
|
|
||||||
from ..events import (
|
from ..events import (
|
||||||
CameraMoveEvent,
|
CameraMoveEvent,
|
||||||
BoxGreenCornerChangeEvent,
|
BoxGreenCornerChangeEvent,
|
||||||
@ -13,7 +12,7 @@ from ..events import (
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from amulet.api.world import World
|
from amulet.api.world import World
|
||||||
from amulet_map_editor.plugins.programs.edit.edit import EditExtension
|
from amulet_map_editor.programs.edit.edit import EditExtension
|
||||||
|
|
||||||
|
|
||||||
key_map = {
|
key_map = {
|
@ -11,21 +11,19 @@ from amulet.api.data_types import OperationType, OperationReturnType
|
|||||||
from amulet.operations.paste import paste
|
from amulet.operations.paste import paste
|
||||||
from amulet.operations.fill import fill
|
from amulet.operations.fill import fill
|
||||||
|
|
||||||
from amulet_map_editor.plugins.programs import BaseWorldProgram, MenuData
|
from amulet_map_editor.programs import BaseWorldProgram, MenuData
|
||||||
from amulet_map_editor.plugins import operations
|
from amulet_map_editor.plugins import operations
|
||||||
from .canvas.controllable_canvas import ControllableEditCanvas
|
from .canvas.controllable_canvas import ControllableEditCanvas
|
||||||
|
|
||||||
from .ui.file import FilePanel
|
from .ui.file import FilePanel
|
||||||
from amulet_map_editor.plugins.programs.edit.ui.tool_options.operation import OperationUI
|
from amulet_map_editor.programs.edit.ui.tool_options.operation import OperationUI
|
||||||
from amulet_map_editor.plugins.programs.edit.ui.tool_options.select import SelectOptions
|
from amulet_map_editor.programs.edit.ui.tool_options.select import SelectOptions
|
||||||
from amulet_map_editor.plugins.programs.edit.ui.tool import ToolSelect
|
from amulet_map_editor.programs.edit.ui.tool import ToolSelect
|
||||||
|
|
||||||
from .events import (
|
from .events import (
|
||||||
EVT_CAMERA_MOVE,
|
EVT_CAMERA_MOVE,
|
||||||
EVT_SELECT_TOOL_ENABLED,
|
EVT_SELECT_TOOL_ENABLED,
|
||||||
EVT_OPERATION_TOOL_ENABLED,
|
EVT_OPERATION_TOOL_ENABLED
|
||||||
EVT_IMPORT_TOOL_ENABLED,
|
|
||||||
EVT_EXPORT_TOOL_ENABLED
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The edit program is a 3D world editor with similarities to MCEdit Unified. The user can select an area and run various operations on that area.
|
The edit program is a 3D world editor with similarities to MCEdit Unified. The user can select an area and run various operations on that area.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
|
@ -6,7 +6,7 @@ from .goto import show_goto
|
|||||||
from amulet_map_editor.amulet_wx.simple import SimpleChoiceAny
|
from amulet_map_editor.amulet_wx.simple import SimpleChoiceAny
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from amulet_map_editor.plugins.programs.edit.canvas.controllable_canvas import ControllableEditCanvas
|
from amulet_map_editor.programs.edit.canvas.controllable_canvas import ControllableEditCanvas
|
||||||
|
|
||||||
|
|
||||||
class FilePanel(wx.Panel):
|
class FilePanel(wx.Panel):
|
@ -1,6 +1,6 @@
|
|||||||
import wx
|
import wx
|
||||||
|
|
||||||
from amulet_map_editor.plugins.programs.edit.events import (
|
from amulet_map_editor.programs.edit.events import (
|
||||||
SelectToolEnabledEvent,
|
SelectToolEnabledEvent,
|
||||||
OperationToolEnabledEvent,
|
OperationToolEnabledEvent,
|
||||||
ImportToolEnabledEvent,
|
ImportToolEnabledEvent,
|
@ -0,0 +1,90 @@
|
|||||||
|
from typing import TYPE_CHECKING, Type, Any
|
||||||
|
import wx
|
||||||
|
import weakref
|
||||||
|
|
||||||
|
from amulet_map_editor.programs.edit.events import (
|
||||||
|
EVT_BOX_GREEN_CORNER_CHANGE,
|
||||||
|
EVT_BOX_BLUE_CORNER_CHANGE,
|
||||||
|
EVT_BOX_COORDS_ENABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from amulet_map_editor.programs.edit.canvas.controllable_canvas import ControllableEditCanvas
|
||||||
|
|
||||||
|
|
||||||
|
class SelectOptions(wx.Panel):
|
||||||
|
def __init__(self, canvas: 'ControllableEditCanvas'):
|
||||||
|
wx.Panel.__init__(self, canvas)
|
||||||
|
self._canvas = weakref.ref(canvas)
|
||||||
|
self._sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
self.SetSizer(self._sizer)
|
||||||
|
|
||||||
|
self._x1: wx.SpinCtrl = self._add_row('x1', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._y1: wx.SpinCtrl = self._add_row('y1', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._z1: wx.SpinCtrl = self._add_row('z1', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._x1.Bind(wx.EVT_SPINCTRL, self._green_corner_input_change)
|
||||||
|
self._y1.Bind(wx.EVT_SPINCTRL, self._green_corner_input_change)
|
||||||
|
self._z1.Bind(wx.EVT_SPINCTRL, self._green_corner_input_change)
|
||||||
|
|
||||||
|
self._x2: wx.SpinCtrl = self._add_row('x2', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._y2: wx.SpinCtrl = self._add_row('y2', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._z2: wx.SpinCtrl = self._add_row('z2', wx.SpinCtrl, min=-30000000, max=30000000)
|
||||||
|
self._x2.Bind(wx.EVT_SPINCTRL, self._blue_corner_input_change)
|
||||||
|
self._y2.Bind(wx.EVT_SPINCTRL, self._blue_corner_input_change)
|
||||||
|
self._z2.Bind(wx.EVT_SPINCTRL, self._blue_corner_input_change)
|
||||||
|
|
||||||
|
self._x1.Disable()
|
||||||
|
self._y1.Disable()
|
||||||
|
self._z1.Disable()
|
||||||
|
self._x2.Disable()
|
||||||
|
self._y2.Disable()
|
||||||
|
self._z2.Disable()
|
||||||
|
|
||||||
|
self._x1.SetBackgroundColour((160, 215, 145))
|
||||||
|
self._y1.SetBackgroundColour((160, 215, 145))
|
||||||
|
self._z1.SetBackgroundColour((160, 215, 145))
|
||||||
|
|
||||||
|
self._x2.SetBackgroundColour((150, 150, 215))
|
||||||
|
self._y2.SetBackgroundColour((150, 150, 215))
|
||||||
|
self._z2.SetBackgroundColour((150, 150, 215))
|
||||||
|
|
||||||
|
self._canvas().Bind(EVT_BOX_GREEN_CORNER_CHANGE, self._green_corner_renderer_change)
|
||||||
|
self._canvas().Bind(EVT_BOX_BLUE_CORNER_CHANGE, self._blue_corner_renderer_change)
|
||||||
|
self._canvas().Bind(EVT_BOX_COORDS_ENABLE, self._enable_scrolls)
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self._canvas().select_mode = 0
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
def _add_row(self, label: str, wx_object: Type[wx.Object], **kwargs) -> Any:
|
||||||
|
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
self._sizer.Add(sizer, 0, 0)
|
||||||
|
name_text = wx.StaticText(self, label=label)
|
||||||
|
sizer.Add(name_text, flag=wx.CENTER | wx.ALL | wx.EXPAND, border=5)
|
||||||
|
obj = wx_object(self, **kwargs)
|
||||||
|
sizer.Add(obj, flag=wx.CENTER | wx.ALL, border=5)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def _green_corner_input_change(self, _):
|
||||||
|
self._canvas().selection_box.point1 = [self._x1.GetValue(), self._y1.GetValue(), self._z1.GetValue()]
|
||||||
|
|
||||||
|
def _blue_corner_input_change(self, _):
|
||||||
|
self._canvas().selection_box.point2 = [self._x2.GetValue(), self._y2.GetValue(), self._z2.GetValue()]
|
||||||
|
|
||||||
|
def _green_corner_renderer_change(self, evt):
|
||||||
|
self._x1.SetValue(evt.x)
|
||||||
|
self._y1.SetValue(evt.y)
|
||||||
|
self._z1.SetValue(evt.z)
|
||||||
|
|
||||||
|
def _blue_corner_renderer_change(self, evt):
|
||||||
|
self._x2.SetValue(evt.x)
|
||||||
|
self._y2.SetValue(evt.y)
|
||||||
|
self._z2.SetValue(evt.z)
|
||||||
|
|
||||||
|
def _enable_scrolls(self, evt):
|
||||||
|
self._x1.Enable(evt.enabled)
|
||||||
|
self._y1.Enable(evt.enabled)
|
||||||
|
self._z1.Enable(evt.enabled)
|
||||||
|
self._x2.Enable(evt.enabled)
|
||||||
|
self._y2.Enable(evt.enabled)
|
||||||
|
self._z2.Enable(evt.enabled)
|
@ -2,14 +2,14 @@ from typing import TYPE_CHECKING, Type, Any
|
|||||||
import wx
|
import wx
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from amulet_map_editor.plugins.programs.edit.events import (
|
from amulet_map_editor.programs.edit.events import (
|
||||||
EVT_BOX_GREEN_CORNER_CHANGE,
|
EVT_BOX_GREEN_CORNER_CHANGE,
|
||||||
EVT_BOX_BLUE_CORNER_CHANGE,
|
EVT_BOX_BLUE_CORNER_CHANGE,
|
||||||
EVT_BOX_COORDS_ENABLE
|
EVT_BOX_COORDS_ENABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from amulet_map_editor.plugins.programs.edit.canvas.controllable_canvas import ControllableEditCanvas
|
from amulet_map_editor.programs.edit.canvas.controllable_canvas import ControllableEditCanvas
|
||||||
|
|
||||||
|
|
||||||
class SelectOptions(wx.Panel):
|
class SelectOptions(wx.Panel):
|
@ -34,7 +34,7 @@ On the top are the worlds that you currently have open in Amulet to make it easy
|
|||||||
|
|
||||||
On the left are the different sub-programs contained within Amulet. The documentation for which can be found below.
|
On the left are the different sub-programs contained within Amulet. The documentation for which can be found below.
|
||||||
|
|
||||||
[Convert Program Documentation](plugins/programs/convert/readme.md)
|
[Convert Program Documentation](programs/convert/readme.md)
|
||||||
|
|
||||||
[Edit Program Documentation](plugins/programs/edit/readme.md)
|
[Edit Program Documentation](programs/edit/readme.md)
|
||||||
|
|
||||||
|