Esempio n. 1
0
    def selectedObjectExtruders(self) -> List[Union[str, "ExtruderStack"]]:
        if not self._selected_object_extruders:
            object_extruders = set()

            # First, build a list of the actual selected objects (including children of groups, excluding group nodes)
            selected_nodes = []  # type: List["SceneNode"]
            for node in Selection.getAllSelectedObjects():
                if node.callDecoration("isGroup"):
                    for grouped_node in BreadthFirstIterator(node):
                        if grouped_node.callDecoration("isGroup"):
                            continue

                        selected_nodes.append(grouped_node)
                else:
                    selected_nodes.append(node)

            # Then, figure out which nodes are used by those selected nodes.
            current_extruder_trains = self.getActiveExtruderStacks()
            for node in selected_nodes:
                extruder = node.callDecoration("getActiveExtruder")
                if extruder:
                    object_extruders.add(extruder)
                elif current_extruder_trains:
                    object_extruders.add(current_extruder_trains[0].getId())

            self._selected_object_extruders = list(object_extruders)

        return self._selected_object_extruders
Esempio n. 2
0
    def _boundingBoxSelection(self, event):
        """Handle mouse and keyboard events for bounding box selection

        :param event: type(Event) passed from self.event()
        """

        root = self._scene.getRoot()

        ray = self._scene.getActiveCamera().getRay(event.x, event.y)

        intersections = []
        for node in BreadthFirstIterator(root):
            if node.isEnabled() and not node.isLocked():
                intersection = node.getBoundingBox().intersectsRay(ray)
                if intersection:
                    intersections.append((node, intersection[0], intersection[1]))

        if intersections:
            intersections.sort(key=lambda k: k[1])

            node = intersections[0][0]
            if not Selection.isSelected(node):
                if not self._shift_is_active:
                    Selection.clear()
                Selection.add(node)
        else:
            Selection.clear()
Esempio n. 3
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._xray_shader:
            self._xray_shader = OpenGL.getInstance().createShaderProgram(
                os.path.join(
                    PluginRegistry.getInstance().getPluginPath("XRayView"),
                    "xray.shader"))
            self._xray_shader.setUniformValue(
                "u_color",
                Color(*Application.getInstance().getTheme().getColor(
                    "xray").getRgb()))

        for node in BreadthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    renderer.queueNode(
                        node,
                        shader=self._xray_shader,
                        type=RenderBatch.RenderType.Solid,
                        blend_mode=RenderBatch.BlendMode.Additive,
                        sort=-10,
                        state_setup_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_ALWAYS),
                        state_teardown_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_LESS))
