Ejemplo n.º 1
0
    def deleteAll(self, only_selectable = True) -> None:
        Logger.log("i", "Clearing scene")
        if not self.getController().getToolsEnabled():
            return

        nodes = []
        for node in DepthFirstIterator(self.getController().getScene().getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
            if not isinstance(node, SceneNode):
                continue
            if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
                continue  # Node that doesnt have a mesh and is not a group.
            if only_selectable and not node.isSelectable():
                continue
            if not node.callDecoration("isSliceable") and not node.callDecoration("getLayerData") and not node.callDecoration("isGroup"):
                continue  # Only remove nodes that are selectable.
            if node.getParent() and cast(SceneNode, node.getParent()).callDecoration("isGroup"):
                continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
            nodes.append(node)
        if nodes:
            op = GroupedOperation()

            for node in nodes:
                op.addOperation(RemoveSceneNodeOperation(node))

                # Reset the print information
                self.getController().getScene().sceneChanged.emit(node)

            op.push()
            Selection.clear()
Ejemplo n.º 2
0
 def getZ(self):
     # We want to display based on the bottom instead of the actual coordinate.
     if Selection.hasSelection():
         # Note; The switching of z & y is intentional. We display z as up for the user,
         # But store the data in openGL space.
         return float(Selection.getBoundingBox().bottom)
     return 0.0
Ejemplo n.º 3
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()
        renderer.setRenderSelection(False)

        if not self._material:
            self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag"))
            self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])

            self._selection_material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
            self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))

        for node in DepthFirstIterator(scene.getRoot()):
            # We do not want to render ConvexHullNode as it conflicts with the bottom layers.
            # However, it is somewhat relevant when the node is selected, so do render it then.
            if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()):
                continue

            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    if Selection.isSelected(node):
                        renderer.queueNode(node, material = self._selection_material, transparent = True)
                    layer_data = node.callDecoration("getLayerData")
                    if not layer_data:
                        continue

                    # Render all layers below a certain number as line mesh instead of vertices.
                    if self._current_layer_num - self._solid_layers > -1:
                        start = 0
                        end = 0
                        element_counts = layer_data.getElementCounts()
                        for layer, counts in element_counts.items():
                            if layer + self._solid_layers > self._current_layer_num:
                                break
                            end += counts

                        # This uses glDrawRangeElements internally to only draw a certain range of lines.
                        renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end)

                    # We currently recreate the current "solid" layers every time a
                    if not self._current_layer_mesh:
                        self._current_layer_mesh = MeshData()
                        for i in range(self._solid_layers):
                            layer = self._current_layer_num - i
                            if layer < 0:
                                continue

                            layer_mesh = layer_data.getLayer(layer).createMesh()
                            if not layer_mesh or layer_mesh.getVertices() is None:
                                continue

                            self._current_layer_mesh.addVertices(layer_mesh.getVertices())

                            # Scale layer color by a brightness factor based on the current layer number
                            # This will result in a range of 0.5 - 1.0 to multiply colors by.
                            brightness = (2.0 - (i / self._solid_layers)) / 2.0
                            self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness)

                    renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material)
Ejemplo n.º 4
0
    def requestWriteSelectionToDevice(self, device_id, file_name):
        if not Selection.hasSelection():
            return

        # On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal
        # handler attached to a QML MenuItem. So instead, defer the call to the next run of the event 
        # loop, since that does work.
        event = CallFunctionEvent(self._writeToDevice, [Selection.getSelectedObject(0), device_id, file_name], {})
        Application.getInstance().functionEvent(event)
Ejemplo n.º 5
0
    def event(self, event):
        super().event(event)

        if event.type == Event.MousePressEvent and self._controller.getToolsEnabled():
            # Initialise a mirror operation
            if MouseEvent.LeftButton not in event.buttons:
                return False

            id = self._selection_pass.getIdAtPosition(event.x, event.y)
            if not id:
                return False

            if self._handle.isAxis(id):
                self.setLockedAxis(id)
                self._operation_started = True
                self.operationStarted.emit(self)
                return True

        if event.type == Event.MouseReleaseEvent:
            if self._operation_started:
                self._operation_started = False
                self.operationStopped.emit(self)

            # Perform a mirror operation
            if self.getLockedAxis() != ToolHandle.NoAxis:
                if Selection.getCount() == 1:
                    node = Selection.getSelectedObject(0)
                    if self.getLockedAxis() == ToolHandle.XAxis:
                        mirror = Vector(-1, 1, 1)
                    elif self.getLockedAxis() == ToolHandle.YAxis:
                        mirror = Vector(1, -1, 1)
                    elif self.getLockedAxis() == ToolHandle.ZAxis:
                        mirror = Vector(1, 1, -1)
                    else:
                        mirror = Vector(1, 1, 1)
                    op = MirrorOperation(node, mirror, mirror_around_center = True)
                else:
                    op = GroupedOperation()

                    for node in self._getSelectedObjectsWithoutSelectedAncestors():
                        if self.getLockedAxis() == ToolHandle.XAxis:
                            mirror = Vector(-1, 1, 1)
                        elif self.getLockedAxis() == ToolHandle.YAxis:
                            mirror = Vector(1, -1, 1)
                        elif self.getLockedAxis() == ToolHandle.ZAxis:
                            mirror = Vector(1, 1, -1)
                        else:
                            mirror = Vector(1, 1, 1)

                        op.addOperation(MirrorOperation(node, mirror, mirror_around_center = True))

                op.push()

                self.setLockedAxis(ToolHandle.NoAxis)
                return True

        return False
Ejemplo n.º 6
0
    def requestWriteSelectionToDevice(self, device_id, file_name, kwargs):
        if not Selection.hasSelection():
            return

        filter_by_machine = kwargs.get("filter_by_machine", False)
        # On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal
        # handler attached to a QML MenuItem. So instead, defer the call to the next run of the event 
        # loop, since that does work.
        Application.getInstance().callLater(self._writeToDevice, Selection.getSelectedObject(0), device_id, file_name, filter_by_machine)
Ejemplo n.º 7
0
    def removeSelection(self):
        if not Selection.hasSelection():
            return

        op = GroupedOperation()
        for node in Selection.getAllSelectedObjects():
            op.addOperation(RemoveSceneNodeOperation(node))
        op.push()
        Selection.clear()
Ejemplo n.º 8
0
    def requestWriteSelectionToDevice(self, device_id: str, file_name: str, kwargs: Mapping[str, str]) -> None:
        if not Selection.hasSelection():
            return

        limit_mimetypes = kwargs.get("limit_mimetypes", False)
        preferred_mimetypes = kwargs.get("preferred_mimetypes", None)
        # On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal
        # handler attached to a QML MenuItem. So instead, defer the call to the next run of the event 
        # loop, since that does work.
        Application.getInstance().callLater(self._writeToDevice, Selection.getAllSelectedObjects(), device_id, file_name, limit_mimetypes, preferred_mimetypes = preferred_mimetypes)
