示例#1
0
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.toolWidget.setLayout(
            Column(self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
示例#2
0
文件: select.py 项目: wcpe/mcedit2
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.optionsButton = QtGui.QPushButton(self.tr("Options"))

        self.optionsMenu = QtGui.QMenu()
        self.optionsButton.setMenu(self.optionsMenu)

        classicSelectionAction = self.optionsMenu.addAction(
            self.tr("Classic Selection"))
        stickySelectionAction = self.optionsMenu.addAction(
            self.tr("Sticky Selection"))

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(
            Column(self.optionsButton, self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node("selectOverlay")
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        classicSelectionAction.setCheckable(True)
        classicSelectionAction.toggled.connect(ClassicSelectionOption.setValue)
        classicSelectionAction.setChecked(ClassicSelectionOption.value())
        ClassicSelectionOption.connectAndCall(self.setClassicSelection)

        stickySelectionAction.setCheckable(True)
        stickySelectionAction.toggled.connect(StickySelectionOption.setValue)
        stickySelectionAction.setChecked(StickySelectionOption.value())
        StickySelectionOption.connectAndCall(self.setStickySelection)

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)
示例#3
0
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.deselectButton = QtGui.QPushButton(self.tr("Deselect"))
        self.deselectButton.clicked.connect(self.deselect)
        self.deleteSelectionButton = QtGui.QPushButton(self.tr("Delete"))
        self.deleteSelectionButton.clicked.connect(self.deleteSelection)
        self.deleteBlocksButton = QtGui.QPushButton(self.tr("Delete Blocks"))
        self.deleteBlocksButton.clicked.connect(self.deleteBlocks)
        self.deleteEntitiesButton = QtGui.QPushButton(self.tr("Delete Entities"))
        self.deleteEntitiesButton.clicked.connect(self.deleteEntities)
        self.fillButton = QtGui.QPushButton(self.tr("Fill"))
        self.fillButton.clicked.connect(self.fill)
        self.replaceButton = QtGui.QPushButton(self.tr("Replace"))
        self.replaceButton.clicked.connect(self.replace)

        self.toolWidget.setLayout(Column(self.coordInput,
                                         self.shapeInput,
                                         self.deselectButton,
                                         self.deleteSelectionButton,
                                         self.deleteBlocksButton,
                                         self.deleteEntitiesButton,
                                         self.fillButton,
                                         self.replaceButton,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.selectionNode.dimension = editorSession.currentDimension  # xxx dimensionDidChange
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None
示例#4
0
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.toolWidget.setLayout(Column(self.coordInput,
                                         self.shapeInput,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
示例#5
0
文件: select.py 项目: qtx0213/mcedit2
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.optionsButton = QtGui.QPushButton(self.tr("Options"))

        self.optionsMenu = QtGui.QMenu()
        self.optionsButton.setMenu(self.optionsMenu)
        
        classicSelectionAction = self.optionsMenu.addAction(self.tr("Classic Selection"))
        stickySelectionAction = self.optionsMenu.addAction(self.tr("Sticky Selection"))

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(Column(self.optionsButton,
                                         self.coordInput,
                                         self.shapeInput,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node("selectOverlay")
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        classicSelectionAction.setCheckable(True)
        classicSelectionAction.toggled.connect(ClassicSelectionOption.setValue)
        classicSelectionAction.setChecked(ClassicSelectionOption.value())
        ClassicSelectionOption.connectAndCall(self.setClassicSelection)

        stickySelectionAction.setCheckable(True)
        stickySelectionAction.toggled.connect(StickySelectionOption.setValue)
        stickySelectionAction.setChecked(StickySelectionOption.value())
        StickySelectionOption.connectAndCall(self.setStickySelection)

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)
示例#6
0
    def createToolWidget(self):
        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [TreeGen()]
        self.currentType = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        for gt in self.generatorTypes:
            self.generatorTypeInput.addItem(gt.displayName, gt)

        self.generatorTypeInput.currentIndexChanged.connect(
            self.generatorTypeChanged)
        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                         QtGui.QSizePolicy.Expanding)

        column.append(self.generatorTypeInput)
        column.append(self.optionsHolder)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenegraph.Node()

        self.sceneHolderNode = scenegraph.TranslateNode()
        self.overlayNode.addChild(self.sceneHolderNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None

        self.schematicBounds = None
示例#7
0
    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.livePreview = False
        self.blockPreview = False
        self.glPreview = True

        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [pluginClass(self) for pluginClass in _pluginClasses]
        self.currentGenerator = None
        if len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        self.generatorTypesChanged()

        self.generatorTypeInput.currentIndexChanged.connect(self.currentTypeChanged)

        self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview")
        self.livePreviewCheckbox.setChecked(self.livePreview)
        self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled)

        self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview")
        self.blockPreviewCheckbox.setChecked(self.blockPreview)
        self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled)

        self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview")
        self.glPreviewCheckbox.setChecked(self.glPreview)
        self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled)

        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)

        self.generateButton = QtGui.QPushButton(self.tr("Generate"))
        self.generateButton.clicked.connect(self.generateClicked)

        column.append(self.generatorTypeInput)
        column.append(self.livePreviewCheckbox)
        column.append(self.blockPreviewCheckbox)
        column.append(self.glPreviewCheckbox)
        column.append(self.optionsHolder)
        column.append(self.generateButton)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenegraph.Node()

        self.sceneHolderNode = scenegraph.TranslateNode()
        self.overlayNode.addChild(self.sceneHolderNode)

        self.previewNode = None

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None
        self.loader = None

        self.previewBounds = None
        self.schematicBounds = None
        self.currentSchematic = None

        self.currentTypeChanged(0)

        # Name of last selected generator plugin is saved after unloading
        # so it can be reselected if it is immediately reloaded
        self._lastTypeName = None

        _GeneratePlugins.instance.pluginAdded.connect(self.addPlugin)
        _GeneratePlugins.instance.pluginRemoved.connect(self.removePlugin)
示例#8
0
class GenerateTool(EditorTool):
    name = "Generate"
    iconName = "generate"

    instantDisplayChunks = 32

    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.livePreview = False
        self.blockPreview = False
        self.glPreview = True

        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [pluginClass(self) for pluginClass in _pluginClasses]
        self.currentGenerator = None
        if len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        self.generatorTypesChanged()

        self.generatorTypeInput.currentIndexChanged.connect(self.currentTypeChanged)

        self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview")
        self.livePreviewCheckbox.setChecked(self.livePreview)
        self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled)

        self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview")
        self.blockPreviewCheckbox.setChecked(self.blockPreview)
        self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled)

        self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview")
        self.glPreviewCheckbox.setChecked(self.glPreview)
        self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled)

        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)

        self.generateButton = QtGui.QPushButton(self.tr("Generate"))
        self.generateButton.clicked.connect(self.generateClicked)

        column.append(self.generatorTypeInput)
        column.append(self.livePreviewCheckbox)
        column.append(self.blockPreviewCheckbox)
        column.append(self.glPreviewCheckbox)
        column.append(self.optionsHolder)
        column.append(self.generateButton)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenegraph.Node()

        self.sceneHolderNode = scenegraph.TranslateNode()
        self.overlayNode.addChild(self.sceneHolderNode)

        self.previewNode = None

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None
        self.loader = None

        self.previewBounds = None
        self.schematicBounds = None
        self.currentSchematic = None

        self.currentTypeChanged(0)

        # Name of last selected generator plugin is saved after unloading
        # so it can be reselected if it is immediately reloaded
        self._lastTypeName = None

        _GeneratePlugins.instance.pluginAdded.connect(self.addPlugin)
        _GeneratePlugins.instance.pluginRemoved.connect(self.removePlugin)

    def removePlugin(self, cls):
        self.generatorTypes[:] = [gt for gt in self.generatorTypes if not isinstance(gt, cls)]
        self.generatorTypesChanged()
        if self.currentGenerator not in self.generatorTypes:
            lastTypeName = self.currentGenerator.__class__.__name__
            self.currentTypeChanged(0)  # resets self._lastTypeName
            self._lastTypeName = lastTypeName

    def addPlugin(self, cls):
        self.generatorTypes.append(cls(self))
        self.generatorTypesChanged()
        if self._lastTypeName is not None:
            if cls.__name__ == self._lastTypeName:
                self.currentTypeChanged(len(self.generatorTypes)-1)

    def generatorTypesChanged(self):
        for gt in self.generatorTypes:
            if hasattr(gt, 'displayName'):
                displayName = gt.displayName
            else:
                displayName = gt.__class__.__name__
            self.generatorTypeInput.addItem(displayName, gt)


    def livePreviewToggled(self, value):
        self.livePreview = value

    def blockPreviewToggled(self, value):
        self.blockPreview = value
        if value:
            if self.currentSchematic:
                self.displaySchematic(self.currentSchematic, self.schematicBounds.origin)
            else:
                self.updateBlockPreview()
        else:
            self.clearSchematic()

    def glPreviewToggled(self, value):
        self.glPreview = value
        if value:
            self.updateNodePreview()  # xxx cache previewNode?
        else:
            self.clearNode()

    def currentTypeChanged(self, index):
        # user selected generator type after old type was unloaded, so forget the old type
        self._lastTypeName = None

        self.optionsHolder.removeWidget(self.optionsHolder.widget(0))
        if index < len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[index]
            self.optionsHolder.addWidget(self.currentGenerator.getOptionsWidget())
            self.updatePreview()
        else:
            self.currentGenerator = None
            self.clearSchematic()
            self.clearNode()

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    def boundsDidChange(self, bounds):
        # box still being resized
        if not self.currentGenerator:
            return

        if not self.livePreview:
            return

        self.previewBounds = bounds
        self.currentGenerator.boundsChanged(bounds)
        self.updatePreview()

    def boundsDidChangeDone(self, bounds, newSelection):
        # box finished resize
        if not self.currentGenerator:
            return

        self.previewBounds = bounds
        self.schematicBounds = bounds
        self.currentGenerator.boundsChanged(bounds)
        self.updatePreview()

    def clearNode(self):
        if self.previewNode:
            self.overlayNode.removeChild(self.previewNode)
            self.previewNode = None

    def updatePreview(self):
        if self.blockPreview:
            self.updateBlockPreview()
        else:
            self.clearSchematic()

        if self.glPreview:
            self.updateNodePreview()
        else:
            self.clearNode()

    def updateBlockPreview(self):
        bounds = self.previewBounds

        if bounds is not None and bounds.volume > 0:
            self.generateNextSchematic(bounds)
        else:
            self.clearSchematic()

    def updateNodePreview(self):
        bounds = self.previewBounds
        if self.currentGenerator is None:
            return

        if bounds is not None and bounds.volume > 0:
            node = self.currentGenerator.getPreviewNode(bounds)
            if node is not None:
                self.clearNode()

                if isinstance(node, list):
                    nodes = node
                    node = scenegraph.Node()
                    for c in nodes:
                        node.addChild(c)

                self.overlayNode.addChild(node)
                self.previewNode = node

    def generateNextSchematic(self, bounds):
        if bounds is None:
            self.clearSchematic()
            return
        if self.currentGenerator is None:
            return

        try:
            schematic = self.currentGenerator.generate(bounds, self.editorSession.worldEditor.blocktypes)
            self.currentSchematic = schematic
            self.displaySchematic(schematic, bounds.origin)
        except Exception as e:
            log.exception("Error while running generator %s: %s", self.currentGenerator, e)
            QtGui.QMessageBox.warning(qApp.mainWindow, "Error while running generator",
                                      "An error occurred while running the generator: \n  %s.\n\n"
                                      "Traceback: %s" % (e, traceback.format_exc()))
            self.livePreview = False

    def displaySchematic(self, schematic, offset):
        if schematic is not None:
            dim = schematic.getDimension()

            if self.worldScene:
                self.sceneHolderNode.removeChild(self.worldScene)
                self.loader.timer.stop()
                self.loader = None

            atlas = self.editorSession.textureAtlas
            self.worldScene = WorldScene(dim, atlas)
            self.sceneHolderNode.translateOffset = offset
            self.sceneHolderNode.addChild(self.worldScene)

            self.loader = WorldLoader(self.worldScene)
            if dim.chunkCount() <= self.instantDisplayChunks:
                exhaust(self.loader.work())
            else:
                self.loader.timer.start()
        else:
            self.clearSchematic()

    def clearSchematic(self):
        if self.worldScene:
            self.sceneHolderNode.removeChild(self.worldScene)
            self.worldScene = None
            self.loader.timer.stop()
            self.loader = None

    def generateClicked(self):
        if self.currentGenerator is None:
            return

        if self.schematicBounds is None:
            log.info("schematicBounds is None, not generating")
            return

        if self.currentSchematic is None:
            log.info("Generating new schematic for import")
            currentSchematic = self.currentGenerator.generate(self.schematicBounds, self.editorSession.worldEditor.blocktypes)
        else:
            log.info("Importing previously generated schematic.")
            currentSchematic = self.currentSchematic

        command = GenerateCommand(self, self.schematicBounds)
        try:
            with command.begin():
                if currentSchematic is not None:
                    task = self.editorSession.currentDimension.importSchematicIter(currentSchematic, self.schematicBounds.origin)
                    showProgress(self.tr("Importing generated object..."), task)
                else:
                    task = self.currentGenerator.generateInWorld(self.schematicBounds, self.editorSession.currentDimension)
                    showProgress(self.tr("Generating object in world..."), task)
        except Exception as e:
            log.exception("Error while importing or generating in world: %r" % e)
            command.undo()
        else:
            self.editorSession.pushCommand(command)
