Skip to content

Commit

Permalink
Added: "Record Undo" option.
Browse files Browse the repository at this point in the history
"Record Undo" is reset when loading or saving a level.
Long undo operations can be canceled.
  • Loading branch information
codewarrior0 committed Mar 14, 2013
1 parent c5e5ceb commit 963d2a7
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 37 deletions.
1 change: 0 additions & 1 deletion editortools/brush.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -853,7 +853,6 @@ def mouseUp(self, evt, pos, direction):
self.editor.level, self.editor.level,
self.draggedPositions, self.draggedPositions,
self.getBrushOptions()) self.getBrushOptions())
self.performWithRetry(op)


box = op.dirtyBox() box = op.dirtyBox()
self.editor.addOperation(op) self.editor.addOperation(op)
Expand Down
21 changes: 10 additions & 11 deletions editortools/clone.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -193,13 +193,16 @@ def dirtyBox(self):
return self._dirtyBox return self._dirtyBox


def perform(self, recordUndo=True): def perform(self, recordUndo=True):
if recordUndo: with setWindowCaption("COPYING - "):
chunks = set() self.editor.freezeStatus("Copying %0.1f million blocks" % (float(self._dirtyBox.volume) / 1048576.,))
for op in self.blockCopyOps: if recordUndo:
chunks.update(op.dirtyBox().chunkPositions) chunks = set()
self.undoLevel = self.extractUndoChunks(self.level, chunks) for op in self.blockCopyOps:
[i.perform(False) for i in self.blockCopyOps] chunks.update(op.dirtyBox().chunkPositions)
[i.perform(recordUndo) for i in self.selectionOps] self.undoLevel = self.extractUndoChunks(self.level, chunks)

[i.perform(False) for i in self.blockCopyOps]
[i.perform(recordUndo) for i in self.selectionOps]


def undo(self): def undo(self):
super(CloneOperation, self).undo() super(CloneOperation, self).undo()
Expand Down Expand Up @@ -955,10 +958,6 @@ def confirm(self):


self.editor.toolbar.selectTool(-1) # deselect tool so that the clone tool's selection change doesn't update its schematic self.editor.toolbar.selectTool(-1) # deselect tool so that the clone tool's selection change doesn't update its schematic


with setWindowCaption("COPYING - "):
self.editor.freezeStatus("Copying %0.1f million blocks" % (float(destVolume) / 1048576.,))
self.performWithRetry(op)

self.editor.addUnsavedEdit() self.editor.addUnsavedEdit()


self.editor.addOperation(op) self.editor.addOperation(op)
Expand Down
6 changes: 0 additions & 6 deletions editortools/editortool.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -293,9 +293,3 @@ def hidePanel(self):
self.panel.parent.remove(self.panel) self.panel.parent.remove(self.panel)
self.panel = None self.panel = None


def performWithRetry(self, op, recordUndo=True):
try:
op.perform(recordUndo)
except MemoryError:
self.editor.invalidateAllChunks()
op.perform(recordUndo)
1 change: 0 additions & 1 deletion editortools/fill.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ def confirm(self):
blocksToReplace = [] blocksToReplace = []
op = BlockFillOperation(self.editor, self.editor.level, self.selectionBox(), self.blockInfo, blocksToReplace) op = BlockFillOperation(self.editor, self.editor.level, self.selectionBox(), self.blockInfo, blocksToReplace)


self.performWithRetry(op)


self.editor.addOperation(op) self.editor.addOperation(op)


Expand Down
1 change: 0 additions & 1 deletion editortools/filter.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ def confirm(self):
op = FilterOperation(self.editor, self.editor.level, self.selectionBox(), filterModule, self.panel.filterOptionsPanel.options) op = FilterOperation(self.editor, self.editor.level, self.selectionBox(), filterModule, self.panel.filterOptionsPanel.options)


self.editor.level.showProgress = showProgress self.editor.level.showProgress = showProgress
self.performWithRetry(op)


self.editor.addOperation(op) self.editor.addOperation(op)
self.editor.addUnsavedEdit() self.editor.addUnsavedEdit()
Expand Down
7 changes: 6 additions & 1 deletion editortools/operation.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os import os
import shutil import shutil
import tempfile import tempfile
import albow
from pymclevel import BoundingBox from pymclevel import BoundingBox
import numpy import numpy
from albow.root import Cancel from albow.root import Cancel
Expand Down Expand Up @@ -57,7 +58,11 @@ def _extractUndo():
undoLevel.saveInPlace() undoLevel.saveInPlace()


