From f0145de3d33ded851c963bd54bdcf8ba1dd0ad91 Mon Sep 17 00:00:00 2001 From: David Vierra Date: Wed, 7 Oct 2015 01:29:55 -1000 Subject: [PATCH] Painfully fixed recursion depth error when undoing Move Finish commands. This is very, very unsatisfactory. It isn't clear which object is the definitive source for a pending import's position, transformed or not. --- src/mcedit2/editorsession.py | 15 +++++++- src/mcedit2/editortools/move.py | 65 ++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/mcedit2/editorsession.py b/src/mcedit2/editorsession.py index abf29c5..2b88699 100644 --- a/src/mcedit2/editorsession.py +++ b/src/mcedit2/editorsession.py @@ -141,6 +141,13 @@ class PendingImport(object): return self.pos return self.pos + self.transformedDim.bounds.origin - self.selection.origin + @importPos.setter + def importPos(self, pos): + if self.transformedDim is None: + self.pos = pos + else: + self.pos = pos - self.transformedDim.bounds.origin + self.selection.origin + @property def importDim(self): if self.transformedDim is not None: @@ -179,8 +186,14 @@ class PendingImport(object): @property def bounds(self): return BoundingBox(self.pos, self.selection.size) - #return BoundingBox(self.pos, self.sourceDim.bounds.size) + @property + def importBounds(self): + if self.transformedDim is not None: + size = self.transformedDim.bounds.size + else: + size = self.selection.size + return BoundingBox(self.importPos, size) class PasteImportCommand(QtGui.QUndoCommand): def __init__(self, editorSession, pendingImport, text, *args, **kwargs): diff --git a/src/mcedit2/editortools/move.py b/src/mcedit2/editortools/move.py index 7903b31..248f135 100644 --- a/src/mcedit2/editortools/move.py +++ b/src/mcedit2/editortools/move.py @@ -51,7 +51,6 @@ class MoveSelectionCommand(SimpleRevisionCommand): class MoveOffsetCommand(QtGui.QUndoCommand): - def __init__(self, moveTool, oldPoint, newPoint): super(MoveOffsetCommand, self).__init__() self.setText(moveTool.tr("Move Object")) @@ -80,7 +79,7 @@ class MoveFinishCommand(SimpleRevisionCommand): def redo(self): super(MoveFinishCommand, self).redo() self.previousSelection = self.editorSession.currentSelection - self.editorSession.currentSelection = self.pendingImport.bounds + self.editorSession.currentSelection = self.pendingImport.importBounds self.moveTool.removePendingImport(self.pendingImport) @@ -128,6 +127,10 @@ class PendingImportNode(Node, QtCore.QObject): self.pendingImport = pendingImport dim = pendingImport.sourceDim + # positionTranslateNode contains the non-transformed preview of the imported + # object, including its world scene. This preview will be rotated model-wise + # while the user is dragging the rotate controls. + self.positionTranslateNode = TranslateNode() self.rotateNode = Rotate3DNode() self.addChild(self.positionTranslateNode) @@ -135,10 +138,18 @@ class PendingImportNode(Node, QtCore.QObject): self.rotateNode.setAnchor(self.pendingImport.bounds.size * 0.5) + # worldSceneTranslateNode is contained by positionTranslateNode, and + # serves to translate the world scene back to 0, 0, 0 so the positionTranslateNode + # can translate by the current position. + self.worldSceneTranslateNode = TranslateNode() self.worldScene = WorldScene(dim, textureAtlas, bounds=pendingImport.selection) self.worldScene.depthOffsetNode.depthOffset = DepthOffset.PreviewRenderer + # transformedWorldTranslateNode contains the transformed preview of the imported + # object, including a world scene that displays the object wrapped by a + # DimensionTransform. + self.transformedWorldTranslateNode = TranslateNode() self.transformedWorldScene = None self.addChild(self.transformedWorldTranslateNode) @@ -147,31 +158,46 @@ class PendingImportNode(Node, QtCore.QObject): self.worldSceneTranslateNode.addChild(self.worldScene) self.rotateNode.addChild(self.worldSceneTranslateNode) - box = BoundingBox(self.pos, pendingImport.bounds.size) + # handleNode displays a bounding box that can be moved around, and responds + # to mouse events. + + box = BoundingBox(pendingImport.importPos, pendingImport.importBounds.size) self.handleNode = BoxHandle() self.handleNode.bounds = box self.handleNode.resizable = False + + self.updateTransformedScene() + self.pos = pendingImport.pos + self.handleNode.boundsChanged.connect(self.handleBoundsChanged) self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone) self.addChild(self.handleNode) - self.pos = pendingImport.pos - + # loads the non-transformed world scene asynchronously. self.loader = WorldLoader(self.worldScene, list(pendingImport.selection.chunkPositions())) self.loader.startLoader() - def handleBoundsChanged(self, bounds): - self.pos = bounds.origin - - # newPos, oldPos + # Emitted when the user finishes dragging the box handle and releases the mouse + # button. Arguments are (newPosition, oldPosition). importMoved = QtCore.Signal(object, object) def handleBoundsChangedDone(self, bounds, oldBounds): - if bounds.origin != oldBounds.origin: - self.importMoved.emit(bounds.origin, oldBounds.origin) + point = self.getPosFromBox(bounds.origin) + oldPoint = self.getPosFromBox(oldBounds.origin) + if point != oldPoint: + self.importMoved.emit(point, oldPoint) + + def handleBoundsChanged(self, bounds): + point = self.getPosFromBox(bounds.origin) + if self.pos != point: + self.pos = point + + def getPosFromBox(self, point): + offset = self.pendingImport.pos - self.pendingImport.importPos + return point + offset def setPreviewRotation(self, rots): self.rotateNode.visible = True @@ -182,9 +208,11 @@ class PendingImportNode(Node, QtCore.QObject): def setRotation(self, rots): self.pendingImport.rotation = rots self.updateTransformedScene() + self.updateBoxHandle() def updateTransformedScene(self): if self.pendingImport.transformedDim is not None: + log.info("Showing transformed scene") self.rotateNode.visible = False self.worldSceneTranslateNode.visible = False self.transformedWorldTranslateNode.visible = True @@ -205,6 +233,7 @@ class PendingImportNode(Node, QtCore.QObject): self.loader.startLoader() else: + log.info("Hiding transformed scene") self.rotateNode.visible = True self.worldSceneTranslateNode.visible = True self.transformedWorldTranslateNode.visible = False @@ -224,10 +253,17 @@ class PendingImportNode(Node, QtCore.QObject): if value == self.positionTranslateNode.translateOffset: return - self.positionTranslateNode.translateOffset = value + self.positionTranslateNode.translateOffset = Vector(*value) self.updateTransformedSceneOffset() - - bounds = BoundingBox(value, self.pendingImport.bounds.size) + self.updateBoxHandle() + + def updateBoxHandle(self): + if self.transformedWorldScene is None: + bounds = BoundingBox(self.pos, self.pendingImport.bounds.size) + else: + origin = self.pos - self.pendingImport.pos + self.pendingImport.importPos + bounds = BoundingBox(origin, self.pendingImport.importBounds.size) + #if self.handleNode.bounds.size != bounds.size: self.handleNode.bounds = bounds # --- Mouse events --- @@ -242,6 +278,7 @@ class PendingImportNode(Node, QtCore.QObject): def mouseRelease(self, event): self.handleNode.mouseRelease(event) + class RotationWidget(QtGui.QWidget): def __init__(self): super(RotationWidget, self).__init__()