示例#9
0
文件: imports.py 项目: dzkdev/mcedit2
    def __init__(self, pendingImport, textureAtlas):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        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)
        self.positionTranslateNode.addChild(self.rotateNode)

        self.rotateNode.setAnchor(self.pendingImport.selection.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)

        self.worldSceneTranslateNode.translateOffset = -self.pendingImport.selection.origin
        self.worldSceneTranslateNode.addChild(self.worldScene)
        self.rotateNode.addChild(self.worldSceneTranslateNode)

        # 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.basePosition = pendingImport.basePosition

        self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
        self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

        self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(
            self.worldScene, list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader()

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
示例#10
0
文件: imports.py 项目: dzkdev/mcedit2
class PendingImportNode(Node, QtCore.QObject):
    __node_id_counter = 0

    def __init__(self, pendingImport, textureAtlas):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        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)
        self.positionTranslateNode.addChild(self.rotateNode)

        self.rotateNode.setAnchor(self.pendingImport.selection.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)

        self.worldSceneTranslateNode.translateOffset = -self.pendingImport.selection.origin
        self.worldSceneTranslateNode.addChild(self.worldScene)
        self.rotateNode.addChild(self.worldSceneTranslateNode)

        # 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.basePosition = pendingImport.basePosition

        self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
        self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

        self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(
            self.worldScene, list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader()

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)

    # 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):
        point = self.getBaseFromTransformed(bounds.origin)
        oldPoint = self.getBaseFromTransformed(oldBounds.origin)
        if point != oldPoint:
            self.importMoved.emit(point, oldPoint)

    def handleBoundsChanged(self, bounds):
        point = self.getBaseFromTransformed(bounds.origin)
        if self.basePosition != point:
            self.basePosition = point

    def getBaseFromTransformed(self, point):
        offset = self.pendingImport.basePosition - self.pendingImport.importPos
        return point + offset

    def setPreviewRotation(self, rots):
        self.rotateNode.visible = True
        self.worldSceneTranslateNode.visible = True
        self.transformedWorldTranslateNode.visible = False
        self.rotateNode.setRotation(rots)

    def setRotation(self, rots):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.rotateNode.setRotation(rots)

    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

            if self.transformedWorldScene:
                self.transformedWorldTranslateNode.removeChild(
                    self.transformedWorldScene)

            self.transformedWorldScene = WorldScene(
                self.pendingImport.transformedDim, self.textureAtlas)
            self.transformedWorldScene.depthOffsetNode.depthOffset = DepthOffset.PreviewRenderer
            self.transformedWorldTranslateNode.addChild(
                self.transformedWorldScene)

            self.updateTransformedSceneOffset()

            cPos = list(self.pendingImport.transformedDim.chunkPositions())
            self.loader = WorldLoader(self.transformedWorldScene, cPos)
            self.loader.startLoader()

        else:
            log.info("Hiding transformed scene")
            self.rotateNode.visible = True
            self.worldSceneTranslateNode.visible = True
            self.transformedWorldTranslateNode.visible = False
            if self.transformedWorldScene:
                self.transformedWorldTranslateNode.removeChild(
                    self.transformedWorldScene)
                self.transformedWorldScene = None

    def updateTransformedSceneOffset(self):
        self.transformedWorldTranslateNode.translateOffset = self.transformedPosition - self.pendingImport.importDim.bounds.origin

    @property
    def transformedPosition(self):
        return self.basePosition + self.pendingImport.importPos - self.pendingImport.basePosition

    @property
    def basePosition(self):
        return self.positionTranslateNode.translateOffset

    @basePosition.setter
    def basePosition(self, value):
        if value == self.positionTranslateNode.translateOffset:
            return

        self.positionTranslateNode.translateOffset = Vector(*value)
        self.updateTransformedSceneOffset()
        self.updateBoxHandle()

    def setPosition(self, pos):
        self.basePosition = pos

    def updateBoxHandle(self):
        if self.transformedWorldScene is None:
            bounds = BoundingBox(self.basePosition,
                                 self.pendingImport.bounds.size)
        else:
            origin = self.transformedPosition
            bounds = BoundingBox(origin, self.pendingImport.importBounds.size)
        #if self.handleNode.bounds.size != bounds.size:
        self.handleNode.bounds = bounds

    # --- Mouse events ---

    # inherit from BoxHandle?
    def mouseMove(self, event):
        self.handleNode.mouseMove(event)

    def mousePress(self, event):
        self.handleNode.mousePress(event)

    def mouseRelease(self, event):
        self.handleNode.mouseRelease(event)
示例#11
0
    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.livePreview = False
        self.blockPreview = False
        self.glPreview = True

        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [pluginClass(self) for pluginClass in _pluginClasses]
        self.currentGenerator = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        for gt in self.generatorTypes:
            self.generatorTypeInput.addItem(gt.displayName, gt)

        self.generatorTypeInput.currentIndexChanged.connect(self.generatorTypeChanged)

        self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview")
        self.livePreviewCheckbox.setChecked(self.livePreview)
        self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled)

        self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview")
        self.blockPreviewCheckbox.setChecked(self.blockPreview)
        self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled)

        self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview")
        self.glPreviewCheckbox.setChecked(self.glPreview)
        self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled)

        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)

        self.generateButton = QtGui.QPushButton(self.tr("Generate"))
        self.generateButton.clicked.connect(self.generateClicked)

        column.append(self.generatorTypeInput)
        column.append(self.livePreviewCheckbox)
        column.append(self.blockPreviewCheckbox)
        column.append(self.glPreviewCheckbox)
        column.append(self.optionsHolder)
        column.append(self.generateButton)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenegraph.Node()

        self.sceneHolderNode = scenegraph.TranslateNode()
        self.overlayNode.addChild(self.sceneHolderNode)

        self.previewNode = None

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None

        self.previewBounds = None
        self.schematicBounds = None
        self.currentSchematic = None

        if len(self.generatorTypes):
            self.generatorTypeChanged(0)