Ejemplo n.º 9
0
    def setActiveBuildPlate(self, nr):
        if nr == self._active_build_plate:
            return
        Logger.log("d", "Select build plate: %s" % nr)
        self._active_build_plate = nr
        Selection.clear()

        self._multi_build_plate_model.setActiveBuildPlate(nr)
        self._objects_model.setActiveBuildPlate(nr)
        self.activeBuildPlateChanged.emit()
Ejemplo n.º 10
0
    def test_selectionCount(self):
        assert self.proxy.selectionCount == 0

        node_1 = SceneNode()
        Selection.add(node_1)
        assert self.proxy.selectionCount == 1

        node_2 = SceneNode()
        Selection.add(node_2)
        assert self.proxy.selectionCount == 2
Ejemplo n.º 11
0
    def setX(self, x):
        bounding_box = Selection.getBoundingBox()

        op = GroupedOperation()
        for selected_node in Selection.getAllSelectedObjects():
            world_position = selected_node.getWorldPosition()
            new_position = world_position.set(x=float(x) + (world_position.x - bounding_box.center.x))
            node_op = TranslateOperation(selected_node, new_position, set_position = True)
            op.addOperation(node_op)
        op.push()
        self.operationStopped.emit(self)
Ejemplo n.º 12
0
    def test_hasSelection(self):
        # Nothing is selected by default
        assert not self.proxy.hasSelection

        node_1 = SceneNode()
        Selection.add(node_1)

        assert self.proxy.hasSelection

        Selection.remove(node_1)
        assert not self.proxy.hasSelection
Ejemplo n.º 13
0
 def _onChildrenChanged(self, node):
     if not self.getNode().hasChildren():
         # A group that no longer has children may remove itself from the scene
         self._old_parent = self.getNode().getParent()
         self.getNode().setParent(None)
         Selection.remove(self.getNode())
     else:
         # A group that has removed itself from the scene because it had no children may add itself back to the scene when a child is added to it
         if not self.getNode().getParent() and self._old_parent:
             self.getNode().setParent(self._old_parent)
             self._old_parent = None
Ejemplo n.º 14
0
 def setScaleX(self, scale):
     obj = Selection.getSelectedObject(0)
     if obj:
         obj_scale = self._getScaleInWorldCoordinates(obj)
         if round(float(obj_scale.x), 4) != scale:
             scale_factor = abs(scale / obj_scale.x)
             if self._non_uniform_scale:
                 scale_vector = Vector(scale_factor, 1, 1)
             else:
                 scale_vector = Vector(scale_factor, scale_factor, scale_factor)
             Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
Ejemplo n.º 15
0
 def setScaleZ(self, scale):
     obj = Selection.getSelectedObject(0)
     if obj:
         obj_scale = self._getScaleInWorldCoordinates(obj)
         if round(float(obj_scale.z), 4) != scale:
             scale_factor = abs(scale / obj_scale.z)
             if self._non_uniform_scale:
                 scale_vector = Vector(1, 1, scale_factor)
             else:
                 scale_vector = Vector(scale_factor, scale_factor, scale_factor)
             Selection.applyOperation(ScaleOperation, scale_vector)
Ejemplo n.º 16
0
    def onSelectionChanged(self):
        if Selection.hasSelection():
            if not self.getController().getActiveTool():
                self.getController().setActiveTool("TranslateTool")

            self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
            self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
            self._camera_animation.start()
        else:
            if self.getController().getActiveTool():
                self.getController().setActiveTool(None)
Ejemplo n.º 17
0
def test_UndoRedoWithSelection():
    node = SceneNode()
    parent_node = SceneNode()
    Selection.add(node)

    operation = AddSceneNodeOperation(node, parent_node)
    operation.undo()

    assert not Selection.isSelected(node)

    operation.redo()
    assert Selection.isSelected(node)
Ejemplo n.º 18
0
 def setObjectWidth(self, width):
     obj = Selection.getSelectedObject(0)
     if obj:
         width = float(width)
         obj_width = obj.getBoundingBox().width
         if not Float.fuzzyCompare(obj_width, width, DIMENSION_TOLERANCE):
             scale_factor = width / obj_width
             if self._non_uniform_scale:
                 scale_vector = Vector(scale_factor, 1, 1)
             else:
                 scale_vector = Vector(scale_factor, scale_factor, scale_factor)
             Selection.applyOperation(ScaleOperation, scale_vector, scale_around_point = obj.getWorldPosition())
Ejemplo n.º 19
0
 def setObjectHeight(self, height):
     obj = Selection.getSelectedObject(0)
     if obj:
         height = float(height)
         obj_height = obj.getBoundingBox().height
         if not Float.fuzzyCompare(obj_height, height, DIMENSION_TOLERANCE):
             scale_factor = height / obj_height
             if self._non_uniform_scale:
                 scale_vector = Vector(1, scale_factor, 1)
             else:
                 scale_vector = Vector(scale_factor, scale_factor, scale_factor)
             Selection.applyOperation(ScaleOperation, scale_vector)
Ejemplo n.º 20
0
 def setObjectDepth(self, depth):
     obj = Selection.getSelectedObject(0)
     if obj:
         depth = float(depth)
         obj_depth = obj.getBoundingBox().depth
         if not Float.fuzzyCompare(obj_depth, depth, DIMENSION_TOLERANCE):
             scale_factor = depth / obj_depth
             if self._non_uniform_scale:
                 scale_vector = Vector(1, 1, scale_factor)
             else:
                 scale_vector = Vector(scale_factor, scale_factor, scale_factor)
             Selection.applyOperation(ScaleOperation, scale_vector)
Ejemplo n.º 21
0
    def _removeEraserMesh(self, node: CuraSceneNode):
        parent = node.getParent()
        if parent == self._controller.getScene().getRoot():
            parent = None

        op = RemoveSceneNodeOperation(node)
        op.push()

        if parent and not Selection.isSelected(parent):
            Selection.add(parent)

        CuraApplication.getInstance().getController().getScene().sceneChanged.emit(node)
Ejemplo n.º 22
0
    def setZ(self, z):
        bounding_box = Selection.getBoundingBox()

        op = GroupedOperation()
        for selected_node in Selection.getAllSelectedObjects():
            # Note: The switching of z & y is intentional. We display z as up for the user,
            # But store the data in openGL space.
            world_position = selected_node.getWorldPosition()
            new_position = world_position.set(y=float(z) + (world_position.y - bounding_box.bottom))
            node_op = TranslateOperation(selected_node, new_position, set_position = True)
            op.addOperation(node_op)
        op.push()
        self.operationStopped.emit(self)
Ejemplo n.º 23
0
 def groupSelected(self):
     group_node = SceneNode()
     group_decorator = GroupDecorator()
     group_node.addDecorator(group_decorator)
     group_node.setParent(self.getController().getScene().getRoot())
     
     for node in Selection.getAllSelectedObjects():
         node.setParent(group_node)
     
     for node in group_node.getChildren():
         Selection.remove(node)
     
     Selection.add(group_node)