if chunkCount > 25 or chunkCount < 1: if chunkCount > 25 or chunkCount < 1:
showProgress("Recording undo...", _extractUndo()) if "Canceled" == showProgress("Recording undo...", _extractUndo(), cancel=True):
if albow.ask("Continue with undo disabled?", ["Continue", "Cancel"]) == "Cancel":
raise Cancel
else:
return None
else: else:
exhaust(_extractUndo()) exhaust(_extractUndo())


Expand Down
15 changes: 3 additions & 12 deletions editortools/select.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ def nudgeBlocks(self, dir):
dir = dir * (16, 16, 16) dir = dir * (16, 16, 16)
op = NudgeBlocksOperation(self.editor, self.editor.level, self.selectionBox(), dir) op = NudgeBlocksOperation(self.editor, self.editor.level, self.selectionBox(), dir)


self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)
self.editor.addUnsavedEdit() self.editor.addUnsavedEdit()


Expand All @@ -416,8 +415,7 @@ def nudgeSelection(self, dir):
return return


op = NudgeSelectionOperation(self, dir) op = NudgeSelectionOperation(self, dir)
self.performWithRetry(op) self.editor.addOperation(op)
# self.editor.addOperation(op)


def nudgePoint(self, p, n): def nudgePoint(self, p, n):
if self.selectionBox() is None: if self.selectionBox() is None:
Expand Down Expand Up @@ -608,7 +606,6 @@ def mouseUp(self, evt, pos, direction):
o, m = self.selectionPointsFromDragResize() o, m = self.selectionPointsFromDragResize()


op = SelectionOperation(self, (o, m)) op = SelectionOperation(self, (o, m))
self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)


self.dragResizeFace = None self.dragResizeFace = None
Expand All @@ -622,13 +619,12 @@ def mouseUp(self, evt, pos, direction):


if self.dragStartPoint != pos or self.clickSelectionInProgress: if self.dragStartPoint != pos or self.clickSelectionInProgress:
op = SelectionOperation(self, (self.dragStartPoint, pos)) op = SelectionOperation(self, (self.dragStartPoint, pos))
self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)
self.selectionInProgress = False self.selectionInProgress = False
self.currentCorner = 1 self.currentCorner = 1
self.clickSelectionInProgress = False self.clickSelectionInProgress = False
self.dragStartPoint = None self.dragStartPoint = None

else: else:
points = self.getSelectionPoints() points = self.getSelectionPoints()
if not all(points): if not all(points):
Expand All @@ -639,7 +635,6 @@ def mouseUp(self, evt, pos, direction):
self.clickSelectionInProgress = True self.clickSelectionInProgress = True
else: else:
op = SelectionOperation(self, points) op = SelectionOperation(self, points)
self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)


self.selectOtherCorner() self.selectOtherCorner()
Expand Down Expand Up @@ -947,12 +942,10 @@ def selectNone(self):
def selectAll(self): def selectAll(self):
box = self.editor.level.bounds box = self.editor.level.bounds
op = SelectionOperation(self, self.selectionPointsFromBox(box)) op = SelectionOperation(self, self.selectionPointsFromBox(box))
self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)


def deselect(self): def deselect(self):
op = SelectionOperation(self, None) op = SelectionOperation(self, None)
self.performWithRetry(op)
self.editor.addOperation(op) self.editor.addOperation(op)


def setSelectionPoint(self, pointNumber, newPoint): def setSelectionPoint(self, pointNumber, newPoint):
Expand Down Expand Up @@ -996,14 +989,13 @@ def deleteBlocks(self):
else: else:
self._deleteBlocks() self._deleteBlocks()


def _deleteBlocks(self, recordUndo=True): def _deleteBlocks(self):
box = self.selectionBox() box = self.selectionBox()
if None is box: if None is box:
return return
op = BlockFillOperation(self.editor, self.editor.level, box, self.editor.level.materials.Air, []) op = BlockFillOperation(self.editor, self.editor.level, box, self.editor.level.materials.Air, [])
with setWindowCaption("DELETING - "): with setWindowCaption("DELETING - "):
self.editor.freezeStatus("Deleting {0} blocks".format(box.volume)) self.editor.freezeStatus("Deleting {0} blocks".format(box.volume))
self.performWithRetry(op, recordUndo)


self.editor.addOperation(op) self.editor.addOperation(op)
self.editor.invalidateBox(box) self.editor.invalidateBox(box)
Expand All @@ -1030,7 +1022,6 @@ def undo(self):
editor.renderer.invalidateEntitiesInBox(box) editor.renderer.invalidateEntitiesInBox(box)