Esempio n. 4
0
    def selectedObjectExtruders(self) -> List[str]:
        if not self._selected_object_extruders:
            object_extruders = set()

            # First, build a list of the actual selected objects (including children of groups, excluding group nodes)
            selected_nodes = []
            for node in Selection.getAllSelectedObjects():
                if node.callDecoration("isGroup"):
                    for grouped_node in BreadthFirstIterator(node):
                        if grouped_node.callDecoration("isGroup"):
                            continue

                        selected_nodes.append(grouped_node)
                else:
                    selected_nodes.append(node)

            # Then, figure out which nodes are used by those selected nodes.
            global_stack = Application.getInstance().getGlobalContainerStack()
            current_extruder_trains = self._extruder_trains.get(global_stack.getId())
            for node in selected_nodes:
                extruder = node.callDecoration("getActiveExtruder")
                if extruder:
                    object_extruders.add(extruder)
                elif current_extruder_trains:
                    object_extruders.add(current_extruder_trains["0"].getId())

            self._selected_object_extruders = list(object_extruders)

        return self._selected_object_extruders
    def _updateNodes(self, source):
        self.clear()
        camera = Application.getInstance().getController().getScene(
        ).getActiveCamera()
        for node in BreadthFirstIterator(self._root):
            if type(node) is not SceneNode or not node.getMeshData(
            ) or not node.isSelectable():
                continue

            projected_position = camera.project(node.getWorldPosition())

            node_profile = node.callDecoration("getProfile")
            if not node_profile:
                node_profile = "global"
            else:
                node_profile = node_profile.getName()

            self.appendItem({
                "id":
                id(node),
                "x":
                float(projected_position[0]),
                "y":
                float(projected_position[1]),
                "material":
                "",
                "profile":
                node_profile,
                "settings":
                SettingOverrideModel.SettingOverrideModel(node)
            })
    def setExtruderForSelection(self, extruder_id: str) -> None:
        operation = GroupedOperation()

        nodes_to_change = []
        for node in Selection.getAllSelectedObjects():
            # If the node is a group, apply the active extruder to all children of the group.
            if node.callDecoration("isGroup"):
                for grouped_node in BreadthFirstIterator(node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                    if grouped_node.callDecoration("getActiveExtruder") == extruder_id:
                        continue

                    if grouped_node.callDecoration("isGroup"):
                        continue

                    nodes_to_change.append(grouped_node)
                continue

            # Do not change any nodes that already have the right extruder set.
            if node.callDecoration("getActiveExtruder") == extruder_id:
                continue

            nodes_to_change.append(node)

        if not nodes_to_change:
            # If there are no changes to make, we still need to reset the selected extruders.
            # This is a workaround for checked menu items being deselected while still being
            # selected.
            ExtruderManager.getInstance().resetSelectedObjectExtruders()
            return

        for node in nodes_to_change:
            operation.addOperation(SetObjectExtruderOperation(node, extruder_id))
        operation.push()
Esempio n. 7
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._xray_shader:
            self._xray_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "xray.shader"))
            self._xray_shader.setUniformValue(
                "u_color",
                Color(*Application.getInstance().getTheme().getColor(
                    "xray").getRgb()))

        for node in BreadthFirstIterator(scene.getRoot()):
            # We do not want to render ConvexHullNode as it conflicts with the bottom of the X-Ray (z-fighting).
            if type(node) is ConvexHullNode:
                continue

            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    renderer.queueNode(
                        node,
                        shader=self._xray_shader,
                        type=RenderBatch.RenderType.Solid,
                        blend_mode=RenderBatch.BlendMode.Additive,
                        sort=-10,
                        state_setup_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_ALWAYS),
                        state_teardown_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_LESS))
Esempio n. 8
0
    def getAllCameras(self):
        cameras = []
        for node in BreadthFirstIterator(self._root):
            if isinstance(node, Camera):
                cameras.append(node)

        return cameras
Esempio n. 9
0
    def getAllCameras(self):
        cameras = []
        for node in BreadthFirstIterator(self._root):
            if type(node) is Camera:
                cameras.append(node)

        return cameras
Esempio n. 10
0
    def _onChangeTimerFinished(self):
        root = Application.getInstance().getController().getScene().getRoot()
        new_scene_objects = set(
            node for node in BreadthFirstIterator(root)
            if node.getMeshData() and type(node) is SceneNode)
        if new_scene_objects != self._scene_objects:
            for node in new_scene_objects - self._scene_objects:  #Nodes that were added to the scene.
                node.decoratorsChanged.connect(self._onNodeDecoratorChanged)
            for node in self._scene_objects - new_scene_objects:  #Nodes that were removed from the scene.
                per_mesh_stack = node.callDecoration("getStack")
                if per_mesh_stack:
                    per_mesh_stack.propertyChanged.disconnect(
                        self._onSettingPropertyChanged)
                active_extruder_changed = node.callDecoration(
                    "getActiveExtruderChangedSignal")
                if active_extruder_changed is not None:
                    node.callDecoration(
                        "getActiveExtruderChangedSignal").disconnect(
                            self._updateDisallowedAreasAndRebuild)
                node.decoratorsChanged.disconnect(self._onNodeDecoratorChanged)

            self._scene_objects = new_scene_objects
            self._onSettingPropertyChanged(
                "print_sequence",
                "value")  # Create fake event, so right settings are triggered.