Ejemplo n.º 24
0
    def setX(self, x):
        parsed_x = self._parseInt(x)
        bounding_box = Selection.getBoundingBox()

        op = GroupedOperation()
        if not Float.fuzzyCompare(parsed_x, float(bounding_box.center.x), DIMENSION_TOLERANCE):
            for selected_node in Selection.getAllSelectedObjects():
                world_position = selected_node.getWorldPosition()
                new_position = world_position.set(x=parsed_x + (world_position.x - bounding_box.center.x))
                node_op = TranslateOperation(selected_node, new_position, set_position = True)
                op.addOperation(node_op)
            op.push()
        self._controller.toolOperationStopped.emit(self)
Ejemplo n.º 25
0
    def selectAll(self):
        if not self.getController().getToolsEnabled():
            return

        Selection.clear()
        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
            if type(node) is not SceneNode:
                continue
            if not node.getMeshData() and not node.callDecoration("isGroup"):
                continue  # Node that doesnt have a mesh and is not a group.
            if node.getParent() and node.getParent().callDecoration("isGroup"):
                continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
            Selection.add(node)
Ejemplo n.º 26
0
    def event(self, event):
        super().event(event)

        if event.type == Event.MousePressEvent:
            if MouseEvent.LeftButton not in event.buttons:
                return False

            id = self._selection_pass.getIdAtPosition(event.x, event.y)
            if not id:
                return False

            if ToolHandle.isAxis(id):
                self.setLockedAxis(id)
                return True

        if event.type == Event.MouseReleaseEvent:
            if self.getLockedAxis():
                op = None
                if Selection.getCount() == 1:
                    node = Selection.getSelectedObject(0)
                    mirror = node.getMirror()
                    if self.getLockedAxis() == ToolHandle.XAxis:
                        mirror.setX(-mirror.x)
                    elif self.getLockedAxis() == ToolHandle.YAxis:
                        mirror.setY(-mirror.y)
                    elif self.getLockedAxis() == ToolHandle.ZAxis:
                        mirror.setZ(-mirror.z)

                    op = MirrorOperation(node, mirror, set_mirror=True)
                else:
                    op = GroupedOperation()

                    for node in Selection.getAllSelectedObjects():
                        mirror = node.getMirror()
                        if self.getLockedAxis() == ToolHandle.XAxis:
                            mirror.setX(-mirror.x)
                        elif self.getLockedAxis() == ToolHandle.YAxis:
                            mirror.setY(-mirror.y)
                        elif self.getLockedAxis() == ToolHandle.ZAxis:
                            mirror.setZ(-mirror.z)

                        op.addOperation(MirrorOperation(node, mirror, set_mirror = True))

                op.push()

                self.setLockedAxis(None)
                return True

        return False
Ejemplo n.º 27
0
    def event(self, event):
        super().event(event)

        if event.type == Event.MousePressEvent:
            if MouseEvent.LeftButton not in event.buttons:
                return False

            id = self._renderer.getIdAtCoordinate(event.x, event.y)
            if not id:
                return False

            if ToolHandle.isAxis(id):
                self.setLockedAxis(id)
                return True

        if event.type == Event.MouseReleaseEvent:
            if self.getLockedAxis():
                op = None
                if Selection.getCount() == 1:
                    node = Selection.getSelectedObject(0)
                    scale = node.getScale()
                    if self.getLockedAxis() == ToolHandle.XAxis:
                        scale.setX(-scale.x)
                    elif self.getLockedAxis() == ToolHandle.YAxis:
                        scale.setY(-scale.y)
                    elif self.getLockedAxis() == ToolHandle.ZAxis:
                        scale.setZ(-scale.z)

                    op = ScaleOperation(node, scale, set_scale=True)
                else:
                    op = GroupedOperation()

                    for node in Selection.getAllSelectedObjects():
                        scale = node.getScale()
                        if self.getLockedAxis() == ToolHandle.XAxis:
                            scale.setX(-scale.x)
                        elif self.getLockedAxis() == ToolHandle.YAxis:
                            scale.setY(-scale.y)
                        elif self.getLockedAxis() == ToolHandle.ZAxis:
                            scale.setZ(-scale.z)

                        op.addOperation(ScaleOperation(node, scale, set_scale = True))

                op.push()

                self.setLockedAxis(None)
                return True

        return False
Ejemplo n.º 28
0
    def setZ(self, z):
        parsed_z = self._parseInt(z)
        bounding_box = Selection.getBoundingBox()

        op = GroupedOperation()
        if not Float.fuzzyCompare(parsed_z, float(bounding_box.center.y), DIMENSION_TOLERANCE):
            for selected_node in Selection.getAllSelectedObjects():
                # Note: The switching of z & y is intentional. We display z as up for the user,
                # But store the data in openGL space.
                world_position = selected_node.getWorldPosition()
                new_position = world_position.set(y=parsed_z + (world_position.y - bounding_box.bottom))
                node_op = TranslateOperation(selected_node, new_position, set_position = True)
                op.addOperation(node_op)
            op.push()
        self._controller.toolOperationStopped.emit(self)
Ejemplo n.º 29
0
 def groupSelected(self):
     group_node = SceneNode()
     group_decorator = GroupDecorator()
     group_node.addDecorator(group_decorator)
     group_node.setParent(self.getController().getScene().getRoot())
     
     for node in Selection.getAllSelectedObjects():
         node.setParent(group_node)
     group_node.setCenterPosition(group_node.getBoundingBox().center)
     #group_node.translate(Vector(0,group_node.getBoundingBox().center.y,0))
     group_node.translate(group_node.getBoundingBox().center)
     for node in group_node.getChildren():
         Selection.remove(node)
     
     Selection.add(group_node)
Ejemplo n.º 30
0
    def updateList(self, trigger_node):
        self.clear()
        for root_child in self._scene.getRoot().getChildren():
            if root_child.callDecoration("isGroup"): # Check if its a group node
                parent_key = id(root_child)
                for node in DepthFirstIterator(root_child):
                    if root_child in self._collapsed_nodes:
                        self._collapsed_nodes.append(node)

                    data = {"name":node.getName(),
                            "visibility": node.isVisible(),
                            "key": (id(node)),
                            "selected": Selection.isSelected(node),
                            "collapsed": node in self._collapsed_nodes,
                            "parent_key": parent_key,
                            "is_group":bool(node.callDecoration("isGroup")),
                            "is_dummy" : False
                            }
                    self.appendItem(data)
                data = { "name":"Dummy",
                         "visibility": True,
                         "key": 0,
                         "selected": Selection.isSelected(node),
                         "collapsed": root_child in self._collapsed_nodes,
                         "parent_key": parent_key,
                         "is_group":False,
                         "is_dummy" : True
                        }
                self.appendItem(data)

            elif type(root_child) is SceneNode or type(root_child) is PointCloudNode: # Item is not a group node.
                data = {"name":root_child.getName(),
                        "visibility": root_child.isVisible(),
                        "key": (id(root_child)),
                        "selected": Selection.isSelected(root_child),
                        "collapsed": root_child in self._collapsed_nodes,
                        "parent_key": 0,
                        "is_group":bool(root_child.callDecoration("isGroup")),
                        "is_dummy" : False
                        }

                # Check if data exists, if yes, remove old and re-add.
                index = self.find("key",(id(root_child)))
                if index is not None and index >= 0:
                    self.removeItem(index)
                    self.insertItem(index,data)
                else:
                    self.appendItem(data)