示例#12
0
class PendingImportNode(Node, QtCore.QObject):
    __node_id_counter = 0

    def __init__(self, pendingImport, textureAtlas, hasHandle=True):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.
        hasHandle: bool
            True if this import node should have a user-interactive BoxHandle associated
            with it. This is False for the extra copies displayed by a repeated clone.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        self.pendingImport = pendingImport
        self.hasHandle = hasHandle

        dim = pendingImport.sourceDim

        self.transformedPosition = Vector(0, 0, 0)

        # worldScene is contained by rotateNode, and
        # translates the world scene back to 0, 0, 0 so the rotateNode can
        # rotate it around the anchor, and the plainSceneNode can translate
        # it to the current position.

        self.worldScene = WorldScene(dim,
                                     textureAtlas,
                                     bounds=pendingImport.selection)
        self.worldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer

        self.worldSceneTranslate = Translate(
            -self.pendingImport.selection.origin)
        self.worldScene.addState(self.worldSceneTranslate)

        # rotateNode is used to rotate the non-transformed preview during live rotation

        self.rotateNode = Rotate3DNode()
        self.rotateNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.rotateNode.addChild(self.worldScene)

        self.scaleNode = Scale3DNode()
        self.scaleNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.scaleNode.addChild(self.rotateNode)

        # plainSceneNode 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.plainSceneNode = Node("plainScene")
        self.positionTranslate = Translate()
        self.plainSceneNode.addState(self.positionTranslate)
        self.plainSceneNode.addChild(self.scaleNode)

        self.addChild(self.plainSceneNode)

        # transformedSceneNode contains the transformed preview of the imported
        # object, including a world scene that displays the object wrapped by a
        # DimensionTransform.

        self.transformedSceneNode = Node("transformedScene")
        self.transformedSceneTranslate = Translate()
        self.transformedSceneNode.addState(self.transformedSceneTranslate)

        self.transformedWorldScene = None
        self.addChild(self.transformedSceneNode)

        box = BoundingBox(pendingImport.importPos,
                          pendingImport.importBounds.size)

        if hasHandle:
            # handleNode displays a bounding box that can be moved around, and responds
            # to mouse events.
            self.handleNode = BoxHandle()
            self.handleNode.bounds = box
            self.handleNode.resizable = False
            self.boxNode = None
        else:
            # boxNode displays a plain, non-movable bounding box
            self.boxNode = SelectionBoxNode()
            self.boxNode.wireColor = (1, 1, 1, .2)
            self.boxNode.filled = False
            self.handleNode = None
            self.addChild(self.boxNode)

        self.updateTransformedScene()
        self.basePosition = pendingImport.basePosition

        if hasHandle:
            self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
            self.handleNode.boundsChangedDone.connect(
                self.handleBoundsChangedDone)

            self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(
            self.worldScene, list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
        self.pendingImport.scaleChanged.connect(self.setScale)

    # Emitted when the user finishes dragging the box handle and releases the mouse
    # button. Arguments are (newPosition, oldPosition).
    importMoved = QtCore.Signal(object, object)

    # Emitted while the user is dragging the box handle. Argument is the box origin.
    importIsMoving = QtCore.Signal(object)

    def handleBoundsChangedDone(self, bounds, oldBounds):
        point = self.getBaseFromTransformed(bounds.origin)
        oldPoint = self.getBaseFromTransformed(oldBounds.origin)
        if point != oldPoint:
            self.importMoved.emit(point, oldPoint)

    def handleBoundsChanged(self, bounds):
        log.info("handleBoundsChanged: %s", bounds)
        self.setPreviewBasePosition(bounds.origin)

    def setPreviewBasePosition(self, origin):
        point = self.getBaseFromTransformed(origin)
        if self.basePosition != point:
            self.basePosition = point
            self.importIsMoving.emit(point)

    def getBaseFromTransformed(self, point):
        return point - self.pendingImport.transformOffset

    def setPreviewRotation(self, rots):
        self.plainSceneNode.visible = True
        self.transformedSceneNode.visible = False
        self.rotateNode.setRotation(rots)

    def setRotation(self, rots):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.rotateNode.setRotation(rots)

    def setPreviewScale(self, scale):
        self.plainSceneNode.visible = True
        self.transformedSceneNode.visible = False
        self.scaleNode.setScale(scale)

    def setScale(self, scale):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.scaleNode.setScale(scale)

    def updateTransformedScene(self):
        if self.pendingImport.transformedDim is not None:
            log.info("Showing transformed scene")
            self.plainSceneNode.visible = False
            self.transformedSceneNode.visible = True

            if self.transformedWorldScene:
                self.transformedSceneNode.removeChild(
                    self.transformedWorldScene)

            self.transformedWorldScene = WorldScene(
                self.pendingImport.transformedDim, self.textureAtlas)
            self.transformedWorldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer
            self.transformedSceneNode.addChild(self.transformedWorldScene)

            self.updateTransformedPosition()

            cPos = list(self.pendingImport.transformedDim.chunkPositions())
            self.loader = WorldLoader(self.transformedWorldScene, cPos)

            # ALERT!: self.hasHandle is overloaded with the meaning:
            #  "not the first clone in a repeated clone"
            self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        else:
            log.info("Hiding transformed scene")
            self.plainSceneNode.visible = True
            self.transformedSceneNode.visible = False
            if self.transformedWorldScene:
                self.transformedSceneNode.removeChild(
                    self.transformedWorldScene)
                self.transformedWorldScene = None

    def updateTransformedPosition(self):
        self.transformedPosition = self.basePosition + self.pendingImport.transformOffset
        self.transformedSceneTranslate.translateOffset = self.transformedPosition - self.pendingImport.importDim.bounds.origin

    def updateBoxHandle(self):
        if self.transformedWorldScene is None:
            bounds = BoundingBox(self.basePosition,
                                 self.pendingImport.bounds.size)
        else:
            origin = self.transformedPosition
            bounds = BoundingBox(origin, self.pendingImport.importBounds.size)
        #if self.handleNode.bounds.size != bounds.size:
        if self.hasHandle:
            self.handleNode.bounds = bounds
        else:
            self.boxNode.selectionBox = bounds

    @property
    def basePosition(self):
        return self.positionTranslate.translateOffset

    @basePosition.setter
    def basePosition(self, value):
        value = Vector(*value)
        if value == self.positionTranslate.translateOffset:
            return

        self.positionTranslate.translateOffset = value
        self.updateTransformedPosition()
        self.updateBoxHandle()

    def setPosition(self, pos):
        self.basePosition = pos

    # --- Mouse events ---

    # inherit from BoxHandle?
    def mouseMove(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mouseMove(event)

    def mousePress(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mousePress(event)

    def mouseRelease(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mouseRelease(event)
示例#13
0
文件: generate.py 项目: wcpe/mcedit2
class GenerateTool(EditorTool):
    name = "Generate"
    iconName = "generate"

    instantDisplayChunks = 32
    modifiesWorld = True

    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.livePreview = False
        self.blockPreview = False
        self.glPreview = True

        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [
            pluginClass(self)
            for pluginClass in GeneratePlugins.registeredPlugins
        ]
        self.currentGenerator = None
        if len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        self.generatorTypesChanged()

        self.generatorTypeInput.currentIndexChanged.connect(
            self.currentTypeChanged)

        self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview")
        self.livePreviewCheckbox.setChecked(self.livePreview)
        self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled)

        self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview")
        self.blockPreviewCheckbox.setChecked(self.blockPreview)
        self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled)

        self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview")
        self.glPreviewCheckbox.setChecked(self.glPreview)
        self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled)

        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                         QtGui.QSizePolicy.Expanding)

        self.generateButton = QtGui.QPushButton(self.tr("Generate"))
        self.generateButton.clicked.connect(self.generateClicked)

        column.append(self.generatorTypeInput)
        column.append(self.livePreviewCheckbox)
        column.append(self.blockPreviewCheckbox)
        column.append(self.glPreviewCheckbox)
        column.append(self.optionsHolder)
        column.append(self.generateButton)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenenode.Node("generateOverlay")

        self.sceneHolderNode = Node("sceneHolder")
        self.sceneTranslate = Translate()
        self.sceneHolderNode.addState(self.sceneTranslate)

        self.overlayNode.addChild(self.sceneHolderNode)

        self.previewNode = None

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None
        self.loader = None

        self.previewBounds = None
        self.schematicBounds = None
        self.currentSchematic = None

        self.currentTypeChanged(0)

        # Name of last selected generator plugin is saved after unloading
        # so it can be reselected if it is immediately reloaded
        self._lastTypeName = None

        GeneratePlugins.pluginAdded.connect(self.addPlugin)
        GeneratePlugins.pluginRemoved.connect(self.removePlugin)

    def removePlugin(self, cls):
        log.info("Removing plugin %s", cls.__name__)
        self.generatorTypes[:] = [
            gt for gt in self.generatorTypes if not isinstance(gt, cls)
        ]
        self.generatorTypesChanged()
        if self.currentGenerator not in self.generatorTypes:
            lastTypeName = self.currentGenerator.__class__.__name__
            self.currentTypeChanged(0)  # resets self._lastTypeName
            self._lastTypeName = lastTypeName

    def addPlugin(self, cls):
        log.info("Adding plugin %s", cls.__name__)
        self.generatorTypes.append(cls(self))
        self.generatorTypesChanged()
        if self._lastTypeName is not None:
            if cls.__name__ == self._lastTypeName:
                self.currentTypeChanged(len(self.generatorTypes) - 1)

    def generatorTypesChanged(self):
        self.generatorTypeInput.clear()
        for gt in self.generatorTypes:
            if hasattr(gt, 'displayName'):
                displayName = gt.displayName
            else:
                displayName = gt.__class__.__name__
            self.generatorTypeInput.addItem(displayName, gt)

    def livePreviewToggled(self, value):
        self.livePreview = value

    def blockPreviewToggled(self, value):
        self.blockPreview = value
        if value:
            if self.currentSchematic:
                self.displaySchematic(self.currentSchematic,
                                      self.schematicBounds.origin)
            else:
                self.updateBlockPreview()
        else:
            self.clearSchematic()

    def glPreviewToggled(self, value):
        self.glPreview = value
        if value:
            self.updateNodePreview()  # xxx cache previewNode?
        else:
            self.clearNode()

    def currentTypeChanged(self, index):
        # user selected generator type after old type was unloaded, so forget the old type
        self._lastTypeName = None

        self.optionsHolder.removeWidget(self.optionsHolder.widget(0))
        if index < len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[index]
            self.optionsHolder.addWidget(
                self.currentGenerator.getOptionsWidget())
            self.updatePreview()
        else:
            self.currentGenerator = None
            self.clearSchematic()
            self.clearNode()

        log.info("Chose generator %s", repr(self.currentGenerator))

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    def boundsDidChange(self, bounds):
        # box still being resized
        if not self.currentGenerator:
            return

        if not self.livePreview:
            return

        self.previewBounds = bounds
        self.currentGenerator.boundsChanged(bounds)
        self.updatePreview()

    def boundsDidChangeDone(self, bounds, oldBounds):
        # box finished resize
        if not self.currentGenerator:
            return

        self.previewBounds = bounds
        self.schematicBounds = bounds
        self.currentGenerator.boundsChanged(bounds)
        self.updatePreview()

    def clearNode(self):
        if self.previewNode:
            self.overlayNode.removeChild(self.previewNode)
            self.previewNode = None

    def updatePreview(self):
        if self.blockPreview:
            self.updateBlockPreview()
        else:
            self.clearSchematic()

        if self.glPreview:
            self.updateNodePreview()
        else:
            self.clearNode()

    def updateBlockPreview(self):
        bounds = self.previewBounds

        if bounds is not None and bounds.volume > 0:
            self.generateNextSchematic(bounds)
        else:
            self.clearSchematic()

    def updateNodePreview(self):
        bounds = self.previewBounds
        if self.currentGenerator is None:
            return

        if bounds is not None and bounds.volume > 0:
            try:
                node = self.currentGenerator.getPreviewNode(bounds)
            except Exception:
                log.exception(
                    "Error while getting scene nodes from generator:")
            else:
                if node is not None:
                    self.clearNode()

                    if isinstance(node, list):
                        nodes = node
                        node = scenenode.Node("generatePreviewHolder")
                        for c in nodes:
                            node.addChild(c)

                    self.overlayNode.addChild(node)
                    self.previewNode = node

    def generateNextSchematic(self, bounds):
        if bounds is None:
            self.clearSchematic()
            return
        if self.currentGenerator is None:
            return

        try:
            schematic = self.currentGenerator.generate(
                bounds, self.editorSession.worldEditor.blocktypes)
            self.currentSchematic = schematic
            self.displaySchematic(schematic, bounds.origin)
        except Exception as e:
            log.exception("Error while running generator %s: %s",
                          self.currentGenerator, e)
            QtGui.QMessageBox.warning(
                QtGui.qApp.mainWindow, "Error while running generator",
                "An error occurred while running the generator: \n  %s.\n\n"
                "Traceback: %s" % (e, traceback.format_exc()))
            self.livePreview = False

    def displaySchematic(self, schematic, offset):
        if schematic is not None:
            dim = schematic.getDimension()

            if self.worldScene:
                self.sceneHolderNode.removeChild(self.worldScene)
                self.loader.timer.stop()
                self.loader = None

            atlas = self.editorSession.textureAtlas
            self.worldScene = WorldScene(dim, atlas)
            self.sceneTranslate.translateOffset = offset
            self.sceneHolderNode.addChild(self.worldScene)

            self.loader = WorldLoader(self.worldScene)
            if dim.chunkCount() <= self.instantDisplayChunks:
                exhaust(self.loader.work())
            else:
                self.loader.startLoader()
        else:
            self.clearSchematic()

    def clearSchematic(self):
        if self.worldScene:
            self.sceneHolderNode.removeChild(self.worldScene)
            self.worldScene = None
            self.loader.timer.stop()
            self.loader = None

    def generateClicked(self):
        if self.currentGenerator is None:
            return

        if self.schematicBounds is None:
            log.info("schematicBounds is None, not generating")
            return

        if self.currentSchematic is None:
            log.info("Generating new schematic for import")
            currentSchematic = self.currentGenerator.generate(
                self.schematicBounds,
                self.editorSession.worldEditor.blocktypes)
        else:
            log.info("Importing previously generated schematic.")
            currentSchematic = self.currentSchematic

        command = GenerateCommand(self, self.schematicBounds)
        try:
            with command.begin():
                if currentSchematic is not None:
                    task = self.editorSession.currentDimension.importSchematicIter(
                        currentSchematic, self.schematicBounds.origin)
                    showProgress(self.tr("Importing generated object..."),
                                 task)
                else:
                    task = self.currentGenerator.generateInWorld(
                        self.schematicBounds,
                        self.editorSession.currentDimension)
                    showProgress(self.tr("Generating object in world..."),
                                 task)
        except Exception as e:
            log.exception("Error while importing or generating in world: %r" %
                          e)
            command.undo()
        else:
            self.editorSession.pushCommand(command)