Esempio n. 11
0
    def setBuildPlateForSelection(self, build_plate_nr: int) -> None:
        Logger.log("d", "Setting build plate number... %d" % build_plate_nr)
        operation = GroupedOperation()

        root = cura.CuraApplication.CuraApplication.getInstance(
        ).getController().getScene().getRoot()

        nodes_to_change = []
        for node in Selection.getAllSelectedObjects():
            parent_node = node  # Find the parent node to change instead
            while parent_node.getParent() != root:
                parent_node = parent_node.getParent()

            for single_node in BreadthFirstIterator(
                    parent_node
            ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                nodes_to_change.append(single_node)

        if not nodes_to_change:
            Logger.log("d", "Nothing to change.")
            return

        for node in nodes_to_change:
            operation.addOperation(
                SetBuildPlateNumberOperation(node, build_plate_nr))
        operation.push()

        Selection.clear()
Esempio n. 12
0
 def _automaticFileName(self, nodes):
     for root in nodes:
         for child in BreadthFirstIterator(root):
             if child.getMeshData():
                 name = child.getName()
                 if name:
                     return name
     raise OutputDeviceError.WriteRequestFailedError("Could not find a file name when trying to write to {device}.".format(device = self.getName()))
Esempio n. 13
0
 def _automaticFileName(self, nodes):
     for root in nodes:
         for child in BreadthFirstIterator(root):
             if child.getMeshData():
                 name = child.getName()
                 if name:
                     return name
     raise OutputDeviceError.WriteRequestFailedError(catalog.i18nc("@info:status Don't translate the tag {device}!", "Could not find a file name when trying to write to {device}.").format(device = self.getName()))
Esempio n. 14
0
    def _pixelSelection(self, event):
        # Find a node id by looking at a pixel value at the requested location
        if self._selection_pass:
            item_id = self._selection_pass.getIdAtPosition(event.x, event.y)
        else:
            Logger.log("w", "Selection pass is None. getRenderPass('selection') returned None")
            return False

        if not item_id and not self._shift_is_active:
            if Selection.hasSelection():
                Selection.clear()
                return True
            return False  # Nothing was selected before and the user didn't click on an object.

        # Find the scene-node which matches the node-id
        for node in BreadthFirstIterator(self._scene.getRoot()):
            if id(node) != item_id:
                continue

            if self._isNodeInGroup(node):
                is_selected = Selection.isSelected(self._findTopGroupNode(node))
            else:
                is_selected = Selection.isSelected(node)

            if self._shift_is_active:
                if is_selected:
                    # Deselect the SceneNode and its siblings in a group
                    if node.getParent():
                        if self._ctrl_is_active or not self._isNodeInGroup(node):
                            Selection.remove(node)
                        else:
                            Selection.remove(self._findTopGroupNode(node))
                        return True
                else:
                    # Select the SceneNode and its siblings in a group
                    if node.getParent():
                        if self._ctrl_is_active or not self._isNodeInGroup(node):
                            Selection.add(node)
                        else:
                            Selection.add(self._findTopGroupNode(node))
                        return True
            else:
                if not is_selected or Selection.getCount() > 1:
                    # Select only the SceneNode and its siblings in a group
                    Selection.clear()
                    if node.getParent():
                        if self._ctrl_is_active or not self._isNodeInGroup(node):
                            Selection.add(node)
                        else:
                            Selection.add(self._findTopGroupNode(node))
                        return True
                elif self._isNodeInGroup(node) and self._ctrl_is_active:
                    Selection.clear()
                    Selection.add(node)
                    return True

        return False
Esempio n. 15
0
    def requestWrite(self, node, file_name=None):
        if self._writing:
            raise OutputDeviceError.DeviceBusyError()

        gcode_writer = Application.getInstance().getMeshFileHandler(
        ).getWriterByMimeType("text/x-gcode")
        if not gcode_writer:
            Logger.log(
                "e",
                "Could not find GCode writer, not writing to removable drive %s",
                self.getName())
            raise OutputDeviceError.WriteRequestFailedError()

        if file_name == None:
            for n in BreadthFirstIterator(node):
                if n.getMeshData():
                    file_name = n.getName()
                    if file_name:
                        break

        if not file_name:
            Logger.log(
                "e",
                "Could not determine a proper file name when trying to write to %s, aborting",
                self.getName())
            raise OutputDeviceError.WriteRequestFailedError()

        file_name = os.path.join(self.getId(),
                                 os.path.splitext(file_name)[0] + ".gcode")

        try:
            Logger.log("d", "Writing to %s", file_name)
            stream = open(file_name, "wt")
            job = WriteMeshJob(gcode_writer, stream, node,
                               MeshWriter.OutputMode.TextMode)
            job.setFileName(file_name)
            job.progress.connect(self._onProgress)
            job.finished.connect(self._onFinished)

            message = Message(
                catalog.i18nc(
                    "@info:progress",
                    "Saving to Removable Drive <filename>{0}</filename>").
                format(self.getName()), 0, False, -1)
            message.show()

            self.writeStarted.emit(self)

            job._message = message
            self._writing = True
            job.start()
        except PermissionError as e:
            raise OutputDeviceError.PermissionDeniedError() from e
        except OSError as e:
            raise OutputDeviceError.WriteRequestFailedError() from e
Esempio n. 16
0
    def write(self, stream, node, mode = MeshWriter.OutputMode.BinaryMode):
        nodes = []
        for n in BreadthFirstIterator(node):
            if type(n) is not SceneNode or not n.getMeshData():
                continue

            nodes.append(n)
        if not len(nodes):
            return False

        archive = zipfile.ZipFile(stream, 'w',compression=zipfile.ZIP_DEFLATED)
        try:
            model_file = zipfile.ZipInfo("3D/3dmodel.model")
            content_types_file = zipfile.ZipInfo("[Content_Types].xml")
            model = ET.Element('model', unit = "millimeter", xmlns = self._namespaces["3mf"])
            resources = ET.SubElement(model, "resources")
            build = ET.SubElement(model, "build")
            for index, n in enumerate(nodes):
                object = ET.SubElement(resources, "object", id = str(index+1), type = "model")
                mesh = ET.SubElement(object, "mesh")

                mesh_data = n.getMeshData()
                vertices = ET.SubElement(mesh, "vertices")
                verts = mesh_data.getVertices()
                if mesh_data.hasIndices():
                    for face in mesh_data.getIndices():
                        v1 = verts[face[0]]
                        v2 = verts[face[1]]
                        v3 = verts[face[2]]
                        xml_vertex1 = ET.SubElement(vertices, "vertex", x = str(v1[0]), y = str(v1[2]), z = str(v1[1]))
                        xml_vertex2 = ET.SubElement(vertices, "vertex", x = str(v2[0]), y = str(v2[2]), z = str(v2[1]))
                        xml_vertex3 = ET.SubElement(vertices, "vertex", x = str(v3[0]), y = str(v3[2]), z = str(v3[1]))

                    triangles = ET.SubElement(mesh, "triangles")
                    for face in mesh_data.getIndices():
                        triangle = ET.SubElement(triangles, "triangle", v1 = str(face[0]) , v2 = str(face[1]), v3 = str(face[2]))
                else:
                    for vert in verts:
                        xml_vertex = ET.SubElement(vertices, "vertex", x = str(vert[0]), y = str(vert[0]), z = str(vert[0]))

                transformation_string = self._convertMatrixToString(node.getWorldTransformation())
                if transformation_string != self._convertMatrixToString(Matrix()):
                    item = ET.SubElement(build, "item", objectid = str(index+1), transform = transformation_string)
                else:
                    item = ET.SubElement(build, "item", objectid = str(index+1)) #, transform = transformation_string)

            archive.writestr(model_file, b'<?xml version="1.0" encoding="UTF-8"?> \n' + ET.tostring(model))
            archive.writestr(content_types_file, "")
        except Exception as e:
            print("Error writing zip file", e)
            return False
        finally:
            archive.close()

        return True
    def onSceneChanged(self, node):
        root = Application.getInstance().getController().getScene().getRoot()
        new_scene_objects = set(node for node in BreadthFirstIterator(root)
                                if node.callDecoration("isSliceable"))
        if new_scene_objects != self._scene_objects:
            to_scale = new_scene_objects - self._scene_objects
            self._scene_objects = new_scene_objects

            for node in to_scale:
                # Scale up by 2.5% on X and Y.  Modify as needed.
                node.scale(Vector(1.025, 1.0, 1.025))
    def _updatePositions(self, source):
        camera = Application.getInstance().getController().getScene(
        ).getActiveCamera()
        for node in BreadthFirstIterator(self._root):
            if type(node) is not SceneNode or not node.getMeshData():
                continue

            projected_position = camera.project(node.getWorldPosition())

            index = self.find("id", id(node))
            self.setProperty(index, "x", float(projected_position[0]))
            self.setProperty(index, "y", float(projected_position[1]))
Esempio n. 19
0
    def findObject(self, object_id: int) -> Optional[SceneNode]:
        """Find an object by id.

        :param object_id: The id of the object to search for, as returned by the python id() method.

        :return: The object if found, or None if not.
        """

        for node in BreadthFirstIterator(self._root):
            if id(node) == object_id:
                return node
        return None
Esempio n. 20
0
    def requestWrite(self, node, file_name = None, filter_by_machine = False):
        filter_by_machine = True # This plugin is indended to be used by machine (regardless of what it was told to do)
        if self._writing:
            raise OutputDeviceError.DeviceBusyError()

        file_formats = Application.getInstance().getMeshFileHandler().getSupportedFileTypesWrite() #Formats supported by this application.
        if filter_by_machine:
            machine_file_formats = Application.getInstance().getMachineManager().getActiveMachineInstance().getMachineDefinition().getFileFormats()
            file_formats = list(filter(lambda file_format: file_format["mime_type"] in machine_file_formats, file_formats)) #Take the intersection between file_formats and machine_file_formats.
        if len(file_formats) == 0:
            Logger.log("e", "There are no file formats available to write with!")
            raise OutputDeviceError.WriteRequestFailedError()
        writer = Application.getInstance().getMeshFileHandler().getWriterByMimeType(file_formats[0]["mime_type"]) #Just take the first file format available.
        extension = file_formats[0]["extension"]

        if file_name == None:
            for n in BreadthFirstIterator(node):
                if n.getMeshData():
                    file_name = n.getName()
                    if file_name:
                        break

        if not file_name:
            Logger.log("e", "Could not determine a proper file name when trying to write to %s, aborting", self.getName())
            raise OutputDeviceError.WriteRequestFailedError()

        if extension: #Not empty string.
            extension = "." + extension
        file_name = os.path.join(self.getId(), os.path.splitext(file_name)[0] + extension)

        try:
            Logger.log("d", "Writing to %s", file_name)
            stream = open(file_name, "wt")
            job = WriteMeshJob(writer, stream, node, MeshWriter.OutputMode.TextMode)
            job.setFileName(file_name)
            job.progress.connect(self._onProgress)
            job.finished.connect(self._onFinished)

            message = Message(catalog.i18nc("@info:progress", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1)
            message.show()

            self.writeStarted.emit(self)

            job._message = message
            self._writing = True
            job.start()
        except PermissionError as e:
            Logger.log("e", "Permission denied when trying to write to %s: %s", file_name, str(e))
            raise OutputDeviceError.PermissionDeniedError() from e
        except OSError as e:
            Logger.log("e", "Operating system would not let us write to %s: %s", file_name, str(e))
            raise OutputDeviceError.WriteRequestFailedError() from e
Esempio n. 21
0
    def _automaticFileName(self, nodes):
        """Generate a file name automatically for the specified nodes to be saved in.

        The name generated will be the name of one of the nodes. Which node that
        is can not be guaranteed.

        :param nodes: A collection of nodes for which to generate a file name.
        """
        for root in nodes:
            for child in BreadthFirstIterator(root):
                if child.getMeshData():
                    name = child.getName()
                    if name:
                        return name
        raise OutputDeviceError.WriteRequestFailedError(catalog.i18nc("@info:status Don't translate the tag {device}!", "Could not find a file name when trying to write to {device}.").format(device = self.getName()))
Esempio n. 22
0
    def _meshNodes(nodes):
        """Filters a collection of nodes to only include nodes that are actual
        meshes.
        
        This does not include auxiliary nodes such as tool handles.
        
        :param nodes: A sequence of nodes.
        :return: The nodes among those that are actual scene nodes.
        """

        for root in nodes:
            yield from filter(
                lambda child: isinstance(child, SceneNode) and child.
                isSelectable() and child.getMeshData(),
                BreadthFirstIterator(root))
Esempio n. 23
0
    def _pixelSelection(self, event):
        # Find a node id by looking at a pixel value at the requested location
        item_id = self._selection_pass.getIdAtPosition(event.x, event.y)

        if not item_id:
            Selection.clear()
            return

        # Find the scene-node which matches the node-id
        for node in BreadthFirstIterator(self._scene.getRoot()):
            if id(node) == item_id:
                if self._isNodeInGroup(node):
                    is_selected = Selection.isSelected(
                        self._findTopGroupNode(node))
                else:
                    is_selected = Selection.isSelected(node)

                if self._ctrl_is_active:
                    if is_selected:
                        # Deselect the scenenode and its sibblings in a group
                        if node.getParent():
                            if self._alt_is_active or not self._isNodeInGroup(
                                    node):
                                Selection.remove(node)
                            else:
                                Selection.remove(self._findTopGroupNode(node))
                    else:
                        # Select the scenenode and its sibblings in a group
                        if node.getParent():
                            if self._alt_is_active or not self._isNodeInGroup(
                                    node):
                                Selection.add(node)
                            else:
                                Selection.add(self._findTopGroupNode(node))
                else:
                    if not is_selected or Selection.getCount() > 1:
                        # Select only the scenenode and its sibblings in a group
                        Selection.clear()
                        if node.getParent():
                            if self._alt_is_active or not self._isNodeInGroup(
                                    node):
                                Selection.add(node)
                            else:
                                Selection.add(self._findTopGroupNode(node))
                    elif self._isNodeInGroup(node) and self._alt_is_active:
                        Selection.clear()
                        Selection.add(node)
    def _onSceneChanged(self, _) -> None:
        root = Application.getInstance().getController().getScene().getRoot()
        new_scene_objects = set(node for node in BreadthFirstIterator(root)
                                if node.callDecoration("isSliceable"))
        if new_scene_objects != self._scene_objects:
            to_scale = new_scene_objects - self._scene_objects
            self._scene_objects = new_scene_objects

            for node in to_scale:
                node.scale(
                    Vector((100.0 + float(self._x_scale)) / 100.0,
                           (100.0 + float(self._z_scale)) / 100.0,
                           (100.0 + float(self._y_scale)) / 100.0))
                self._message = Message(
                    i18n_catalog.i18nc("@info:status",
                                       "Scaled: %s." % (node.getName())),
                    title=i18n_catalog.i18nc("@title", "Auto Scale"))
                self._message.show()
Esempio n. 25
0
    def write(self, stream, node, mode=MeshWriter.OutputMode.TextMode):
        if mode != MeshWriter.OutputMode.TextMode:
            return False

        nodes = []
        for n in BreadthFirstIterator(node):
            if type(n) is not SceneNode or not n.getMeshData():
                continue

            nodes.append(n)

        if not nodes:
            return False

        stream.write("# URANIUM OBJ EXPORT {0}\n".format(
            time.strftime("%a %d %b %Y %H:%M:%S")))

        face_offset = 1
        for node in nodes:
            mesh_data = node.getMeshData().getTransformed(
                node.getWorldTransformation())
            if not mesh_data.hasIndices():
                continue

            stream.write("# {0}\n# Vertices\n".format(node.getName()))

            verts = mesh_data.getVertices()
            for face in mesh_data.getIndices():
                v1 = verts[face[0]]
                v2 = verts[face[1]]
                v3 = verts[face[2]]
                stream.write("v {0} {1} {2}\n".format(v1[0], -v1[2], v1[1]))
                stream.write("v {0} {1} {2}\n".format(v2[0], -v2[2], v2[1]))
                stream.write("v {0} {1} {2}\n".format(v3[0], -v3[2], v3[1]))

            stream.write("# Faces\n")
            for face in mesh_data.getIndices():
                stream.write("f {0} {1} {2}\n".format(face[0] + face_offset,
                                                      face[1] + face_offset,
                                                      face[2] + face_offset))

            face_offset += mesh_data.getVertexCount()

        return True
Esempio n. 26
0
    def updateNodeBoundaryCheck(self):
        root = Application.getInstance().getController().getScene().getRoot()
        nodes = list(BreadthFirstIterator(root))
        group_nodes = []

        build_volume_bounding_box = self.getBoundingBox()
        if build_volume_bounding_box:
            # It's over 9000!
            build_volume_bounding_box = build_volume_bounding_box.set(bottom=-9001)
        else:
            # No bounding box. This is triggered when running Cura from command line with a model for the first time
            # In that situation there is a model, but no machine (and therefore no build volume.
            return

        for node in nodes:
            # Need to check group nodes later
            if node.callDecoration("isGroup"):
                group_nodes.append(node)  # Keep list of affected group_nodes

            if node.callDecoration("isSliceable") or node.callDecoration("isGroup"):
                node._outside_buildarea = False
                bbox = node.getBoundingBox()

                # 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
                    continue

                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.getDisallowedAreas():
                        overlap = convex_hull.intersectsPolygon(area)
                        if overlap is None:
                            continue
                        node._outside_buildarea = True
                        continue

        # Group nodes should override the _outside_buildarea property of their children.
        for group_node in group_nodes:
            for child_node in group_node.getAllChildren():
                child_node._outside_buildarea = group_node._outside_buildarea
Esempio n. 27
0
 def _onChangeTimerFinished(self):
     root = Application.getInstance().getController().getScene().getRoot()
     new_number_of_objects = len([
         node for node in BreadthFirstIterator(root)
         if node.getMeshData() and type(node) is SceneNode
     ])
     if new_number_of_objects != self._number_of_objects:
         recalculate = False
         if self._global_container_stack.getProperty(
                 "print_sequence", "value") == "one_at_a_time":
             recalculate = (new_number_of_objects < 2
                            and self._number_of_objects > 1) or (
                                new_number_of_objects > 1
                                and self._number_of_objects < 2)
         self._number_of_objects = new_number_of_objects
         if recalculate:
             self._onSettingPropertyChanged(
                 "print_sequence", "value"
             )  # Create fake event, so right settings are triggered.
Esempio n. 28
0
    def _pixelSelection(self, event):
        pixel_id = self._renderer.getIdAtCoordinate(event.x, event.y)

        if not pixel_id:
            Selection.clear()
            return
        for node in BreadthFirstIterator(self._scene.getRoot()):
            if id(node) == pixel_id:
                if self._ctrl_is_active:
                    if Selection.isSelected(node):
                        if node.getParent():
                            group_node = node.getParent()
                            if not group_node.callDecoration("isGroup"):
                                Selection.remove(node)
                            else:
                                while group_node.getParent().callDecoration(
                                        "isGroup"):
                                    group_node = group_node.getParent()
                                Selection.remove(group_node)
                    else:
                        if node.getParent():
                            group_node = node.getParent()
                            if not group_node.callDecoration("isGroup"):
                                Selection.add(node)
                            else:
                                while group_node.getParent().callDecoration(
                                        "isGroup"):
                                    group_node = group_node.getParent()
                                Selection.add(group_node)
                else:
                    if not Selection.isSelected(
                            node) or Selection.getCount() > 1:
                        Selection.clear()
                        if node.getParent():
                            group_node = node.getParent()
                            if not group_node.callDecoration("isGroup"):
                                Selection.add(node)
                            else:
                                while group_node.getParent().callDecoration(
                                        "isGroup"):
                                    group_node = group_node.getParent()
                                Selection.add(group_node)
Esempio n. 29
0
    def write(self, stream, node, mode = MeshWriter.OutputMode.TextMode):
        nodes = []
        for n in BreadthFirstIterator(node):
            if type(n) is not SceneNode or not n.getMeshData():
                continue

            nodes.append(n)

        if not nodes:
            return False

        if mode == MeshWriter.OutputMode.TextMode:
            self._writeAscii(stream, nodes)
        elif mode == MeshWriter.OutputMode.BinaryMode:
            self._writeBinary(stream, nodes)
        else:
            Logger.log("e", "Unsupported output mode writing STL to stream")
            return False

        return True
Esempio n. 30
0
    def _updateModel(self):
        self.clear()
        for node in BreadthFirstIterator(self._root):
            if type(node) is not SceneNode or not node.isSelectable():
                continue
            node_profile = node.callDecoration("getProfile")
            if not node_profile:
                node_profile = "global"
            else:
                node_profile = node_profile.getName()

            self.appendItem({
                "id":
                id(node),
                "material":
                "",
                "profile":
                node_profile,
                "settings":
                SettingOverrideModel.SettingOverrideModel(node)
            })