Ejemplo n.º 31
0
 def multiplySelection(self, count: int) -> None:
     job = MultiplyObjectsJob(Selection.getAllSelectedObjects(),
                              count,
                              min_offset=4)
     job.start()
Ejemplo n.º 32
0
    def _onChangeTimerFinished(self):
        if not self._enabled:
            return

        root = self._controller.getScene().getRoot()
        for node in BreadthFirstIterator(root):
            if node is root or type(node) is not SceneNode:
                continue

            bbox = node.getBoundingBox()
            if not bbox or not bbox.isValid():
                self._change_timer.start()
                continue

            build_volume_bounding_box = copy.deepcopy(
                self._build_volume.getBoundingBox())
            build_volume_bounding_box.setBottom(
                -9001)  # Ignore intersections with the bottom

            # Mark the node as outside the build volume if the bounding box test fails.
            if build_volume_bounding_box.intersectsBox(
                    bbox
            ) != AxisAlignedBox.IntersectionResult.FullIntersection:
                node._outside_buildarea = True
            else:
                node._outside_buildarea = False

            # Move it downwards if bottom is above platform
            move_vector = Vector()
            if bbox.bottom > 0:
                move_vector.setY(-bbox.bottom)
            #if not Float.fuzzyCompare(bbox.bottom, 0.0):
            #   pass#move_vector.setY(-bbox.bottom)

            # If there is no convex hull for the node, start calculating it and continue.
            if not node.getDecorator(ConvexHullDecorator):
                node.addDecorator(ConvexHullDecorator())

            if not node.callDecoration("getConvexHull"):
                if not node.callDecoration("getConvexHullJob"):
                    job = ConvexHullJob.ConvexHullJob(node)
                    job.start()
                    node.callDecoration("setConvexHullJob", job)

            elif Selection.isSelected(node):
                pass
            elif Preferences.getInstance().getValue(
                    "physics/automatic_push_free"):
                # Check for collisions between convex hulls
                for other_node in BreadthFirstIterator(root):
                    # Ignore root, ourselves and anything that is not a normal SceneNode.
                    if other_node is root or type(
                            other_node) is not SceneNode or other_node is node:
                        continue

                    # Ignore colissions of a group with it's own children
                    if other_node in node.getAllChildren(
                    ) or node in other_node.getAllChildren():
                        continue

                    # Ignore colissions within a group
                    if other_node.getParent().callDecoration(
                            "isGroup") is not None:
                        if node.getParent().callDecoration(
                                "isGroup") is other_node.getParent(
                                ).callDecoration("isGroup"):
                            continue

                    # Ignore nodes that do not have the right properties set.
                    if not other_node.callDecoration(
                            "getConvexHull") or not other_node.getBoundingBox(
                            ):
                        continue

                    # Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects.
                    #if node.getBoundingBox().intersectsBox(other_node.getBoundingBox()) == AxisAlignedBox.IntersectionResult.NoIntersection:
                    #    continue

                    # Get the overlap distance for both convex hulls. If this returns None, there is no intersection.
                    try:
                        overlap = node.callDecoration(
                            "getConvexHull").intersectsPolygon(
                                other_node.callDecoration("getConvexHull"))
                    except:
                        overlap = None  #It can sometimes occur that the caclulated convex hull has no size, in which case there is no overlap.

                    if overlap is None:
                        continue

                    move_vector.setX(overlap[0] * 1.1)
                    move_vector.setZ(overlap[1] * 1.1)
            convex_hull = node.callDecoration("getConvexHull")
            if convex_hull:
                if not convex_hull.isValid():
                    return
                # Check for collisions between disallowed areas and the object
                for area in self._build_volume.getDisallowedAreas():
                    overlap = convex_hull.intersectsPolygon(area)
                    if overlap is None:
                        continue

                    node._outside_buildarea = True

            if move_vector != Vector():
                op = PlatformPhysicsOperation.PlatformPhysicsOperation(
                    node, move_vector)
                op.push()
 def redo(self) -> None:
     self._node.setParent(self._parent)
     if self._selected:  # It was selected while the operation was undone. We should restore that selection.
         Selection.add(self._node)
Ejemplo n.º 34
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        self._checkSetup()

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack:
            if Application.getInstance().getPreferences().getValue(
                    "view/show_overhang"):
                # Make sure the overhang angle is valid before passing it to the shader
                if self._support_angle >= 0 and self._support_angle <= 90:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle",
                        math.cos(math.radians(90 - self._support_angle)))
                else:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(0))
                    )  #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle",
                                                     math.cos(math.radians(0)))
        self._enabled_shader.setUniformValue("u_lowestPrintableHeight",
                                             self._lowest_printable_height)
        disabled_batch = renderer.createRenderBatch(
            shader=self._disabled_shader)
        normal_object_batch = renderer.createRenderBatch(
            shader=self._enabled_shader)
        renderer.addRenderBatch(disabled_batch)
        renderer.addRenderBatch(normal_object_batch)
        for node in DepthFirstIterator(scene.getRoot()):
            if node.render(renderer):
                continue

            if node.getMeshData() and node.isVisible():
                uniforms = {}
                shade_factor = 1.0

                per_mesh_stack = node.callDecoration("getStack")

                extruder_index = node.callDecoration(
                    "getActiveExtruderPosition")
                if extruder_index is None:
                    extruder_index = "0"
                extruder_index = int(extruder_index)

                try:
                    material_color = self._extruders_model.getItem(
                        extruder_index)["color"]
                except KeyError:
                    material_color = self._extruders_model.defaultColors[0]

                if extruder_index != ExtruderManager.getInstance(
                ).activeExtruderIndex:
                    # Shade objects that are printed with the non-active extruder 25% darker
                    shade_factor = 0.6

                try:
                    # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                    # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                    uniforms["diffuse_color"] = [
                        shade_factor * int(material_color[1:3], 16) / 255,
                        shade_factor * int(material_color[3:5], 16) / 255,
                        shade_factor * int(material_color[5:7], 16) / 255, 1.0
                    ]

                    # Color the currently selected face-id. (Disable for now.)
                    #face = Selection.getHoverFace()
                    uniforms[
                        "hover_face"] = -1  #if not face or node != face[0] else face[1]
                except ValueError:
                    pass

                if node.callDecoration("isNonPrintingMesh"):
                    if per_mesh_stack and (
                            node.callDecoration("isInfillMesh")
                            or node.callDecoration("isCuttingMesh")):
                        renderer.queueNode(node,
                                           shader=self._non_printing_shader,
                                           uniforms=uniforms,
                                           transparent=True)
                    else:
                        renderer.queueNode(node,
                                           shader=self._non_printing_shader,
                                           transparent=True)
                elif getattr(node, "_outside_buildarea", False):
                    disabled_batch.addItem(
                        node.getWorldTransformation(copy=False),
                        node.getMeshData(),
                        normal_transformation=node.getCachedNormalMatrix())
                elif per_mesh_stack and node.callDecoration("isSupportMesh"):
                    # Render support meshes with a vertical stripe that is darker
                    shade_factor = 0.6
                    uniforms["diffuse_color_2"] = [
                        uniforms["diffuse_color"][0] * shade_factor,
                        uniforms["diffuse_color"][1] * shade_factor,
                        uniforms["diffuse_color"][2] * shade_factor, 1.0
                    ]
                    renderer.queueNode(node,
                                       shader=self._support_mesh_shader,
                                       uniforms=uniforms)
                else:
                    normal_object_batch.addItem(
                        node.getWorldTransformation(copy=False),
                        node.getMeshData(),
                        uniforms=uniforms,
                        normal_transformation=node.getCachedNormalMatrix())
            if node.callDecoration("isGroup") and Selection.isSelected(node):
                renderer.queueNode(scene.getRoot(),
                                   mesh=node.getBoundingBoxMesh(),
                                   mode=RenderBatch.RenderMode.LineLoop)
