diff --git a/editortools/brush.py b/editortools/brush.py index b15b4ac..0b54458 100644 --- a/editortools/brush.py +++ b/editortools/brush.py @@ -21,6 +21,8 @@ import tempfile import itertools from toolbasics import * import logging +from operation import Operation + log = logging.getLogger(__name__) diff --git a/editortools/clone.py b/editortools/clone.py index 73a6022..95f5bba 100644 --- a/editortools/clone.py +++ b/editortools/clone.py @@ -11,6 +11,7 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" +from operation import Operation from pymclevel.box import Vector from toolbasics import * diff --git a/editortools/fill.py b/editortools/fill.py index 030c671..4537ac7 100644 --- a/editortools/fill.py +++ b/editortools/fill.py @@ -11,6 +11,7 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" +from operation import Operation from toolbasics import * diff --git a/editortools/filter.py b/editortools/filter.py index d44b600..77d8354 100644 --- a/editortools/filter.py +++ b/editortools/filter.py @@ -11,6 +11,7 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" +from operation import Operation from toolbasics import * from albow.dialogs import wrapped_label from albow import * diff --git a/editortools/operation.py b/editortools/operation.py new file mode 100644 index 0000000..7a663ed --- /dev/null +++ b/editortools/operation.py @@ -0,0 +1,57 @@ +import atexit +import shutil +import tempfile +import pymclevel +from mceutils import showProgress + +class Operation(object): + changedLevel = True + undoLevel = None + + def __init__(self, editor, level): + self.editor = editor + self.level = level + + def extractUndo(self, level, box): + undoPath = tempfile.mkdtemp("mceditundo") + undoLevel = pymclevel.MCInfdevOldLevel(undoPath, create=True) + atexit.register(shutil.rmtree, undoPath, True) + + def _extractUndo(): + yield 0, 0, "Recording undo..." + for i, (cx, cz) in enumerate(box.chunkPositions): + undoLevel.copyChunkFrom(level, cx, cz) + yield i, box.chunkCount, "Copying chunk %s..." % ((cx, cz),) + undoLevel.saveInPlace() + + showProgress("Recording undo...", _extractUndo()) + + return undoLevel + + # represents a single undoable operation + def perform(self, recordUndo=True): + " Perform the operation. Record undo information if recordUndo" + + def undo(self): + """ Undo the operation. Ought to leave the Operation in a state where it can be performed again. + Default implementation copies all chunks in undoLevel back into level. Non-chunk-based operations + should override this.""" + + if self.undoLevel: + + def _undo(): + yield 0, 0, "Undoing..." + for i, (cx, cz) in enumerate(self.undoLevel.allChunks): + self.level.copyChunkFrom(self.undoLevel, cx, cz) + yield i, self.undoLevel.chunkCount, "Copying chunk %s..." % ((cx, cz),) + + + showProgress("Undoing...", _undo()) + self.editor.invalidateChunks(self.undoLevel.allChunks) + + + def dirtyBox(self): + """ The region modified by the operation. + Return None to indicate no blocks were changed. + """ + return None diff --git a/editortools/player.py b/editortools/player.py index b935d76..a5d7b01 100644 --- a/editortools/player.py +++ b/editortools/player.py @@ -11,6 +11,7 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" +from operation import Operation from toolbasics import * import urllib diff --git a/editortools/select.py b/editortools/select.py index f7d8f4a..8e93eb7 100644 --- a/editortools/select.py +++ b/editortools/select.py @@ -13,6 +13,7 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""" from collections import defaultdict +from operation import Operation from pymclevel.box import Vector from fill import FillTool, BlockFillOperation import tempfile diff --git a/editortools/toolbasics.py b/editortools/toolbasics.py index 6c98f48..b5a510a 100644 --- a/editortools/toolbasics.py +++ b/editortools/toolbasics.py @@ -16,6 +16,7 @@ import shutil import tempfile from OpenGL.GL import * +from operation import Operation from pymclevel import * import pymclevel @@ -97,59 +98,6 @@ class NudgeButton(GLBackground): self.nudge(Vector(*right)) -class Operation(object): - changedLevel = True - undoLevel = None - - def __init__(self, editor, level): - self.editor = editor - self.level = level - - def extractUndo(self, level, box): - undoPath = tempfile.mkdtemp("mceditundo") - undoLevel = MCInfdevOldLevel(undoPath, create=True) - atexit.register(shutil.rmtree, undoPath, True) - - def _extractUndo(): - yield 0, 0, "Recording undo..." - for i, (cx, cz) in enumerate(box.chunkPositions): - undoLevel.copyChunkFrom(level, cx, cz) - yield i, box.chunkCount, "Copying chunk %s..." % ((cx, cz),) - undoLevel.saveInPlace() - - showProgress("Recording undo...", _extractUndo()) - - return undoLevel - - # represents a single undoable operation - def perform(self, recordUndo=True): - " Perform the operation. Record undo information if recordUndo" - - def undo(self): - """ Undo the operation. Ought to leave the Operation in a state where it can be performed again. - Default implementation copies all chunks in undoLevel back into level. Non-chunk-based operations - should override this.""" - - if self.undoLevel: - - def _undo(): - yield 0, 0, "Undoing..." - for i, (cx, cz) in enumerate(self.undoLevel.allChunks): - self.level.copyChunkFrom(self.undoLevel, cx, cz) - yield i, self.undoLevel.chunkCount, "Copying chunk %s..." % ((cx, cz),) - - - showProgress("Undoing...", _undo()) - self.editor.invalidateChunks(self.undoLevel.allChunks) - - - def dirtyBox(self): - """ The region modified by the operation. - Return None to indicate no blocks were changed. - """ - return None - - class ToolOptions(Panel): @property def editor(self): diff --git a/leveleditor.py b/leveleditor.py index 0d25fd4..21c50c8 100644 --- a/leveleditor.py +++ b/leveleditor.py @@ -58,8 +58,8 @@ from albow.openglwidgets import GLOrtho, GLViewport from pygame import display, event, key, KMOD_ALT, KMOD_CTRL, KMOD_LALT, KMOD_META, KMOD_RALT, KMOD_SHIFT, mouse, MOUSEMOTION from depths import DepthOffset +from editortools.operation import Operation from editortools.chunk import GeneratorPanel -from editortools.toolbasics import Operation from glbackground import GLBackground, Panel from glutils import gl, Texture from mcplatform import askSaveFile