示例#14
0
class SelectionTool(EditorTool):
    name = "Select"
    iconName = "select_blocks"

    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.toolWidget.setLayout(
            Column(self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        editorSession.dimensionChanged.connect(self.dimensionDidChange)

    def dimensionDidChange(self):
        self.selectionNode.dimension = self.editorSession.currentDimension

    def shapeDidChange(self):
        if self.currentSelection is not None:
            self.currentSelection = self.createShapedSelection(
                self.currentSelection)

    def toolActive(self):
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .5

    def toolInactive(self):
        self.faceHoverNode.visible = False
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .33

    @property
    def hideSelectionWalls(self):
        return not self.selectionNode.filled

    @hideSelectionWalls.setter
    def hideSelectionWalls(self, value):
        self.selectionNode.filled = not value

    @property
    def currentSelection(self):
        return self.editorSession.currentSelection

    @currentSelection.setter
    def currentSelection(self, value):
        self.editorSession.currentSelection = value

    def coordInputChanged(self, box):
        self.currentSelection = self.createShapedSelection(box)

    def selectionDidChange(self, value):
        self.coordInput.boundingBox = value
        self.updateNodes()

    def updateNodes(self):
        box = self.currentSelection
        if box:
            self.boxHandleNode.bounds = BoundingBox(box.origin, box.size)
            self.selectionNode.visible = True
            self.selectionNode.selection = box
        else:
            self.boxHandleNode.bounds = None
            self.selectionNode.visible = False
            self.faceHoverNode.visible = False

    def boxHandleResized(self, box):
        if box is not None:
            self.selectionNode.selection = self.createShapedSelection(box)

    def boxHandleResizedDone(self, box, newSelection):
        if box is not None:
            selection = self.createShapedSelection(box)
            command = SelectCommand(self.editorSession, selection)
            if not newSelection:
                command.setText(self.tr("Resize Selection"))
            self.editorSession.undoStack.push(command)
            self.updateNodes()

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.mouseDrag(event)

    def mouseDrag(self, event):
        # Update cursor
        self.cursorNode.point = event.blockPosition
        self.cursorNode.face = event.blockFace

        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    selectionColor = (0.8, 0.8, 1.0)
    alpha = 0.33

    showPreviousSelection = True

    def createShapedSelection(self, box):
        if self.shapeInput.currentShape is shapewidget.Square:
            return box
        else:
            return selection.ShapedSelection(
                box, self.shapeInput.currentShape.shapeFunc)
示例#15
0
文件: imports.py 项目: dzkdev/mcedit2
class PendingImportNode(Node, QtCore.QObject):
    __node_id_counter = 0

    def __init__(self, pendingImport, textureAtlas):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        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)
        self.positionTranslateNode.addChild(self.rotateNode)

        self.rotateNode.setAnchor(self.pendingImport.selection.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)

        self.worldSceneTranslateNode.translateOffset = -self.pendingImport.selection.origin
        self.worldSceneTranslateNode.addChild(self.worldScene)
        self.rotateNode.addChild(self.worldSceneTranslateNode)

        # 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.basePosition = pendingImport.basePosition

        self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
        self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

        self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(self.worldScene,
                                  list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader()

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)

    # 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):
        point = self.getBaseFromTransformed(bounds.origin)
        oldPoint = self.getBaseFromTransformed(oldBounds.origin)
        if point != oldPoint:
            self.importMoved.emit(point, oldPoint)

    def handleBoundsChanged(self, bounds):
        point = self.getBaseFromTransformed(bounds.origin)
        if self.basePosition != point:
            self.basePosition = point

    def getBaseFromTransformed(self, point):
        offset = self.pendingImport.basePosition - self.pendingImport.importPos
        return point + offset

    def setPreviewRotation(self, rots):
        self.rotateNode.visible = True
        self.worldSceneTranslateNode.visible = True
        self.transformedWorldTranslateNode.visible = False
        self.rotateNode.setRotation(rots)

    def setRotation(self, rots):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.rotateNode.setRotation(rots)

    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

            if self.transformedWorldScene:
                self.transformedWorldTranslateNode.removeChild(self.transformedWorldScene)

            self.transformedWorldScene = WorldScene(self.pendingImport.transformedDim,
                                                    self.textureAtlas)
            self.transformedWorldScene.depthOffsetNode.depthOffset = DepthOffset.PreviewRenderer
            self.transformedWorldTranslateNode.addChild(self.transformedWorldScene)

            self.updateTransformedSceneOffset()

            cPos = list(self.pendingImport.transformedDim.chunkPositions())
            self.loader = WorldLoader(self.transformedWorldScene,
                                      cPos)
            self.loader.startLoader()

        else:
            log.info("Hiding transformed scene")
            self.rotateNode.visible = True
            self.worldSceneTranslateNode.visible = True
            self.transformedWorldTranslateNode.visible = False
            if self.transformedWorldScene:
                self.transformedWorldTranslateNode.removeChild(self.transformedWorldScene)
                self.transformedWorldScene = None

    def updateTransformedSceneOffset(self):
        self.transformedWorldTranslateNode.translateOffset = self.transformedPosition - self.pendingImport.importDim.bounds.origin

    @property
    def transformedPosition(self):
        return self.basePosition + self.pendingImport.importPos - self.pendingImport.basePosition

    @property
    def basePosition(self):
        return self.positionTranslateNode.translateOffset

    @basePosition.setter
    def basePosition(self, value):
        if value == self.positionTranslateNode.translateOffset:
            return

        self.positionTranslateNode.translateOffset = Vector(*value)
        self.updateTransformedSceneOffset()
        self.updateBoxHandle()

    def setPosition(self, pos):
        self.basePosition = pos

    def updateBoxHandle(self):
        if self.transformedWorldScene is None:
            bounds = BoundingBox(self.basePosition, self.pendingImport.bounds.size)
        else:
            origin = self.transformedPosition
            bounds = BoundingBox(origin, self.pendingImport.importBounds.size)
        #if self.handleNode.bounds.size != bounds.size:
        self.handleNode.bounds = bounds

    # --- Mouse events ---

    # inherit from BoxHandle?
    def mouseMove(self, event):
        self.handleNode.mouseMove(event)

    def mousePress(self, event):
        self.handleNode.mousePress(event)

    def mouseRelease(self, event):
        self.handleNode.mouseRelease(event)
示例#16
0
文件: select.py 项目: qtx0213/mcedit2
class SelectionTool(EditorTool):
    name = "Select"
    iconName = "select_blocks"

    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.optionsButton = QtGui.QPushButton(self.tr("Options"))

        self.optionsMenu = QtGui.QMenu()
        self.optionsButton.setMenu(self.optionsMenu)
        
        classicSelectionAction = self.optionsMenu.addAction(self.tr("Classic Selection"))
        stickySelectionAction = self.optionsMenu.addAction(self.tr("Sticky Selection"))

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(Column(self.optionsButton,
                                         self.coordInput,
                                         self.shapeInput,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node("selectOverlay")
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        classicSelectionAction.setCheckable(True)
        classicSelectionAction.toggled.connect(ClassicSelectionOption.setValue)
        classicSelectionAction.setChecked(ClassicSelectionOption.value())
        ClassicSelectionOption.connectAndCall(self.setClassicSelection)

        stickySelectionAction.setCheckable(True)
        stickySelectionAction.toggled.connect(StickySelectionOption.setValue)
        stickySelectionAction.setChecked(StickySelectionOption.value())
        StickySelectionOption.connectAndCall(self.setStickySelection)

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)

    def revisionDidChange(self, changes):
        chunks = changes.chunks[self.editorSession.currentDimension.dimName]
        for cx, cz in chunks:
            self.selectionNode.discardChunk(cx, cz)

    def dimensionDidChange(self):
        self.selectionNode.dimension = self.editorSession.currentDimension

    def shapeDidChange(self):
        if self.currentSelection is not None:
            self.currentSelection = self.createShapedSelection(self.currentSelection)

    def toolActive(self):
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .5

    def toolInactive(self):
        self.faceHoverNode.visible = False
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .33

    @property
    def hideSelectionWalls(self):
        return not self.selectionNode.filled

    @hideSelectionWalls.setter
    def hideSelectionWalls(self, value):
        self.selectionNode.filled = not value

    @property
    def currentSelection(self):
        return self.editorSession.currentSelection

    @currentSelection.setter
    def currentSelection(self, value):
        self.editorSession.currentSelection = value

    def coordInputChanged(self, box):
        self.currentSelection = self.createShapedSelection(box)

    def selectionDidChange(self, value):
        self.coordInput.boundingBox = value
        self.updateNodes()

    def updateNodes(self):
        box = self.currentSelection
        if box:
            self.boxHandleNode.bounds = BoundingBox(box.origin, box.size)
            self.selectionNode.visible = True
            self.selectionNode.selection = box
        else:
            self.boxHandleNode.bounds = None
            self.selectionNode.visible = False
            self.faceHoverNode.visible = False

    lastResizeTime = time.time()

    def boxHandleResized(self, box):
        if box is not None:
            self.selectionNode.selection = self.createShapedSelection(box)
            if time.time() - self.lastResizeTime > 0.025:
                self.selectionNode.loadImmediateChunks(0.025)
            self.lastResizeTime = time.time()

    def boxHandleResizedDone(self, box, oldBox):
        if box is not None:
            selection = self.createShapedSelection(box)
            command = SelectCommand(self.editorSession, selection)
            if oldBox is not None:
                command.setText(self.tr("Resize Selection"))
            self.editorSession.undoStack.push(command)
            self.updateNodes()
            self.selectionNode.loadImmediateChunks()

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.mouseDrag(event)

    def mouseDrag(self, event):
        # Update cursor
        self.cursorNode.point = event.blockPosition
        self.cursorNode.face = event.blockFace

        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    selectionColor = (0.8, 0.8, 1.0)
    alpha = 0.33

    showPreviousSelection = True

    def createShapedSelection(self, box):
        return self.shapeInput.currentShape.createShapedSelection(box, self.editorSession.currentDimension)

    def setClassicSelection(self, enabled):
        self.boxHandleNode.classicSelection = enabled

    def setStickySelection(self, enabled):
        self.boxHandleNode.stickySelection = enabled
示例#17
0
    def __init__(self, pendingImport, textureAtlas, hasHandle=True):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.
        hasHandle: bool
            True if this import node should have a user-interactive BoxHandle associated
            with it. This is False for the extra copies displayed by a repeated clone.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        self.pendingImport = pendingImport
        self.hasHandle = hasHandle

        dim = pendingImport.sourceDim

        self.transformedPosition = Vector(0, 0, 0)

        # worldScene is contained by rotateNode, and
        # translates the world scene back to 0, 0, 0 so the rotateNode can
        # rotate it around the anchor, and the plainSceneNode can translate
        # it to the current position.

        self.worldScene = WorldScene(dim,
                                     textureAtlas,
                                     bounds=pendingImport.selection)
        self.worldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer

        self.worldSceneTranslate = Translate(
            -self.pendingImport.selection.origin)
        self.worldScene.addState(self.worldSceneTranslate)

        # rotateNode is used to rotate the non-transformed preview during live rotation

        self.rotateNode = Rotate3DNode()
        self.rotateNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.rotateNode.addChild(self.worldScene)

        self.scaleNode = Scale3DNode()
        self.scaleNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.scaleNode.addChild(self.rotateNode)

        # plainSceneNode 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.plainSceneNode = Node("plainScene")
        self.positionTranslate = Translate()
        self.plainSceneNode.addState(self.positionTranslate)
        self.plainSceneNode.addChild(self.scaleNode)

        self.addChild(self.plainSceneNode)

        # transformedSceneNode contains the transformed preview of the imported
        # object, including a world scene that displays the object wrapped by a
        # DimensionTransform.

        self.transformedSceneNode = Node("transformedScene")
        self.transformedSceneTranslate = Translate()
        self.transformedSceneNode.addState(self.transformedSceneTranslate)

        self.transformedWorldScene = None
        self.addChild(self.transformedSceneNode)

        box = BoundingBox(pendingImport.importPos,
                          pendingImport.importBounds.size)

        if hasHandle:
            # handleNode displays a bounding box that can be moved around, and responds
            # to mouse events.
            self.handleNode = BoxHandle()
            self.handleNode.bounds = box
            self.handleNode.resizable = False
            self.boxNode = None
        else:
            # boxNode displays a plain, non-movable bounding box
            self.boxNode = SelectionBoxNode()
            self.boxNode.wireColor = (1, 1, 1, .2)
            self.boxNode.filled = False
            self.handleNode = None
            self.addChild(self.boxNode)

        self.updateTransformedScene()
        self.basePosition = pendingImport.basePosition

        if hasHandle:
            self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
            self.handleNode.boundsChangedDone.connect(
                self.handleBoundsChangedDone)

            self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(
            self.worldScene, list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
        self.pendingImport.scaleChanged.connect(self.setScale)
示例#18
0
class SelectionTool(EditorTool):
    name = "Select"
    iconName = "select_blocks"

    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.deselectButton = QtGui.QPushButton(self.tr("Deselect"))
        self.deselectButton.clicked.connect(self.deselect)
        self.deleteSelectionButton = QtGui.QPushButton(self.tr("Delete"))
        self.deleteSelectionButton.clicked.connect(self.deleteSelection)
        self.deleteBlocksButton = QtGui.QPushButton(self.tr("Delete Blocks"))
        self.deleteBlocksButton.clicked.connect(self.deleteBlocks)
        self.deleteEntitiesButton = QtGui.QPushButton(self.tr("Delete Entities"))
        self.deleteEntitiesButton.clicked.connect(self.deleteEntities)
        self.fillButton = QtGui.QPushButton(self.tr("Fill"))
        self.fillButton.clicked.connect(self.fill)
        self.replaceButton = QtGui.QPushButton(self.tr("Replace"))
        self.replaceButton.clicked.connect(self.replace)

        self.toolWidget.setLayout(Column(self.coordInput,
                                         self.shapeInput,
                                         self.deselectButton,
                                         self.deleteSelectionButton,
                                         self.deleteBlocksButton,
                                         self.deleteEntitiesButton,
                                         self.fillButton,
                                         self.replaceButton,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.selectionNode.dimension = editorSession.currentDimension  # xxx dimensionDidChange
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

    def shapeDidChange(self):
        if self.currentSelection is not None:
            self.currentSelection = self.createShapedSelection(self.currentSelection)

    def toolActive(self):
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .5

    def toolInactive(self):
        self.faceHoverNode.visible = False
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .33

    @property
    def hideSelectionWalls(self):
        return not self.selectionNode.filled

    @hideSelectionWalls.setter
    def hideSelectionWalls(self, value):
        self.selectionNode.filled = not value

    @property
    def currentSelection(self):
        return self.editorSession.currentSelection

    @currentSelection.setter
    def currentSelection(self, value):
        self.editorSession.currentSelection = value

        self.boxHandleNode.bounds = None if value is None else BoundingBox(value.origin, value.size)

    def coordInputChanged(self, box):
        self.currentSelection = self.createShapedSelection(box)

    def selectionDidChange(self, value):
        self.coordInput.boundingBox = value
        self.updateNodes()

    def updateNodes(self):
        box = self.currentSelection
        if box:
            self.selectionNode.visible = True
            self.selectionNode.selection = box
        else:
            self.selectionNode.visible = False
            self.faceHoverNode.visible = False

    def deleteSelection(self):
        command = SimpleRevisionCommand(self.editorSession, "Delete")
        with command.begin():
            fillTask = self.editorSession.currentDimension.fillBlocksIter(self.editorSession.currentSelection, "air")
            entitiesTask = RemoveEntitiesOperation(self.editorSession.currentDimension, self.editorSession.currentSelection)
            task = ComposeOperations(fillTask, entitiesTask)
            showProgress("Deleting...", task)
        self.editorSession.pushCommand(command)

    def deleteBlocks(self):
        pass

    def deleteEntities(self):
        pass

    def fill(self):
        fillCommand(self.editorSession)

    def replace(self):
        replaceCommand(self.editorSession)

    def boxHandleResized(self, box):
        if box is not None:
            self.selectionNode.selection = self.createShapedSelection(box)

    def boxHandleResizedDone(self, box, newSelection):
        if box is not None:
            selection = self.createShapedSelection(box)
            command = SelectCommand(self, selection)
            if not newSelection:
                command.setText(self.tr("Resize Selection"))
            self.editorSession.undoStack.push(command)
            self.updateNodes()

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.mouseDrag(event)

    def mouseDrag(self, event):
        # Update cursor
        self.cursorNode.point = event.blockPosition
        self.cursorNode.face = event.blockFace

        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)


    def deselect(self):
        editor = self.editorSession
        command = SelectCommand(self, None)
        command.setText(self.tr("Deselect"))
        editor.undoStack.push(command)

    selectionColor = (0.8, 0.8, 1.0)
    alpha = 0.33

    showPreviousSelection = True

    def createShapedSelection(self, box):
        if self.shapeInput.currentShape is shapewidget.Square:
            return box
        else:
            return selection.ShapedSelection(box, self.shapeInput.currentShape.shapeFunc)
示例#19
0
文件: select.py 项目: wcpe/mcedit2
class SelectionTool(EditorTool):
    name = "Select"
    iconName = "select_blocks"

    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.optionsButton = QtGui.QPushButton(self.tr("Options"))

        self.optionsMenu = QtGui.QMenu()
        self.optionsButton.setMenu(self.optionsMenu)

        classicSelectionAction = self.optionsMenu.addAction(
            self.tr("Classic Selection"))
        stickySelectionAction = self.optionsMenu.addAction(
            self.tr("Sticky Selection"))

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(
            Column(self.optionsButton, self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node("selectOverlay")
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        classicSelectionAction.setCheckable(True)
        classicSelectionAction.toggled.connect(ClassicSelectionOption.setValue)
        classicSelectionAction.setChecked(ClassicSelectionOption.value())
        ClassicSelectionOption.connectAndCall(self.setClassicSelection)

        stickySelectionAction.setCheckable(True)
        stickySelectionAction.toggled.connect(StickySelectionOption.setValue)
        stickySelectionAction.setChecked(StickySelectionOption.value())
        StickySelectionOption.connectAndCall(self.setStickySelection)

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)

    def revisionDidChange(self, changes):
        chunks = changes.chunks[self.editorSession.currentDimension.dimName]
        for cx, cz in chunks:
            self.selectionNode.discardChunk(cx, cz)

    def dimensionDidChange(self):
        self.selectionNode.dimension = self.editorSession.currentDimension

    def shapeDidChange(self):
        if self.currentSelection is not None:
            self.currentSelection = self.createShapedSelection(
                self.currentSelection)

    def toolActive(self):
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .5

    def toolInactive(self):
        self.faceHoverNode.visible = False
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .33

    @property
    def hideSelectionWalls(self):
        return not self.selectionNode.filled

    @hideSelectionWalls.setter
    def hideSelectionWalls(self, value):
        self.selectionNode.filled = not value

    @property
    def currentSelection(self):
        return self.editorSession.currentSelection

    @currentSelection.setter
    def currentSelection(self, value):
        self.editorSession.currentSelection = value

    def coordInputChanged(self, box):
        self.currentSelection = self.createShapedSelection(box)

    def selectionDidChange(self, value):
        self.coordInput.boundingBox = value
        self.updateNodes()

    def updateNodes(self):
        box = self.currentSelection
        if box:
            self.boxHandleNode.bounds = BoundingBox(box.origin, box.size)
            self.selectionNode.visible = True
            self.selectionNode.selection = box
        else:
            self.boxHandleNode.bounds = None
            self.selectionNode.visible = False
            self.faceHoverNode.visible = False
            self.selectionNode.selection = None

    lastResizeTime = time.time()

    def boxHandleResized(self, box):
        if box is not None:
            self.selectionNode.selection = self.createShapedSelection(box)
            if time.time() - self.lastResizeTime > 0.025:
                self.selectionNode.loadImmediateChunks(0.025)
            self.lastResizeTime = time.time()
        else:
            self.selectionNode.selection = None

    def boxHandleResizedDone(self, box, oldBox):
        if box is not None:
            selection = self.createShapedSelection(box)
            command = SelectCommand(self.editorSession, selection)
            if oldBox is not None:
                command.setText(self.tr("Resize Selection"))
            self.editorSession.pushCommand(command)
            self.updateNodes()
            self.selectionNode.loadImmediateChunks()
        else:
            self.selectionNode.selection = None

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.mouseDrag(event)

    def mouseDrag(self, event):
        # Update cursor
        self.cursorNode.point = event.blockPosition
        self.cursorNode.face = event.blockFace

        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    selectionColor = (0.8, 0.8, 1.0)
    alpha = 0.33

    showPreviousSelection = True

    def createShapedSelection(self, box):
        return self.shapeInput.currentShape.createShapedSelection(
            box, self.editorSession.currentDimension)

    def setClassicSelection(self, enabled):
        self.boxHandleNode.classicSelection = enabled

    def setStickySelection(self, enabled):
        self.boxHandleNode.stickySelection = enabled
示例#20
0
文件: imports.py 项目: dzkdev/mcedit2
    def __init__(self, pendingImport, textureAtlas):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        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)
        self.positionTranslateNode.addChild(self.rotateNode)

        self.rotateNode.setAnchor(self.pendingImport.selection.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)

        self.worldSceneTranslateNode.translateOffset = -self.pendingImport.selection.origin
        self.worldSceneTranslateNode.addChild(self.worldScene)
        self.rotateNode.addChild(self.worldSceneTranslateNode)

        # 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.basePosition = pendingImport.basePosition

        self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
        self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

        self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(self.worldScene,
                                  list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader()

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
示例#21
0
文件: imports.py 项目: mcedit/mcedit2
class PendingImportNode(Node, QtCore.QObject):
    __node_id_counter = 0

    def __init__(self, pendingImport, textureAtlas, hasHandle=True):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.
        hasHandle: bool
            True if this import node should have a user-interactive BoxHandle associated
            with it. This is False for the extra copies displayed by a repeated clone.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        self.pendingImport = pendingImport
        self.hasHandle = hasHandle

        dim = pendingImport.sourceDim

        self.transformedPosition = Vector(0, 0, 0)

        # worldScene is contained by rotateNode, and
        # translates the world scene back to 0, 0, 0 so the rotateNode can
        # rotate it around the anchor, and the plainSceneNode can translate
        # it to the current position.

        self.worldScene = WorldScene(dim, textureAtlas, bounds=pendingImport.selection)
        self.worldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer

        self.worldSceneTranslate = Translate(-self.pendingImport.selection.origin)
        self.worldScene.addState(self.worldSceneTranslate)

        # rotateNode is used to rotate the non-transformed preview during live rotation

        self.rotateNode = Rotate3DNode()
        self.rotateNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.rotateNode.addChild(self.worldScene)

        self.scaleNode = Scale3DNode()
        self.scaleNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.scaleNode.addChild(self.rotateNode)

        # plainSceneNode 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.plainSceneNode = Node("plainScene")
        self.positionTranslate = Translate()
        self.plainSceneNode.addState(self.positionTranslate)
        self.plainSceneNode.addChild(self.scaleNode)

        self.addChild(self.plainSceneNode)

        # transformedSceneNode contains the transformed preview of the imported
        # object, including a world scene that displays the object wrapped by a
        # DimensionTransform.

        self.transformedSceneNode = Node("transformedScene")
        self.transformedSceneTranslate = Translate()
        self.transformedSceneNode.addState(self.transformedSceneTranslate)

        self.transformedWorldScene = None
        self.addChild(self.transformedSceneNode)

        box = BoundingBox(pendingImport.importPos, pendingImport.importBounds.size)

        if hasHandle:
            # handleNode displays a bounding box that can be moved around, and responds
            # to mouse events.
            self.handleNode = BoxHandle()
            self.handleNode.bounds = box
            self.handleNode.resizable = False
            self.boxNode = None
        else:
            # boxNode displays a plain, non-movable bounding box
            self.boxNode = SelectionBoxNode()
            self.boxNode.wireColor = (1, 1, 1, .2)
            self.boxNode.filled = False
            self.handleNode = None
            self.addChild(self.boxNode)

        self.updateTransformedScene()
        self.basePosition = pendingImport.basePosition

        if hasHandle:
            self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
            self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

            self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(self.worldScene,
                                  list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
        self.pendingImport.scaleChanged.connect(self.setScale)

    # Emitted when the user finishes dragging the box handle and releases the mouse
    # button. Arguments are (newPosition, oldPosition).
    importMoved = QtCore.Signal(object, object)

    # Emitted while the user is dragging the box handle. Argument is the box origin.
    importIsMoving = QtCore.Signal(object)

    def handleBoundsChangedDone(self, bounds, oldBounds):
        point = self.getBaseFromTransformed(bounds.origin)
        oldPoint = self.getBaseFromTransformed(oldBounds.origin)
        if point != oldPoint:
            self.importMoved.emit(point, oldPoint)

    def handleBoundsChanged(self, bounds):
        log.info("handleBoundsChanged: %s", bounds)
        self.setPreviewBasePosition(bounds.origin)

    def setPreviewBasePosition(self, origin):
        point = self.getBaseFromTransformed(origin)
        if self.basePosition != point:
            self.basePosition = point
            self.importIsMoving.emit(point)

    def getBaseFromTransformed(self, point):
        return point - self.pendingImport.transformOffset

    def setPreviewRotation(self, rots):
        self.plainSceneNode.visible = True
        self.transformedSceneNode.visible = False
        self.rotateNode.setRotation(rots)

    def setRotation(self, rots):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.rotateNode.setRotation(rots)

    def setPreviewScale(self, scale):
        self.plainSceneNode.visible = True
        self.transformedSceneNode.visible = False
        self.scaleNode.setScale(scale)

    def setScale(self, scale):
        self.updateTransformedScene()
        self.updateBoxHandle()
        self.scaleNode.setScale(scale)

    def updateTransformedScene(self):
        if self.pendingImport.transformedDim is not None:
            log.info("Showing transformed scene")
            self.plainSceneNode.visible = False
            self.transformedSceneNode.visible = True

            if self.transformedWorldScene:
                self.transformedSceneNode.removeChild(self.transformedWorldScene)

            self.transformedWorldScene = WorldScene(self.pendingImport.transformedDim,
                                                    self.textureAtlas)
            self.transformedWorldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer
            self.transformedSceneNode.addChild(self.transformedWorldScene)

            self.updateTransformedPosition()

            cPos = list(self.pendingImport.transformedDim.chunkPositions())
            self.loader = WorldLoader(self.transformedWorldScene,
                                      cPos)

            # ALERT!: self.hasHandle is overloaded with the meaning:
            #  "not the first clone in a repeated clone"
            self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        else:
            log.info("Hiding transformed scene")
            self.plainSceneNode.visible = True
            self.transformedSceneNode.visible = False
            if self.transformedWorldScene:
                self.transformedSceneNode.removeChild(self.transformedWorldScene)
                self.transformedWorldScene = None

    def updateTransformedPosition(self):
        self.transformedPosition = self.basePosition + self.pendingImport.transformOffset
        self.transformedSceneTranslate.translateOffset = self.transformedPosition - self.pendingImport.importDim.bounds.origin

    def updateBoxHandle(self):
        if self.transformedWorldScene is None:
            bounds = BoundingBox(self.basePosition, self.pendingImport.bounds.size)
        else:
            origin = self.transformedPosition
            bounds = BoundingBox(origin, self.pendingImport.importBounds.size)
        #if self.handleNode.bounds.size != bounds.size:
        if self.hasHandle:
            self.handleNode.bounds = bounds
        else:
            self.boxNode.selectionBox = bounds

    @property
    def basePosition(self):
        return self.positionTranslate.translateOffset

    @basePosition.setter
    def basePosition(self, value):
        value = Vector(*value)
        if value == self.positionTranslate.translateOffset:
            return

        self.positionTranslate.translateOffset = value
        self.updateTransformedPosition()
        self.updateBoxHandle()

    def setPosition(self, pos):
        self.basePosition = pos

    # --- Mouse events ---

    # inherit from BoxHandle?
    def mouseMove(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mouseMove(event)

    def mousePress(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mousePress(event)

    def mouseRelease(self, event):
        if not self.hasHandle:
            return
        self.handleNode.mouseRelease(event)
示例#22
0
文件: generate.py 项目: wcpe/mcedit2
    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.livePreview = False
        self.blockPreview = False
        self.glPreview = True

        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [
            pluginClass(self)
            for pluginClass in GeneratePlugins.registeredPlugins
        ]
        self.currentGenerator = None
        if len(self.generatorTypes):
            self.currentGenerator = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        self.generatorTypesChanged()

        self.generatorTypeInput.currentIndexChanged.connect(
            self.currentTypeChanged)

        self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview")
        self.livePreviewCheckbox.setChecked(self.livePreview)
        self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled)

        self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview")
        self.blockPreviewCheckbox.setChecked(self.blockPreview)
        self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled)

        self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview")
        self.glPreviewCheckbox.setChecked(self.glPreview)
        self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled)

        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                         QtGui.QSizePolicy.Expanding)

        self.generateButton = QtGui.QPushButton(self.tr("Generate"))
        self.generateButton.clicked.connect(self.generateClicked)

        column.append(self.generatorTypeInput)
        column.append(self.livePreviewCheckbox)
        column.append(self.blockPreviewCheckbox)
        column.append(self.glPreviewCheckbox)
        column.append(self.optionsHolder)
        column.append(self.generateButton)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenenode.Node("generateOverlay")

        self.sceneHolderNode = Node("sceneHolder")
        self.sceneTranslate = Translate()
        self.sceneHolderNode.addState(self.sceneTranslate)

        self.overlayNode.addChild(self.sceneHolderNode)

        self.previewNode = None

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None
        self.loader = None

        self.previewBounds = None
        self.schematicBounds = None
        self.currentSchematic = None

        self.currentTypeChanged(0)

        # Name of last selected generator plugin is saved after unloading
        # so it can be reselected if it is immediately reloaded
        self._lastTypeName = None

        GeneratePlugins.pluginAdded.connect(self.addPlugin)
        GeneratePlugins.pluginRemoved.connect(self.removePlugin)
示例#23
0
文件: imports.py 项目: mcedit/mcedit2
    def __init__(self, pendingImport, textureAtlas, hasHandle=True):
        """
        A scenegraph node displaying an object that will be imported later, including
        live and deferred views of the object with transformed items, and a BoxHandle
        for moving the item.

        Parameters
        ----------

        pendingImport: PendingImport
            The object to be imported. The PendingImportNode responds to changes in this
            object's position, rotation, and scale.
        textureAtlas: TextureAtlas
            The textures and block models used to render the preview of the object.
        hasHandle: bool
            True if this import node should have a user-interactive BoxHandle associated
            with it. This is False for the extra copies displayed by a repeated clone.

        Attributes
        ----------

        basePosition: Vector
            The pre-transform position of the pending import. This is equal to
            `self.pendingImport.basePosition` except when the node is currently being
            dragged.
        transformedPosition: Vector
            The post-transform position of the pending import. This is equal to
            `self.pendingImport.importPos` except when the node is currently being
            dragged, scaled, or rotated.
        """
        super(PendingImportNode, self).__init__()

        self.textureAtlas = textureAtlas
        self.pendingImport = pendingImport
        self.hasHandle = hasHandle

        dim = pendingImport.sourceDim

        self.transformedPosition = Vector(0, 0, 0)

        # worldScene is contained by rotateNode, and
        # translates the world scene back to 0, 0, 0 so the rotateNode can
        # rotate it around the anchor, and the plainSceneNode can translate
        # it to the current position.

        self.worldScene = WorldScene(dim, textureAtlas, bounds=pendingImport.selection)
        self.worldScene.depthOffset.depthOffset = DepthOffsets.PreviewRenderer

        self.worldSceneTranslate = Translate(-self.pendingImport.selection.origin)
        self.worldScene.addState(self.worldSceneTranslate)

        # rotateNode is used to rotate the non-transformed preview during live rotation

        self.rotateNode = Rotate3DNode()
        self.rotateNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.rotateNode.addChild(self.worldScene)

        self.scaleNode = Scale3DNode()
        self.scaleNode.setAnchor(self.pendingImport.selection.size * 0.5)
        self.scaleNode.addChild(self.rotateNode)

        # plainSceneNode 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.plainSceneNode = Node("plainScene")
        self.positionTranslate = Translate()
        self.plainSceneNode.addState(self.positionTranslate)
        self.plainSceneNode.addChild(self.scaleNode)

        self.addChild(self.plainSceneNode)

        # transformedSceneNode contains the transformed preview of the imported
        # object, including a world scene that displays the object wrapped by a
        # DimensionTransform.

        self.transformedSceneNode = Node("transformedScene")
        self.transformedSceneTranslate = Translate()
        self.transformedSceneNode.addState(self.transformedSceneTranslate)

        self.transformedWorldScene = None
        self.addChild(self.transformedSceneNode)

        box = BoundingBox(pendingImport.importPos, pendingImport.importBounds.size)

        if hasHandle:
            # handleNode displays a bounding box that can be moved around, and responds
            # to mouse events.
            self.handleNode = BoxHandle()
            self.handleNode.bounds = box
            self.handleNode.resizable = False
            self.boxNode = None
        else:
            # boxNode displays a plain, non-movable bounding box
            self.boxNode = SelectionBoxNode()
            self.boxNode.wireColor = (1, 1, 1, .2)
            self.boxNode.filled = False
            self.handleNode = None
            self.addChild(self.boxNode)

        self.updateTransformedScene()
        self.basePosition = pendingImport.basePosition

        if hasHandle:
            self.handleNode.boundsChanged.connect(self.handleBoundsChanged)
            self.handleNode.boundsChangedDone.connect(self.handleBoundsChangedDone)

            self.addChild(self.handleNode)

        # loads the non-transformed world scene asynchronously.
        self.loader = WorldLoader(self.worldScene,
                                  list(pendingImport.selection.chunkPositions()))
        self.loader.startLoader(0.1 if self.hasHandle else 0.0)

        self.pendingImport.positionChanged.connect(self.setPosition)
        self.pendingImport.rotationChanged.connect(self.setRotation)
        self.pendingImport.scaleChanged.connect(self.setScale)
示例#24
0
class SelectionTool(EditorTool):
    name = "Select"
    iconName = "select_blocks"

    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget()
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.toolWidget.setLayout(Column(self.coordInput,
                                         self.shapeInput,
                                         None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenegraph.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        editorSession.dimensionChanged.connect(self.dimensionDidChange)

    def dimensionDidChange(self):
        self.selectionNode.dimension = self.editorSession.currentDimension

    def shapeDidChange(self):
        if self.currentSelection is not None:
            self.currentSelection = self.createShapedSelection(self.currentSelection)

    def toolActive(self):
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .5

    def toolInactive(self):
        self.faceHoverNode.visible = False
        self.boxHandleNode.boxNode.wireColor = 1, 1, 1, .33

    @property
    def hideSelectionWalls(self):
        return not self.selectionNode.filled

    @hideSelectionWalls.setter
    def hideSelectionWalls(self, value):
        self.selectionNode.filled = not value

    @property
    def currentSelection(self):
        return self.editorSession.currentSelection

    @currentSelection.setter
    def currentSelection(self, value):
        self.editorSession.currentSelection = value

    def coordInputChanged(self, box):
        self.currentSelection = self.createShapedSelection(box)

    def selectionDidChange(self, value):
        self.coordInput.boundingBox = value
        self.updateNodes()

    def updateNodes(self):
        box = self.currentSelection
        if box:
            self.boxHandleNode.bounds = BoundingBox(box.origin, box.size)
            self.selectionNode.visible = True
            self.selectionNode.selection = box
        else:
            self.boxHandleNode.bounds = None
            self.selectionNode.visible = False
            self.faceHoverNode.visible = False

    def boxHandleResized(self, box):
        if box is not None:
            self.selectionNode.selection = self.createShapedSelection(box)

    def boxHandleResizedDone(self, box, newSelection):
        if box is not None:
            selection = self.createShapedSelection(box)
            command = SelectCommand(self.editorSession, selection)
            if not newSelection:
                command.setText(self.tr("Resize Selection"))
            self.editorSession.undoStack.push(command)
            self.updateNodes()

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.mouseDrag(event)

    def mouseDrag(self, event):
        # Update cursor
        self.cursorNode.point = event.blockPosition
        self.cursorNode.face = event.blockFace

        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)


    selectionColor = (0.8, 0.8, 1.0)
    alpha = 0.33

    showPreviousSelection = True

    def createShapedSelection(self, box):
        if self.shapeInput.currentShape is shapewidget.Square:
            return box
        else:
            return selection.ShapedSelection(box, self.shapeInput.currentShape.shapeFunc)
示例#25
0
class GenerateTool(EditorTool):
    name = "Generate"
    iconName = "generate"

    instantDisplayChunks = 32

    def __init__(self, *args, **kwargs):
        EditorTool.__init__(self, *args, **kwargs)
        self.createToolWidget()

    def createToolWidget(self):
        toolWidget = QtGui.QWidget()

        self.toolWidget = toolWidget

        column = []
        self.generatorTypes = [TreeGen()]
        self.currentType = self.generatorTypes[0]

        self.generatorTypeInput = QtGui.QComboBox()
        for gt in self.generatorTypes:
            self.generatorTypeInput.addItem(gt.displayName, gt)

        self.generatorTypeInput.currentIndexChanged.connect(
            self.generatorTypeChanged)
        self.optionsHolder = QtGui.QStackedWidget()
        self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                         QtGui.QSizePolicy.Expanding)

        column.append(self.generatorTypeInput)
        column.append(self.optionsHolder)

        self.toolWidget.setLayout(Column(*column))

        self.overlayNode = scenegraph.Node()

        self.sceneHolderNode = scenegraph.TranslateNode()
        self.overlayNode.addChild(self.sceneHolderNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boundsDidChange)
        self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.worldScene = None

        self.schematicBounds = None

    def generatorTypeChanged(self, index):
        self.currentType = self.generatorTypes[index]
        self.optionsHolder.removeWidget(self.optionsHolder.widget(0))
        self.optionsHolder.addWidget(self.currentType.getOptionsWidget())

    def mousePress(self, event):
        self.boxHandleNode.mousePress(event)

    def mouseMove(self, event):
        self.boxHandleNode.mouseMove(event)

    def mouseRelease(self, event):
        self.boxHandleNode.mouseRelease(event)

    def boundsDidChange(self, bounds):
        if bounds is not None and bounds.volume:
            node = self.currentType.getPreviewNode()
            if node is not None:
                pass
            else:

                if self.schematicBounds is None or self.schematicBounds.size != bounds.size:
                    schematic = self.currentType.generatePreview(
                        bounds, self.editorSession.worldEditor.blocktypes)
                    self.displaySchematic(schematic, bounds.origin)
                else:
                    self.sceneHolderNode.translateOffset = bounds.origin

        self.schematicBounds = bounds

    def boundsDidChangeDone(self, bounds, newSelection):
        if bounds is not None and bounds.volume:
            if self.schematicBounds is None or self.schematicBounds.size != bounds.size:
                schematic = self.currentType.generate(
                    bounds, self.editorSession.worldEditor.blocktypes)
                offset = bounds.origin
                self.displaySchematic(schematic, offset)
            else:
                self.sceneHolderNode.translateOffset = bounds.origin
        else:
            self.displaySchematic(None, None)

        self.schematicBounds = bounds

    def displaySchematic(self, schematic, offset):
        if schematic is not None:
            dim = schematic.getDimension()

            if self.worldScene:
                self.sceneHolderNode.removeChild(self.worldScene)
                self.loader.timer.stop()
                self.loader = None

            atlas = self.editorSession.textureAtlas
            self.worldScene = WorldScene(dim, atlas)
            self.sceneHolderNode.translateOffset = offset
            self.sceneHolderNode.addChild(self.worldScene)

            self.loader = WorldLoader(self.worldScene)
            if dim.chunkCount() <= self.instantDisplayChunks:
                for _ in self.loader.work():
                    pass
            else:
                self.loader.timer.start()
        else:
            if self.worldScene:
                self.sceneHolderNode.removeChild(self.worldScene)
                self.worldScene = None
                self.loader.timer.stop()
                self.loader = None