Ejemplo n.º 35
0
 def getX(self):
     if Selection.hasSelection():
         return float(Selection.getBoundingBox().center.x)
     return 0.0
Ejemplo n.º 36
0
 def getSelectedIndex(self):
     selected_object_id = id(Selection.getSelectedObject(0))
     index = self.getModel().find("id", selected_object_id)
     return index
Ejemplo n.º 37
0
    def getObjectHeight(self):
        if Selection.hasSelection():
            return float(Selection.getSelectedObject(0).getBoundingBox().height)

        return 0.0
Ejemplo n.º 38
0
    def getScaleZ(self):
        if Selection.hasSelection():
            return round(float(Selection.getSelectedObject(0).getScale().z), 4)

        return 1.0
Ejemplo n.º 39
0
 def getSelectedActiveExtruder(self):
     selected_object = Selection.getSelectedObject(0)
     return selected_object.callDecoration("getActiveExtruder")
Ejemplo n.º 40
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._extruders_model:
            self._extruders_model = Application.getInstance(
            ).getExtrudersModel()

        if not self._theme:
            self._theme = Application.getInstance().getTheme()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "overhang.shader"))
            self._enabled_shader.setUniformValue(
                "u_overhangColor",
                Color(*self._theme.getColor("model_overhang").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor1",
                Color(*self._theme.getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor2",
                Color(*self._theme.getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)

        if not self._non_printing_shader:
            self._non_printing_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders,
                                  "transparent_object.shader"))
            self._non_printing_shader.setUniformValue(
                "u_diffuseColor",
                Color(*self._theme.getColor("model_non_printing").getRgb()))
            self._non_printing_shader.setUniformValue("u_opacity", 0.6)

        if not self._support_mesh_shader:
            self._support_mesh_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._support_mesh_shader.setUniformValue("u_vertical_stripes",
                                                      True)
            self._support_mesh_shader.setUniformValue("u_width", 5.0)

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack:
            support_extruder_nr = global_container_stack.getExtruderPositionValueWithDefault(
                "support_extruder_nr")
            support_angle_stack = Application.getInstance().getExtruderManager(
            ).getExtruderStack(support_extruder_nr)

            if support_angle_stack is not None and Application.getInstance(
            ).getPreferences().getValue("view/show_overhang"):
                angle = support_angle_stack.getProperty(
                    "support_angle", "value")
                # Make sure the overhang angle is valid before passing it to the shader
                # Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None)
                if angle is not None and global_container_stack.getProperty(
                        "support_angle",
                        "validationState") in [None, ValidatorState.Valid]:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(90 - angle)))
                else:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(0))
                    )  #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle",
                                                     math.cos(math.radians(0)))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible(
                ) and not node.callDecoration("getLayerData"):
                    uniforms = {}
                    shade_factor = 1.0

                    per_mesh_stack = node.callDecoration("getStack")

                    extruder_index = node.callDecoration(
                        "getActiveExtruderPosition")
                    if extruder_index is None:
                        extruder_index = "0"
                    extruder_index = int(extruder_index)

                    # Use the support extruder instead of the active extruder if this is a support_mesh
                    if per_mesh_stack:
                        if per_mesh_stack.getProperty("support_mesh", "value"):
                            extruder_index = int(
                                global_container_stack.
                                getExtruderPositionValueWithDefault(
                                    "support_extruder_nr"))

                    try:
                        material_color = self._extruders_model.getItem(
                            extruder_index)["color"]
                    except KeyError:
                        material_color = self._extruders_model.defaultColors[0]

                    if extruder_index != ExtruderManager.getInstance(
                    ).activeExtruderIndex:
                        # Shade objects that are printed with the non-active extruder 25% darker
                        shade_factor = 0.6

                    try:
                        # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                        # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                        uniforms["diffuse_color"] = [
                            shade_factor * int(material_color[1:3], 16) / 255,
                            shade_factor * int(material_color[3:5], 16) / 255,
                            shade_factor * int(material_color[5:7], 16) / 255,
                            1.0
                        ]
                    except ValueError:
                        pass

                    if node.callDecoration("isNonPrintingMesh"):
                        if per_mesh_stack and (per_mesh_stack.getProperty(
                                "infill_mesh", "value")
                                               or per_mesh_stack.getProperty(
                                                   "cutting_mesh", "value")):
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                uniforms=uniforms,
                                transparent=True)
                        else:
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                transparent=True)
                    elif getattr(node, "_outside_buildarea", False):
                        renderer.queueNode(node, shader=self._disabled_shader)
                    elif per_mesh_stack and per_mesh_stack.getProperty(
                            "support_mesh", "value"):
                        # Render support meshes with a vertical stripe that is darker
                        shade_factor = 0.6
                        uniforms["diffuse_color_2"] = [
                            uniforms["diffuse_color"][0] * shade_factor,
                            uniforms["diffuse_color"][1] * shade_factor,
                            uniforms["diffuse_color"][2] * shade_factor, 1.0
                        ]
                        renderer.queueNode(node,
                                           shader=self._support_mesh_shader,
                                           uniforms=uniforms)
                    else:
                        renderer.queueNode(node,
                                           shader=self._enabled_shader,
                                           uniforms=uniforms)
                if node.callDecoration("isGroup") and Selection.isSelected(
                        node):
                    renderer.queueNode(scene.getRoot(),
                                       mesh=node.getBoundingBoxMesh(),
                                       mode=RenderBatch.RenderMode.LineLoop)
