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
Expand Up @@ -853,7 +853,6 @@ def mouseUp(self, evt, pos, direction):
self.editor.level,
self.draggedPositions,
self.getBrushOptions())
self.performWithRetry(op)

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

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

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

self.editor.addUnsavedEdit()

self.editor.addOperation(op)
Expand Down
6 changes: 0 additions & 6 deletions editortools/editortool.py
Expand Up @@ -293,9 +293,3 @@ def hidePanel(self):
self.panel.parent.remove(self.panel)
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
Expand Up @@ -244,7 +244,6 @@ def confirm(self):
blocksToReplace = []
op = BlockFillOperation(self.editor, self.editor.level, self.selectionBox(), self.blockInfo, blocksToReplace)

self.performWithRetry(op)

self.editor.addOperation(op)

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

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

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

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:
exhaust(_extractUndo())

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

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

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

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

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

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

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

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

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

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

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

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

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

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

op = DeleteEntitiesOperation(self.editor, self.editor.level)
self.performWithRetry(op, recordUndo)
if recordUndo:
self.editor.addOperation(op)
self.editor.addUnsavedEdit()
Expand Down
23 changes: 19 additions & 4 deletions leveleditor.py
Expand Up @@ -55,7 +55,7 @@
from OpenGL import GL
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.dialogs import Dialog, QuickDialog, wrapped_label
from albow.openglwidgets import GLOrtho, GLViewport
Expand Down Expand Up @@ -1488,8 +1488,10 @@ def showViewOptions():
self.viewportButton = Button("Camera View", action=self.swapViewports,
tooltipText="Shortcut: TAB")

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

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 = Row(row)
Expand Down Expand Up @@ -1948,6 +1950,7 @@ def loadFile(self, filename):

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

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

self.recordUndo = True
self.clearUnsavedEdits()

def addUnsavedEdit(self):
Expand Down Expand Up @@ -2131,7 +2135,7 @@ def clearUnsavedEdits(self):
def saveInfoLabelText(self):
if self.unsavedEdits == 0:
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
def viewDistanceLabelText(self):
Expand Down Expand Up @@ -3357,7 +3361,18 @@ def selectionChanged(self):
self.currentTool.selectionChanged()

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):
self.mouseLookOff()
Expand Down

0 comments on commit 963d2a7

Please sign in to comment.