Added: Use copyChunkFrom to record undo information.
Operation now has `editor` and `level` as required arguments to init. Operation has a default `undo` implementation that copies all chunks from `undoLevel`. `undoSchematic` renamed to `undoLevel`
This commit is contained in:
parent
24e0c8a9b2
commit
4985791551
@ -118,8 +118,7 @@ class Modes:
|
|||||||
if (cx, cz) in dirtyChunks:
|
if (cx, cz) in dirtyChunks:
|
||||||
return
|
return
|
||||||
dirtyChunks.add((cx, cz))
|
dirtyChunks.add((cx, cz))
|
||||||
b = BoundingBox((cx * 16, 0, cz * 16), (16, 128, 16))
|
undoLevel.copyChunkFrom(op.level, cx, cz)
|
||||||
undoLevel.copyBlocksFrom(op.level, b, b.origin, create=True)
|
|
||||||
|
|
||||||
doomedBlock = op.level.blockAt(*point)
|
doomedBlock = op.level.blockAt(*point)
|
||||||
doomedBlockData = op.level.blockDataAt(*point)
|
doomedBlockData = op.level.blockDataAt(*point)
|
||||||
@ -176,7 +175,7 @@ class Modes:
|
|||||||
|
|
||||||
showProgress("Flood fill...", spread([point]), cancel=True)
|
showProgress("Flood fill...", spread([point]), cancel=True)
|
||||||
op.editor.invalidateChunks(dirtyChunks)
|
op.editor.invalidateChunks(dirtyChunks)
|
||||||
op.undoSchematic = undoLevel
|
op.undoLevel = undoLevel
|
||||||
|
|
||||||
class Replace(Fill):
|
class Replace(Fill):
|
||||||
name = "Replace"
|
name = "Replace"
|
||||||
@ -371,12 +370,13 @@ class Modes:
|
|||||||
|
|
||||||
class BrushOperation(Operation):
|
class BrushOperation(Operation):
|
||||||
|
|
||||||
def __init__(self, editor, points, options):
|
def __init__(self, editor, level, points, options):
|
||||||
|
super(BrushOperation, self).__init__(editor, level)
|
||||||
|
|
||||||
# if options is None: options = {}
|
# if options is None: options = {}
|
||||||
|
|
||||||
self.options = options
|
self.options = options
|
||||||
self.editor = editor
|
self.editor = editor
|
||||||
self.level = editor.level
|
|
||||||
if isinstance(points[0], (int, float)):
|
if isinstance(points[0], (int, float)):
|
||||||
points = [points]
|
points = [points]
|
||||||
|
|
||||||
@ -395,7 +395,6 @@ class BrushOperation(Operation):
|
|||||||
boxes = [self.brushMode.brushBoxForPointAndOptions(p, options) for p in points]
|
boxes = [self.brushMode.brushBoxForPointAndOptions(p, options) for p in points]
|
||||||
self._dirtyBox = reduce(lambda a, b: a.union(b), boxes)
|
self._dirtyBox = reduce(lambda a, b: a.union(b), boxes)
|
||||||
|
|
||||||
undoSchematic = None
|
|
||||||
brushStyles = ["Round", "Square", "Diamond"]
|
brushStyles = ["Round", "Square", "Diamond"]
|
||||||
# brushModeNames = ["Fill", "Flood Fill", "Replace", "Erode", "Topsoil", "Paste"] # "Smooth", "Flatten", "Raise", "Lower", "Build", "Erode", "Evert"]
|
# brushModeNames = ["Fill", "Flood Fill", "Replace", "Erode", "Topsoil", "Paste"] # "Smooth", "Flatten", "Raise", "Lower", "Build", "Erode", "Evert"]
|
||||||
brushModeClasses = [
|
brushModeClasses = [
|
||||||
@ -420,29 +419,9 @@ class BrushOperation(Operation):
|
|||||||
def dirtyBox(self):
|
def dirtyBox(self):
|
||||||
return self._dirtyBox
|
return self._dirtyBox
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
if self.undoSchematic:
|
|
||||||
self.level.removeEntitiesInBox(self._dirtyBox)
|
|
||||||
self.level.removeTileEntitiesInBox(self._dirtyBox)
|
|
||||||
|
|
||||||
if self.brushMode.name == "Flood Fill":
|
|
||||||
i = self.level.copyBlocksFromIter(self.undoSchematic,
|
|
||||||
self.undoSchematic.bounds,
|
|
||||||
self.undoSchematic.bounds.origin
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
i = self.level.copyBlocksFromIter(self.undoSchematic,
|
|
||||||
BoundingBox((0, 0, 0), self._dirtyBox.size),
|
|
||||||
self._dirtyBox.origin
|
|
||||||
)
|
|
||||||
|
|
||||||
showProgress("Undoing brush...", i)
|
|
||||||
self.editor.invalidateChunks(self.undoSchematic.allChunks)
|
|
||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.undoSchematic = self.extractUndoSchematicFrom(self.level, self._dirtyBox)
|
self.undoLevel = self.extractUndo(self.level, self._dirtyBox)
|
||||||
|
|
||||||
def _perform():
|
def _perform():
|
||||||
yield 0, len(self.points), "Applying {0} brush...".format(self.brushMode.name)
|
yield 0, len(self.points), "Applying {0} brush...".format(self.brushMode.name)
|
||||||
@ -849,8 +828,9 @@ class BrushTool(CloneTool):
|
|||||||
self.draggedPositions = self.draggedPositions[-1:]
|
self.draggedPositions = self.draggedPositions[-1:]
|
||||||
|
|
||||||
op = BrushOperation(self.editor,
|
op = BrushOperation(self.editor,
|
||||||
self.draggedPositions,
|
self.editor.level,
|
||||||
self.getBrushOptions())
|
self.draggedPositions,
|
||||||
|
self.getBrushOptions())
|
||||||
self.performWithRetry(op)
|
self.performWithRetry(op)
|
||||||
|
|
||||||
box = op.dirtyBox()
|
box = op.dirtyBox()
|
||||||
|
@ -79,14 +79,14 @@ class CoordsInput(Widget):
|
|||||||
|
|
||||||
class BlockCopyOperation(Operation):
|
class BlockCopyOperation(Operation):
|
||||||
def __init__(self, editor, sourceLevel, sourceBox, destLevel, destPoint, copyAir, copyWater):
|
def __init__(self, editor, sourceLevel, sourceBox, destLevel, destPoint, copyAir, copyWater):
|
||||||
self.editor = editor
|
super(BlockCopyOperation, self).__init__(editor, destLevel)
|
||||||
self.sourceLevel = sourceLevel
|
self.sourceLevel = sourceLevel
|
||||||
self.sourceBox = sourceBox
|
self.sourceBox = sourceBox
|
||||||
self.destLevel = destLevel
|
|
||||||
self.destPoint = Vector(*destPoint)
|
self.destPoint = Vector(*destPoint)
|
||||||
self.copyAir = copyAir
|
self.copyAir = copyAir
|
||||||
self.copyWater = copyWater
|
self.copyWater = copyWater
|
||||||
self.sourceBox, self.destPoint = block_copy.adjustCopyParameters(self.destLevel, self.sourceLevel, self.sourceBox, self.destPoint)
|
self.sourceBox, self.destPoint = block_copy.adjustCopyParameters(self.level, self.sourceLevel, self.sourceBox,
|
||||||
|
self.destPoint)
|
||||||
|
|
||||||
def dirtyBox(self):
|
def dirtyBox(self):
|
||||||
return BoundingBox(self.destPoint, self.sourceBox.size)
|
return BoundingBox(self.destPoint, self.sourceBox.size)
|
||||||
@ -94,16 +94,12 @@ class BlockCopyOperation(Operation):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return "Copy {0} blocks".format(self.sourceBox.volume)
|
return "Copy {0} blocks".format(self.sourceBox.volume)
|
||||||
|
|
||||||
def recordUndo(self):
|
|
||||||
self.undoSchematic = self.extractUndoSchematicFrom(self.destLevel, BoundingBox(self.destPoint, self.sourceBox.size))
|
|
||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
dirtyBox = self.dirtyBox()
|
|
||||||
sourceBox = self.sourceBox
|
sourceBox = self.sourceBox
|
||||||
destBox = BoundingBox(self.destPoint, sourceBox.size)
|
|
||||||
|
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.recordUndo()
|
self.undoLevel = self.extractUndo(self.level, BoundingBox(self.destPoint, self.sourceBox.size))
|
||||||
|
|
||||||
|
|
||||||
blocksToCopy = None
|
blocksToCopy = None
|
||||||
if not (self.copyAir and self.copyWater):
|
if not (self.copyAir and self.copyWater):
|
||||||
@ -116,24 +112,17 @@ class BlockCopyOperation(Operation):
|
|||||||
blocksToCopy.remove(9)
|
blocksToCopy.remove(9)
|
||||||
|
|
||||||
with setWindowCaption("Copying - "):
|
with setWindowCaption("Copying - "):
|
||||||
i = self.destLevel.copyBlocksFromIter(self.sourceLevel, self.sourceBox, self.destPoint, blocksToCopy, create=True)
|
i = self.level.copyBlocksFromIter(self.sourceLevel, self.sourceBox, self.destPoint, blocksToCopy, create=True)
|
||||||
showProgress("Copying {0:n} blocks...".format(self.sourceBox.volume), i)
|
showProgress("Copying {0:n} blocks...".format(self.sourceBox.volume), i)
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
if self.undoSchematic:
|
|
||||||
self.destLevel.removeEntitiesInBox(BoundingBox(self.destPoint, self.sourceBox.size))
|
|
||||||
self.destLevel.removeTileEntitiesInBox(BoundingBox(self.destPoint, self.sourceBox.size))
|
|
||||||
|
|
||||||
with setWindowCaption("Undoing - "):
|
|
||||||
i = self.destLevel.copyBlocksFromIter(self.undoSchematic, BoundingBox((0, 0, 0), self.sourceBox.size), self.destPoint, create=True)
|
|
||||||
showProgress("Copying {0:n} blocks...".format(self.sourceBox.volume), i)
|
|
||||||
|
|
||||||
def bufferSize(self):
|
def bufferSize(self):
|
||||||
return 123456
|
return 123456
|
||||||
|
|
||||||
|
|
||||||
class CloneOperation (Operation):
|
class CloneOperation(Operation):
|
||||||
def __init__(self, editor, sourceLevel, sourceBox, originSourceBox, destLevel, destPoint, copyAir, copyWater, repeatCount):
|
def __init__(self, editor, sourceLevel, sourceBox, originSourceBox, destLevel, destPoint, copyAir, copyWater, repeatCount):
|
||||||
|
super(CloneOperation, self).__init__(editor, destLevel)
|
||||||
|
|
||||||
self.blockCopyOps = []
|
self.blockCopyOps = []
|
||||||
dirtyBoxes = []
|
dirtyBoxes = []
|
||||||
if repeatCount > 1: # clone tool only
|
if repeatCount > 1: # clone tool only
|
||||||
|
@ -20,8 +20,7 @@ FillSettings.chooseBlockImmediately = FillSettings("Choose Block Immediately", T
|
|||||||
|
|
||||||
class BlockFillOperation(Operation):
|
class BlockFillOperation(Operation):
|
||||||
def __init__(self, editor, destLevel, destBox, blockInfo, blocksToReplace):
|
def __init__(self, editor, destLevel, destBox, blockInfo, blocksToReplace):
|
||||||
self.editor = editor
|
super(BlockFillOperation, self).__init__(editor, destLevel)
|
||||||
self.destLevel = destLevel
|
|
||||||
self.destBox = destBox
|
self.destBox = destBox
|
||||||
self.blockInfo = blockInfo
|
self.blockInfo = blockInfo
|
||||||
self.blocksToReplace = blocksToReplace
|
self.blocksToReplace = blocksToReplace
|
||||||
@ -31,23 +30,15 @@ class BlockFillOperation(Operation):
|
|||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.undoSchematic = self.extractUndoSchematicFrom(self.destLevel, self.destBox)
|
self.undoLevel = self.extractUndo(self.level, self.destBox)
|
||||||
|
|
||||||
destBox = self.destBox
|
destBox = self.destBox
|
||||||
if self.destLevel.bounds == self.destBox:
|
if self.level.bounds == self.destBox:
|
||||||
destBox = None
|
destBox = None
|
||||||
|
|
||||||
fill = self.destLevel.fillBlocksIter(destBox, self.blockInfo, blocksToReplace=self.blocksToReplace)
|
fill = self.level.fillBlocksIter(destBox, self.blockInfo, blocksToReplace=self.blocksToReplace)
|
||||||
showProgress("Replacing blocks...", fill, cancel=True)
|
showProgress("Replacing blocks...", fill, cancel=True)
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
if self.undoSchematic:
|
|
||||||
self.destLevel.removeEntitiesInBox(self.destBox)
|
|
||||||
self.destLevel.removeTileEntitiesInBox(self.destBox)
|
|
||||||
with setWindowCaption("Undoing - "):
|
|
||||||
i = self.destLevel.copyBlocksFromIter(self.undoSchematic, BoundingBox((0, 0, 0), self.destBox.size), self.destBox.origin)
|
|
||||||
showProgress("Copying {0:n} blocks...".format(self.destBox.volume), i)
|
|
||||||
|
|
||||||
def bufferSize(self):
|
def bufferSize(self):
|
||||||
return self.destBox.volume * 2
|
return self.destBox.volume * 2
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ class FilterModuleOptions(Widget):
|
|||||||
self.pages = pages
|
self.pages = pages
|
||||||
self.optionDict = {}
|
self.optionDict = {}
|
||||||
pageTabContents = []
|
pageTabContents = []
|
||||||
|
|
||||||
print "Creating options for ", module
|
print "Creating options for ", module
|
||||||
if hasattr(module, "inputs"):
|
if hasattr(module, "inputs"):
|
||||||
if isinstance(module.inputs, list):
|
if isinstance(module.inputs, list):
|
||||||
for tabData in module.inputs:
|
for tabData in module.inputs:
|
||||||
title, page, pageRect = self.makeTabPage(self.tool, tabData)
|
title, page, pageRect = self.makeTabPage(self.tool, tabData)
|
||||||
pages.add_page(title, page)
|
pages.add_page(title, page)
|
||||||
pages.set_rect(pageRect.union(pages._rect))
|
pages.set_rect(pageRect.union(pages._rect))
|
||||||
elif isinstance(module.inputs, tuple):
|
elif isinstance(module.inputs, tuple):
|
||||||
title, page, pageRect = self.makeTabPage(self.tool, module.inputs)
|
title, page, pageRect = self.makeTabPage(self.tool, module.inputs)
|
||||||
pages.add_page(title, page)
|
pages.add_page(title, page)
|
||||||
@ -75,7 +75,7 @@ class FilterModuleOptions(Widget):
|
|||||||
if(pages.current_page != None):
|
if(pages.current_page != None):
|
||||||
pages.show_page(pages.current_page)
|
pages.show_page(pages.current_page)
|
||||||
else:
|
else:
|
||||||
pages.show_page(pages.pages[0])
|
pages.show_page(pages.pages[0])
|
||||||
|
|
||||||
for eachPage in pages.pages:
|
for eachPage in pages.pages:
|
||||||
self.optionDict = dict(self.optionDict.items() + eachPage.optionDict.items())
|
self.optionDict = dict(self.optionDict.items() + eachPage.optionDict.items())
|
||||||
@ -109,7 +109,7 @@ class FilterModuleOptions(Widget):
|
|||||||
if a == "strValSize":
|
if a == "strValSize":
|
||||||
field = TextField(value=b, width=c)
|
field = TextField(value=b, width=c)
|
||||||
page.optionDict[optionName] = AttrRef(field, 'value')
|
page.optionDict[optionName] = AttrRef(field, 'value')
|
||||||
|
|
||||||
row = Row((Label(optionName), field))
|
row = Row((Label(optionName), field))
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
else:
|
else:
|
||||||
@ -145,7 +145,7 @@ class FilterModuleOptions(Widget):
|
|||||||
|
|
||||||
row = Row((Label(optionName), cbox))
|
row = Row((Label(optionName), cbox))
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
elif isinstance(optionType, (int, float)):
|
elif isinstance(optionType, (int, float)):
|
||||||
rows.append(addNumField(self, optionName, optionType))
|
rows.append(addNumField(self, optionName, optionType))
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ class FilterModuleOptions(Widget):
|
|||||||
elif optionType == "string":
|
elif optionType == "string":
|
||||||
field = TextField(value="Input String Here", width=200)
|
field = TextField(value="Input String Here", width=200)
|
||||||
page.optionDict[optionName] = AttrRef(field, 'value')
|
page.optionDict[optionName] = AttrRef(field, 'value')
|
||||||
|
|
||||||
row = Row((Label(optionName), field))
|
row = Row((Label(optionName), field))
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
@ -278,29 +278,20 @@ class FilterToolPanel(Panel):
|
|||||||
|
|
||||||
|
|
||||||
class FilterOperation(Operation):
|
class FilterOperation(Operation):
|
||||||
def __init__(self, level, box, filter, options):
|
def __init__(self, editor, level, box, filter, options):
|
||||||
|
super(FilterOperation, self).__init__(editor, level)
|
||||||
self.box = box
|
self.box = box
|
||||||
self.level = level
|
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.recordUndo()
|
self.undoLevel = self.extractUndo(self.level, self.box)
|
||||||
|
|
||||||
self.filter.perform(self.level, BoundingBox(self.box), self.options)
|
self.filter.perform(self.level, BoundingBox(self.box), self.options)
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def recordUndo(self):
|
|
||||||
self.undoSchematic = self.extractUndoSchematicFrom(self.level, self.box)
|
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
if self.undoSchematic:
|
|
||||||
self.level.removeEntitiesInBox(self.box)
|
|
||||||
self.level.removeTileEntitiesInBox(self.box)
|
|
||||||
self.level.copyBlocksFrom(self.undoSchematic, BoundingBox((0, 0, 0), self.box.size), self.box.origin)
|
|
||||||
|
|
||||||
def dirtyBox(self):
|
def dirtyBox(self):
|
||||||
return self.box
|
return self.box
|
||||||
|
|
||||||
@ -370,7 +361,7 @@ class FilterTool(EditorTool):
|
|||||||
with setWindowCaption("APPLYING FILTER - "):
|
with setWindowCaption("APPLYING FILTER - "):
|
||||||
filterModule = self.filterModules[self.panel.filterSelect.selectedChoice]
|
filterModule = self.filterModules[self.panel.filterSelect.selectedChoice]
|
||||||
|
|
||||||
op = FilterOperation(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.performWithRetry(op)
|
||||||
|
@ -24,9 +24,11 @@ class PlayerMoveOperation(Operation):
|
|||||||
undoPos = None
|
undoPos = None
|
||||||
|
|
||||||
def __init__(self, tool, pos, player="Player", yp=(None, None)):
|
def __init__(self, tool, pos, player="Player", yp=(None, None)):
|
||||||
self.tool, self.pos = tool, pos
|
super(PlayerMoveOperation, self).__init__(tool.editor, tool.editor.level)
|
||||||
self.yp = yp
|
self.tool = tool
|
||||||
|
self.pos = pos
|
||||||
self.player = player
|
self.player = player
|
||||||
|
self.yp = yp
|
||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
try:
|
try:
|
||||||
|
@ -191,9 +191,10 @@ class SelectionToolPanel(Panel):
|
|||||||
self.shrink_wrap()
|
self.shrink_wrap()
|
||||||
|
|
||||||
|
|
||||||
class NudgeBlocksOperation (Operation):
|
class NudgeBlocksOperation(Operation):
|
||||||
def __init__(self, editor, sourceBox, direction):
|
def __init__(self, editor, level, sourceBox, direction):
|
||||||
self.editor = editor
|
super(NudgeBlocksOperation, self).__init__(editor, level)
|
||||||
|
|
||||||
self.sourceBox = sourceBox
|
self.sourceBox = sourceBox
|
||||||
self.destBox = BoundingBox(sourceBox.origin + direction, sourceBox.size)
|
self.destBox = BoundingBox(sourceBox.origin + direction, sourceBox.size)
|
||||||
self.nudgeSelection = NudgeSelectionOperation(editor.selectionTool, direction)
|
self.nudgeSelection = NudgeSelectionOperation(editor.selectionTool, direction)
|
||||||
@ -207,7 +208,7 @@ class NudgeBlocksOperation (Operation):
|
|||||||
if tempSchematic:
|
if tempSchematic:
|
||||||
dirtyBox = self.dirtyBox()
|
dirtyBox = self.dirtyBox()
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.undoSchematic = self.extractUndoSchematicFrom(level, dirtyBox)
|
self.undoLevel = self.extractUndo(level, dirtyBox)
|
||||||
|
|
||||||
level.fillBlocks(self.sourceBox, level.materials.Air)
|
level.fillBlocks(self.sourceBox, level.materials.Air)
|
||||||
level.removeTileEntitiesInBox(self.sourceBox)
|
level.removeTileEntitiesInBox(self.sourceBox)
|
||||||
@ -221,12 +222,8 @@ class NudgeBlocksOperation (Operation):
|
|||||||
self.nudgeSelection.perform(recordUndo)
|
self.nudgeSelection.perform(recordUndo)
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
if self.undoSchematic:
|
super(NudgeBlocksOperation, self).undo()
|
||||||
self.editor.level.removeTileEntitiesInBox(self.destBox)
|
self.nudgeSelection.undo()
|
||||||
self.editor.level.removeEntitiesInBox(self.destBox)
|
|
||||||
self.editor.level.copyBlocksFrom(self.undoSchematic, self.undoSchematic.bounds, self.dirtyBox().origin)
|
|
||||||
self.editor.invalidateBox(self.dirtyBox())
|
|
||||||
self.nudgeSelection.undo()
|
|
||||||
|
|
||||||
|
|
||||||
class SelectionTool(EditorTool):
|
class SelectionTool(EditorTool):
|
||||||
@ -388,7 +385,7 @@ class SelectionTool(EditorTool):
|
|||||||
def nudgeBlocks(self, dir):
|
def nudgeBlocks(self, dir):
|
||||||
if key.get_mods() & KMOD_SHIFT:
|
if key.get_mods() & KMOD_SHIFT:
|
||||||
dir = dir * (16, 16, 16)
|
dir = dir * (16, 16, 16)
|
||||||
op = NudgeBlocksOperation(self.editor, self.selectionBox(), dir)
|
op = NudgeBlocksOperation(self.editor, self.editor.level, self.selectionBox(), dir)
|
||||||
|
|
||||||
self.performWithRetry(op)
|
self.performWithRetry(op)
|
||||||
self.editor.addOperation(op)
|
self.editor.addOperation(op)
|
||||||
@ -1018,7 +1015,7 @@ class SelectionTool(EditorTool):
|
|||||||
level.addEntities(self.undoEntities)
|
level.addEntities(self.undoEntities)
|
||||||
editor.renderer.invalidateEntitiesInBox(box)
|
editor.renderer.invalidateEntitiesInBox(box)
|
||||||
|
|
||||||
op = DeleteEntitiesOperation()
|
op = DeleteEntitiesOperation(self.editor, self.editor.level)
|
||||||
self.performWithRetry(op, recordUndo)
|
self.performWithRetry(op, recordUndo)
|
||||||
if recordUndo:
|
if recordUndo:
|
||||||
self.editor.addOperation(op)
|
self.editor.addOperation(op)
|
||||||
@ -1091,6 +1088,7 @@ class SelectionOperation(Operation):
|
|||||||
changedLevel = False
|
changedLevel = False
|
||||||
|
|
||||||
def __init__(self, selectionTool, points):
|
def __init__(self, selectionTool, points):
|
||||||
|
super(SelectionOperation, self).__init__(selectionTool.editor, selectionTool.editor.level)
|
||||||
self.selectionTool = selectionTool
|
self.selectionTool = selectionTool
|
||||||
self.points = points
|
self.points = points
|
||||||
|
|
||||||
@ -1105,14 +1103,14 @@ class SelectionOperation(Operation):
|
|||||||
self.points = points
|
self.points = points
|
||||||
|
|
||||||
|
|
||||||
class NudgeSelectionOperation (Operation):
|
class NudgeSelectionOperation(Operation):
|
||||||
changedLevel = False
|
changedLevel = False
|
||||||
|
|
||||||
def __init__(self, selectionTool, direction):
|
def __init__(self, selectionTool, direction):
|
||||||
|
super(NudgeSelectionOperation, self).__init__(selectionTool.editor, selectionTool.editor.level)
|
||||||
self.selectionTool = selectionTool
|
self.selectionTool = selectionTool
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.oldPoints = selectionTool.getSelectionPoints()
|
self.oldPoints = selectionTool.getSelectionPoints()
|
||||||
|
|
||||||
self.newPoints = [p + direction for p in self.oldPoints]
|
self.newPoints = [p + direction for p in self.oldPoints]
|
||||||
|
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
|
@ -11,6 +11,9 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE."""
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE."""
|
||||||
|
import atexit
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from OpenGL.GL import *
|
from OpenGL.GL import *
|
||||||
from pymclevel import *
|
from pymclevel import *
|
||||||
@ -96,19 +99,27 @@ class NudgeButton(GLBackground):
|
|||||||
|
|
||||||
class Operation(object):
|
class Operation(object):
|
||||||
changedLevel = True
|
changedLevel = True
|
||||||
|
undoLevel = None
|
||||||
|
|
||||||
def extractUndoSchematicFrom(self, level, box):
|
def __init__(self, editor, level):
|
||||||
if box.volume > 131072:
|
self.editor = editor
|
||||||
sch = showProgress("Recording undo...", level.extractAnySchematicIter(box), cancel=True)
|
self.level = level
|
||||||
else:
|
|
||||||
sch = level.extractAnySchematic(box)
|
|
||||||
|
|
||||||
if sch == "Canceled":
|
def extractUndo(self, level, box):
|
||||||
raise Cancel
|
undoPath = tempfile.mkdtemp("mceditundo")
|
||||||
if sch is None:
|
undoLevel = MCInfdevOldLevel(undoPath, create=True)
|
||||||
sch = MCSchematic((0, 0, 0))
|
atexit.register(shutil.rmtree, undoPath, True)
|
||||||
|
|
||||||
return sch
|
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
|
# represents a single undoable operation
|
||||||
def perform(self, recordUndo=True):
|
def perform(self, recordUndo=True):
|
||||||
@ -116,9 +127,21 @@ class Operation(object):
|
|||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
""" Undo the operation. Ought to leave the Operation in a state where it can be performed again.
|
""" Undo the operation. Ought to leave the Operation in a state where it can be performed again.
|
||||||
Returns a BoundingBox containing all of the modified areas of the level. """
|
Default implementation copies all chunks in undoLevel back into level. Non-chunk-based operations
|
||||||
pass
|
should override this."""
|
||||||
undoSchematic = None
|
|
||||||
|
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):
|
def dirtyBox(self):
|
||||||
""" The region modified by the operation.
|
""" The region modified by the operation.
|
||||||
|
Reference in New Issue
Block a user