Ejemplo n.º 41
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "overhang.shader"))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue("u_diffuseColor1",
                                                  [0.48, 0.48, 0.48, 1.0])
            self._disabled_shader.setUniformValue("u_diffuseColor2",
                                                  [0.68, 0.68, 0.68, 1.0])
            self._disabled_shader.setUniformValue("u_width", 50.0)

        multi_extrusion = False

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack:
            if Preferences.getInstance().getValue("view/show_overhang"):
                angle = global_container_stack.getProperty(
                    "support_angle", "value")
                if angle is not None and global_container_stack.getProperty(
                        "support_angle",
                        "validationState") == ValidatorState.Valid:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(90 - angle)))
                else:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(0))
                    )  #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle",
                                                     math.cos(math.radians(0)))

            multi_extrusion = global_container_stack.getProperty(
                "machine_extruder_count", "value") > 1

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():

                    uniforms = {}
                    if not multi_extrusion:
                        if global_container_stack:
                            material = global_container_stack.findContainer(
                                {"type": "material"})
                            material_color = material.getMetaDataEntry(
                                "color_code",
                                default=self._extruders_model.defaultColors[0]
                            ) if material else self._extruders_model.defaultColors[
                                0]
                        else:
                            material_color = self._extruders_model.defaultColors[
                                0]
                    else:
                        # Get color to render this mesh in from ExtrudersModel
                        extruder_index = 0
                        extruder_id = node.callDecoration("getActiveExtruder")
                        if extruder_id:
                            extruder_index = max(
                                0,
                                self._extruders_model.find("id", extruder_id))

                        material_color = self._extruders_model.getItem(
                            extruder_index)["color"]
                    try:
                        # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                        # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                        uniforms["diffuse_color"] = [
                            int(material_color[1:3], 16) / 255,
                            int(material_color[3:5], 16) / 255,
                            int(material_color[5:7], 16) / 255, 1.0
                        ]
                    except ValueError:
                        pass

                    if hasattr(node, "_outside_buildarea"):
                        if node._outside_buildarea:
                            renderer.queueNode(node,
                                               shader=self._disabled_shader)
                        else:
                            renderer.queueNode(node,
                                               shader=self._enabled_shader,
                                               uniforms=uniforms)
                    else:
                        renderer.queueNode(node,
                                           material=self._enabled_shader,
                                           uniforms=uniforms)
                if node.callDecoration("isGroup") and Selection.isSelected(
                        node):
                    renderer.queueNode(scene.getRoot(),
                                       mesh=node.getBoundingBoxMesh(),
                                       mode=Renderer.RenderLines)
Ejemplo n.º 42
0
    def event(self, event):
        super().event(event)

        if event.type == Event.ToolActivateEvent:
            self._old_scale = Selection.getSelectedObject(0).getScale()
            for node in Selection.getAllSelectedObjects():
                node.boundingBoxChanged.connect(self.propertyChanged)

        if event.type == Event.ToolDeactivateEvent:
            for node in Selection.getAllSelectedObjects():
                node.boundingBoxChanged.disconnect(self.propertyChanged)

        if event.type == Event.KeyPressEvent:
            if event.key == KeyEvent.ShiftKey:
                self._snap_scale = False
                self.propertyChanged.emit()
            elif event.key == KeyEvent.ControlKey:
                self._non_uniform_scale = True
                self.propertyChanged.emit()

        if event.type == Event.KeyReleaseEvent:
            if event.key == KeyEvent.ShiftKey:
                self._snap_scale = True
                self.propertyChanged.emit()
            elif event.key == KeyEvent.ControlKey:
                self._non_uniform_scale = False
                self.propertyChanged.emit()

        if event.type == Event.MousePressEvent and self._controller.getToolsEnabled():
            if MouseEvent.LeftButton not in event.buttons:
                return False

            id = self._selection_pass.getIdAtPosition(event.x, event.y)
            if not id:
                return False

            if ToolHandle.isAxis(id):
                self.setLockedAxis(id)

            self._saved_handle_position = self._handle.getWorldPosition()

            if id == ToolHandle.XAxis:
                self.setDragPlane(Plane(Vector(0, 0, 1), self._saved_handle_position.z))
            elif id == ToolHandle.YAxis:
                self.setDragPlane(Plane(Vector(0, 0, 1), self._saved_handle_position.z))
            elif id == ToolHandle.ZAxis:
                self.setDragPlane(Plane(Vector(0, 1, 0), self._saved_handle_position.y))
            else:
                self.setDragPlane(Plane(Vector(0, 1, 0), self._saved_handle_position.y))

            self.setDragStart(event.x, event.y)
            self.operationStarted.emit(self)

        if event.type == Event.MouseMoveEvent:
            if not self.getDragPlane():
                return False

            #handle_position = self._handle.getWorldPosition()
            drag_position = self.getDragPosition(event.x, event.y)
            if drag_position:
                drag_length = (drag_position - self._saved_handle_position).length()
                if self._drag_length > 0:
                    drag_change = (drag_length - self._drag_length) / 100 * self._scale_speed

                    scale_factor = drag_change

                    scale_change = Vector(0.0, 0.0, 0.0)
                    if self._non_uniform_scale:
                        if self.getLockedAxis() == ToolHandle.XAxis:
                            scale_change.setX(scale_factor)
                        elif self.getLockedAxis() == ToolHandle.YAxis:
                            scale_change.setY(scale_factor)
                        elif self.getLockedAxis() == ToolHandle.ZAxis:
                            scale_change.setZ(scale_factor)
                    else:
                        scale_change.setX(scale_factor)
                        scale_change.setY(scale_factor)
                        scale_change.setZ(scale_factor)

                    Selection.applyOperation(ScaleOperation, scale_change, relative_scale = True, snap = self._snap_scale)

                self._drag_length = (self._saved_handle_position - drag_position).length()
                return True

        if event.type == Event.MouseReleaseEvent:
            if self.getDragPlane():
                self.setDragPlane(None)
                self.setLockedAxis(None)
                self._drag_length = 0
                self.operationStopped.emit(self)
                return True
Ejemplo n.º 43
0
    def getScaleZ(self):
        if Selection.hasSelection():
            ## Ensure that the returned value is positive (mirror causes scale to be negative)
            return abs(round(float(Selection.getSelectedObject(0).getScale().z), 4))

        return 1.0
Ejemplo n.º 44
0
    def getObjectDepth(self):
        if Selection.hasSelection():
            return float(Selection.getSelectedObject(0).getBoundingBox().depth)

        return 0.0
 def undo(self) -> None:
     self._node.setParent(None)
     self._selected = Selection.isSelected(self._node)
     if self._selected:
         Selection.remove(self._node)  # Also remove the node from the selection.
Ejemplo n.º 46
0
 def getY(self):
     if Selection.hasSelection():
         # Note; The switching of z & y is intentional. We display z as up for the user,
         # But store the data in openGL space.
         return float(Selection.getBoundingBox().center.z)
     return 0.0