op = DeleteEntitiesOperation(self.editor, self.editor.level) op = DeleteEntitiesOperation(self.editor, self.editor.level)
self.performWithRetry(op, recordUndo)
if recordUndo: if recordUndo:
self.editor.addOperation(op) self.editor.addOperation(op)
self.editor.addUnsavedEdit() self.editor.addUnsavedEdit()
Expand Down
23 changes: 19 additions & 4 deletions leveleditor.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
from OpenGL import GL from OpenGL import GL
from OpenGL import GLU from OpenGL import GLU


from albow import alert, ask, AttrRef, Button, Column, get_font, Grid, input_text, IntField, Menu, root, Row, TableColumn, TableView, TextField, TimeField, Widget from albow import alert, ask, AttrRef, Button, Column, get_font, Grid, input_text, IntField, Menu, root, Row, TableColumn, TableView, TextField, TimeField, Widget, CheckBox
from albow.controls import Label, SmallValueDisplay, ValueDisplay from albow.controls import Label, SmallValueDisplay, ValueDisplay
from albow.dialogs import Dialog, QuickDialog, wrapped_label from albow.dialogs import Dialog, QuickDialog, wrapped_label
from albow.openglwidgets import GLOrtho, GLViewport from albow.openglwidgets import GLOrtho, GLViewport
Expand Down Expand Up @@ -1488,8 +1488,10 @@ def showViewOptions():
self.viewportButton = Button("Camera View", action=self.swapViewports, self.viewportButton = Button("Camera View", action=self.swapViewports,
tooltipText="Shortcut: TAB") tooltipText="Shortcut: TAB")


self.recordUndoButton = mceutils.CheckBoxLabel("Record Undo", ref=AttrRef(self, 'recordUndo'))

row = (mcEditButton, viewDistanceDown, Label("View Distance:"), viewDistanceReadout, viewDistanceUp, row = (mcEditButton, viewDistanceDown, Label("View Distance:"), viewDistanceReadout, viewDistanceUp,
readoutGrid, viewButton, self.viewportButton) readoutGrid, viewButton, self.viewportButton, self.recordUndoButton)


# row += (Button("CR Info", action=self.showChunkRendererInfo), ) # row += (Button("CR Info", action=self.showChunkRendererInfo), )
row = Row(row) row = Row(row)
Expand Down Expand Up @@ -1948,6 +1950,7 @@ def loadFile(self, filename):


self.undoStack = [] self.undoStack = []
self.loadLevel(level) self.loadLevel(level)
self.recordUndo = True
self.clearUnsavedEdits() self.clearUnsavedEdits()


self.renderer.position = self.currentViewport.cameraPosition self.renderer.position = self.currentViewport.cameraPosition
Expand Down Expand Up @@ -2098,6 +2101,7 @@ def saveFile(self):
self.freezeStatus("Saving...") self.freezeStatus("Saving...")
self.level.saveInPlace() self.level.saveInPlace()


self.recordUndo = True
self.clearUnsavedEdits() self.clearUnsavedEdits()


def addUnsavedEdit(self): def addUnsavedEdit(self):
Expand Down Expand Up @@ -2131,7 +2135,7 @@ def clearUnsavedEdits(self):
def saveInfoLabelText(self): def saveInfoLabelText(self):
if self.unsavedEdits == 0: if self.unsavedEdits == 0:
return "" return ""
return "{0} unsaved edits. CTRL-S to save. ".format(self.unsavedEdits) return "{0} unsaved edits. CTRL-S to save. {1}".format(self.unsavedEdits, "" if self.recordUndo else "(UNDO DISABLED)")


@property @property
def viewDistanceLabelText(self): def viewDistanceLabelText(self):
Expand Down Expand Up @@ -3357,7 +3361,18 @@ def selectionChanged(self):
self.currentTool.selectionChanged() self.currentTool.selectionChanged()


def addOperation(self, op): def addOperation(self, op):
self.undoStack.append(op) if self.recordUndo:
self.undoStack.append(op)
self.performWithRetry(op)

recordUndo = True

def performWithRetry(self, op):
try:
op.perform(self.recordUndo)
except MemoryError:
self.invalidateAllChunks()
op.perform(self.recordUndo)


def quit(self): def quit(self):
self.mouseLookOff() self.mouseLookOff()
Expand Down

0 comments on commit 963d2a7

Please sign in to comment.