Ejemplo n.º 47
0
    def _update(self, *args) -> None:
        nodes = []
        filter_current_build_plate = Application.getInstance().getPreferences().getValue("view/filter_current_build_plate")
        active_build_plate_number = self._build_plate_number

        naming_regex = re.compile("^(.+)\(([0-9]+)\)$")

        NodeInfo = namedtuple("NodeInfo", ["index_to_node", "nodes_to_rename", "is_group"])
        name_to_node_info_dict = {}  # type: Dict[str, NodeInfo]

        group_name_template = catalog.i18nc("@label", "Group #{group_nr}")
        group_name_prefix = group_name_template.split("#")[0]

        for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):  # type: ignore
            if not isinstance(node, SceneNode):
                continue
            if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
                continue

            parent = node.getParent()
            if parent and parent.callDecoration("isGroup"):
                continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
            if not node.callDecoration("isSliceable") and not node.callDecoration("isGroup"):
                continue
            node_build_plate_number = node.callDecoration("getBuildPlateNumber")
            if filter_current_build_plate and node_build_plate_number != active_build_plate_number:
                continue

            is_group = bool(node.callDecoration("isGroup"))
            force_rename = False
            if not is_group:
                # Handle names for individual nodes
                name = node.getName()

                name_match = naming_regex.fullmatch(name)
                if name_match is None:
                    original_name = name
                    name_index = 0
                else:
                    original_name = name_match.groups()[0]
                    name_index = int(name_match.groups()[1])

            else:
                # Handle names for grouped nodes
                original_name = group_name_prefix

                current_name = node.getName()
                if current_name.startswith(group_name_prefix):
                    name_index = int(current_name.split("#")[-1])
                else:
                    # Force rename this group because this node has not been named as a group yet, probably because
                    # it's a newly created group.
                    name_index = 0
                    force_rename = True

            if original_name not in name_to_node_info_dict:
                # Keep track of 2 things:
                #  - known indices for nodes which doesn't need to be renamed
                #  - a list of nodes that need to be renamed. When renaming then, we should avoid using the known indices.
                name_to_node_info_dict[original_name] = NodeInfo(index_to_node = {},
                                                                 nodes_to_rename = [],
                                                                 is_group = is_group)
            node_info_dict = name_to_node_info_dict[original_name]
            if not force_rename and name_index not in node_info_dict.index_to_node:
                node_info_dict.index_to_node[name_index] = node
            else:
                node_info_dict.nodes_to_rename.append(node)

        # Go through all names and rename the nodes that need to be renamed.
        node_rename_list = []  # type: List[Dict[str, Any]]
        for name, node_info_dict in name_to_node_info_dict.items():
            # First add the ones that do not need to be renamed.
            for node in node_info_dict.index_to_node.values():
                node_rename_list.append({"node": node})

            # Generate new names for the nodes that need to be renamed
            current_index = 0
            for node in node_info_dict.nodes_to_rename:
                current_index += 1
                while current_index in node_info_dict.index_to_node:
                    current_index += 1

                if not node_info_dict.is_group:
                    new_group_name = "{0}({1})".format(name, current_index)
                else:
                    new_group_name = "{0}#{1}".format(name, current_index)
                node_rename_list.append({"node": node,
                                         "new_name": new_group_name})

        for node_info in node_rename_list:
            node = node_info["node"]
            new_name = node_info.get("new_name")

            if hasattr(node, "isOutsideBuildArea"):
                is_outside_build_area = node.isOutsideBuildArea()  # type: ignore
            else:
                is_outside_build_area = False

            node_build_plate_number = node.callDecoration("getBuildPlateNumber")

            from UM.Logger import Logger

            if new_name is not None:
                old_name = node.getName()
                node.setName(new_name)
                Logger.log("d", "Node [%s] renamed to [%s]", old_name, new_name)

            nodes.append({
                "name": node.getName(),
                "selected": Selection.isSelected(node),
                "outside_build_area": is_outside_build_area,
                "buildplate_number": node_build_plate_number,
                "node": node
            })

        nodes = sorted(nodes, key=lambda n: n["name"])
        self.setItems(nodes)

        self.itemsChanged.emit()
Ejemplo n.º 48
0
    def resetScale(self):
        """Reset scale of the selected objects"""

        Selection.applyOperation(SetTransformOperation, None, None,
                                 Vector(1.0, 1.0, 1.0), Vector(0, 0, 0))
Ejemplo n.º 49
0
    def changeSelection(self, index):
        modifiers = QApplication.keyboardModifiers()
        ctrl_is_active = modifiers & Qt.ControlModifier
        shift_is_active = modifiers & Qt.ShiftModifier

        if ctrl_is_active:
            item = self._objects_model.getItem(index)
            node = item["node"]
            if Selection.isSelected(node):
                Selection.remove(node)
            else:
                Selection.add(node)
        elif shift_is_active:
            polarity = 1 if index + 1 > self._last_selected_index else -1
            for i in range(self._last_selected_index, index + polarity, polarity):
                item = self._objects_model.getItem(i)
                node = item["node"]
                Selection.add(node)
        else:
            # Single select
            item = self._objects_model.getItem(index)
            node = item["node"]
            build_plate_number = node.callDecoration("getBuildPlateNumber")
            if build_plate_number is not None and build_plate_number != -1:
                self.setActiveBuildPlate(build_plate_number)
            Selection.clear()
            Selection.add(node)

        self._last_selected_index = index
Ejemplo n.º 50
0
 def resetScale(self):
     Selection.applyOperation(SetTransformOperation, None, None, Vector(1.0, 1.0, 1.0))
Ejemplo n.º 51
0
    def event(self, event):
        super().event(event)

        if event.type == Event.ToolActivateEvent:
            self._old_scale = Selection.getSelectedObject(0).getScale()
            for node in Selection.getAllSelectedObjects():
                node.boundingBoxChanged.connect(self.propertyChanged)

        if event.type == Event.ToolDeactivateEvent:
            for node in Selection.getAllSelectedObjects():
                node.boundingBoxChanged.disconnect(self.propertyChanged)

        if event.type == Event.KeyPressEvent:
            if event.key == KeyEvent.ShiftKey:
                self._snap_scale = False
                self.propertyChanged.emit()
            elif event.key == KeyEvent.ControlKey:
                self._non_uniform_scale = True
                self.propertyChanged.emit()

        if event.type == Event.KeyReleaseEvent:
            if event.key == KeyEvent.ShiftKey:
                self._snap_scale = True
                self.propertyChanged.emit()
            elif event.key == KeyEvent.ControlKey:
                self._non_uniform_scale = False
                self.propertyChanged.emit()

        if event.type == Event.MousePressEvent:
            if MouseEvent.LeftButton not in event.buttons:
                return False

            id = self._renderer.getIdAtCoordinate(event.x, event.y)
            if not id:
                return False

            if ToolHandle.isAxis(id):
                self.setLockedAxis(id)

            handle_position = self._handle.getWorldPosition()

            if id == ToolHandle.XAxis:
                self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z))
            elif id == ToolHandle.YAxis:
                self.setDragPlane(Plane(Vector(0, 0, 1), handle_position.z))
            elif id == ToolHandle.ZAxis:
                self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y))
            else:
                self.setDragPlane(Plane(Vector(0, 1, 0), handle_position.y))

            self.setDragStart(event.x, event.y)
            self.operationStarted.emit(self)

        if event.type == Event.MouseMoveEvent:
            if not self.getDragPlane():
                return False

            handle_position = self._handle.getWorldPosition()
            drag_position = self.getDragPosition(event.x, event.y)
            if drag_position:
                drag_length = (drag_position - handle_position).length()
                if self._drag_length > 0:
                    drag_change = (drag_length -
                                   self._drag_length) / 100 * self._scale_speed

                    if self._snap_scale:
                        scaleFactor = round(drag_change, 1)
                    else:
                        scaleFactor = drag_change

                    scale = Vector(0.0, 0.0, 0.0)
                    if self._non_uniform_scale:
                        if self.getLockedAxis() == ToolHandle.XAxis:
                            scale.setX(scaleFactor)
                        elif self.getLockedAxis() == ToolHandle.YAxis:
                            scale.setY(scaleFactor)
                        elif self.getLockedAxis() == ToolHandle.ZAxis:
                            scale.setZ(scaleFactor)

                    else:
                        scale.setX(scaleFactor)
                        scale.setY(scaleFactor)
                        scale.setZ(scaleFactor)

                    Selection.applyOperation(ScaleOperation,
                                             scale,
                                             add_scale=True)

                    #this part prevents the mesh being scaled to a size < 0.
                    #This cannot be done before the operation (even though that would be more efficient)
                    #because then the operation can distract more of the mesh then is remaining of its size
                    realWorldMeshScale = Selection.getSelectedObject(
                        0).getScale()
                    if realWorldMeshScale.x <= 0 or realWorldMeshScale.y <= 0 or realWorldMeshScale.z <= 0:
                        minimumScale = 0.01  #1% so the mesh never completely disapears for the user
                        if self._snap_scale == True:
                            minimumScale = 0.1  #10% same reason as above
                        if realWorldMeshScale.x <= 0:
                            realWorldMeshScale.setX(minimumScale)
                        if realWorldMeshScale.y <= 0:
                            realWorldMeshScale.setY(minimumScale)
                        if realWorldMeshScale.z <= 0:
                            realWorldMeshScale.setZ(minimumScale)
                        Selection.applyOperation(SetTransformOperation, None,
                                                 None, realWorldMeshScale)

                self._drag_length = (handle_position - drag_position).length()
                return True

        if event.type == Event.MouseReleaseEvent:
            if self.getDragPlane():
                self.setDragPlane(None)
                self.setLockedAxis(None)
                self._drag_length = 0
                self.operationStopped.emit(self)
                return True
Ejemplo n.º 52
0
 def test_selectionNames(self):
     node_1 = SceneNode(name="TestNode1")
     node_2 = SceneNode(name="TestNode2")
     Selection.add(node_2)
     Selection.add(node_1)
     assert self.proxy.selectionNames == ["TestNode2", "TestNode1"]
Ejemplo n.º 53
0
 def setSelectedActiveExtruder(self, extruder_stack_id):
     selected_object = Selection.getSelectedObject(0)
     stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
     if not stack:
         selected_object.addDecorator(SettingOverrideDecorator())
     selected_object.callDecoration("setActiveExtruder", extruder_stack_id)
Ejemplo n.º 54
0
 def tearDown(self):
     Selection.clear()
Ejemplo n.º 55
0
 def getContainerID(self):
     selected_object = Selection.getSelectedObject(0)
     try:
         return selected_object.callDecoration("getStack").getId()
     except AttributeError:
         return ""
Ejemplo n.º 56
0
 def setUp(self):
     Selection.clear()
     self.proxy = SelectionProxy()
Ejemplo n.º 57
0
 def getSelectedObjectId(self):
     selected_object = Selection.getSelectedObject(0)
     selected_object_id = id(selected_object)
     return selected_object_id
Ejemplo n.º 58
0
 def _updateSelectedObjectBuildPlateNumbers(self, *args):
     result = set()
     for node in Selection.getAllSelectedObjects():
         result.add(node.callDecoration("getBuildPlateNumber"))
     self._selection_build_plates = list(result)
     self.selectionChanged.emit()
Ejemplo n.º 59
0
 def scaleToMax(self):
     if hasattr(self.getController().getScene(), "_maximum_bounds"):
         Selection.applyOperation(ScaleToBoundsOperation, self.getController().getScene()._maximum_bounds)
Ejemplo n.º 60
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()
        renderer.setRenderSelection(False)

        if not self._material:
            self._material = renderer.createMaterial(
                Resources.getPath(Resources.Shaders, "basic.vert"),
                Resources.getPath(Resources.Shaders, "vertexcolor.frag"))
            self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])

            self._selection_material = renderer.createMaterial(
                Resources.getPath(Resources.Shaders, "basic.vert"),
                Resources.getPath(Resources.Shaders, "color.frag"))
            self._selection_material.setUniformValue("u_color",
                                                     Color(35, 35, 35, 128))

        for node in DepthFirstIterator(scene.getRoot()):
            # We do not want to render ConvexHullNode as it conflicts with the bottom layers.
            # However, it is somewhat relevant when the node is selected, so do render it then.
            if type(node) is ConvexHullNode and not Selection.isSelected(
                    node.getWatchedNode()):
                continue

            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    if Selection.isSelected(node):
                        renderer.queueNode(node,
                                           material=self._selection_material,
                                           transparent=True)
                    layer_data = node.callDecoration("getLayerData")
                    if not layer_data:
                        continue

                    # Render all layers below a certain number as line mesh instead of vertices.
                    if self._current_layer_num - self._solid_layers > -1:
                        start = 0
                        end = 0
                        element_counts = layer_data.getElementCounts()
                        for layer, counts in element_counts.items():
                            if layer + self._solid_layers > self._current_layer_num:
                                break
                            end += counts

                        # This uses glDrawRangeElements internally to only draw a certain range of lines.
                        renderer.queueNode(node,
                                           mesh=layer_data,
                                           material=self._material,
                                           mode=Renderer.RenderLines,
                                           start=start,
                                           end=end)

                    # We currently recreate the current "solid" layers every time a
                    if not self._current_layer_mesh:
                        self._current_layer_mesh = MeshData()
                        for i in range(self._solid_layers):
                            layer = self._current_layer_num - i
                            if layer < 0:
                                continue
                            try:
                                layer_mesh = layer_data.getLayer(
                                    layer).createMesh()
                                if not layer_mesh or layer_mesh.getVertices(
                                ) is None:
                                    continue
                            except:
                                continue
                            if self._current_layer_mesh:  #Threading thing; Switching between views can cause the current layer mesh to be deleted.
                                self._current_layer_mesh.addVertices(
                                    layer_mesh.getVertices())

                            # Scale layer color by a brightness factor based on the current layer number
                            # This will result in a range of 0.5 - 1.0 to multiply colors by.
                            brightness = (2.0 - (i / self._solid_layers)) / 2.0
                            if self._current_layer_mesh:
                                self._current_layer_mesh.addColors(
                                    layer_mesh.getColors() * brightness)
                    if self._current_layer_mesh:
                        renderer.queueNode(node,
                                           mesh=self._current_layer_mesh,
                                           material=self._material)

                    if not self._current_layer_jumps:
                        self._current_layer_jumps = MeshData()
                        for i in range(1):
                            layer = self._current_layer_num - i
                            if layer < 0:
                                continue
                            try:
                                layer_mesh = layer_data.getLayer(
                                    layer).createJumps()
                                if not layer_mesh or layer_mesh.getVertices(
                                ) is None:
                                    continue
                            except:
                                continue

                            self._current_layer_jumps.addVertices(
                                layer_mesh.getVertices())

                            # Scale layer color by a brightness factor based on the current layer number
                            # This will result in a range of 0.5 - 1.0 to multiply colors by.
                            brightness = (2.0 - (i / self._solid_layers)) / 2.0
                            self._current_layer_jumps.addColors(
                                layer_mesh.getColors() * brightness)

                    renderer.queueNode(node,
                                       mesh=self._current_layer_jumps,
                                       material=self._material)