Example #1
0
    def _onActiveExtruderChanged(self):
        if self._active_extruder_stack:
            self._active_extruder_stack.propertyChanged.disconnect(self._onSettingChanged)
            self._active_extruder_stack.containersChanged.disconnect(self._onChanged)

        self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack()
        if self._active_extruder_stack:
            self._active_extruder_stack.propertyChanged.connect(self._onSettingChanged)  # Note: Only starts slicing when the value changed.
            self._active_extruder_stack.containersChanged.connect(self._onChanged)
Example #2
0
    def _onActiveExtruderChanged(self):
        if self._active_extruder_stack:
            self._active_extruder_stack.propertyChanged.disconnect(
                self._onSettingChanged)
            self._active_extruder_stack.containersChanged.disconnect(
                self._onChanged)

        self._active_extruder_stack = ExtruderManager.getInstance(
        ).getActiveExtruderStack()
        if self._active_extruder_stack:
            self._active_extruder_stack.propertyChanged.connect(
                self._onSettingChanged
            )  # Note: Only starts slicing when the value changed.
            self._active_extruder_stack.containersChanged.connect(
                self._onChanged)
            self._onChanged()
Example #3
0
    def run(self):
        stack = Application.getInstance().getGlobalContainerStack()
        if not stack:
            self.setResult(StartJobResult.Error)
            return

        # Don't slice if there is a setting with an error value.
        if self._checkStackForErrors(stack):
            self.setResult(StartJobResult.SettingError)
            return

        # Don't slice if there is a per object setting with an error value.
        for node in DepthFirstIterator(self._scene.getRoot()):
            if type(node) is not SceneNode or not node.isSelectable():
                continue

            if self._checkStackForErrors(node.callDecoration("getStack")):
                self.setResult(StartJobResult.SettingError)
                return

        with self._scene.getSceneLock():
            # Remove old layer data.
            for node in DepthFirstIterator(self._scene.getRoot()):
                if node.callDecoration("getLayerData"):
                    node.getParent().removeChild(node)
                    break

            # Get the objects in their groups to print.
            object_groups = []
            if stack.getProperty("print_sequence", "value") == "one_at_a_time":
                for node in OneAtATimeIterator(self._scene.getRoot()):
                    temp_list = []

                    # Node can't be printed, so don't bother sending it.
                    if getattr(node, "_outside_buildarea", False):
                        continue

                    children = node.getAllChildren()
                    children.append(node)
                    for child_node in children:
                        if type(child_node) is SceneNode and child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
                            temp_list.append(child_node)

                    if temp_list:
                        object_groups.append(temp_list)
                    Job.yieldThread()
                if len(object_groups) == 0:
                    Logger.log("w", "No objects suitable for one at a time found, or no correct order found")
            else:
                temp_list = []
                for node in DepthFirstIterator(self._scene.getRoot()):
                    if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
                        if not getattr(node, "_outside_buildarea", False):
                            temp_list.append(node)
                    Job.yieldThread()

                if temp_list:
                    object_groups.append(temp_list)

            if not object_groups:
                self.setResult(StartJobResult.NothingToSlice)
                return

            self._buildGlobalSettingsMessage(stack)

            for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getBottom().getId()):
                self._buildExtruderMessage(extruder_stack)

            for group in object_groups:
                group_message = self._slice_message.addRepeatedMessage("object_lists")
                if group[0].getParent().callDecoration("isGroup"):
                    self._handlePerObjectSettings(group[0].getParent(), group_message)
                for object in group:
                    mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())

                    obj = group_message.addRepeatedMessage("objects")
                    obj.id = id(object)
                    verts = numpy.array(mesh_data.getVertices())

                    # Convert from Y up axes to Z up axes. Equals a 90 degree rotation.
                    verts[:, [1, 2]] = verts[:, [2, 1]]
                    verts[:, 1] *= -1

                    obj.vertices = verts

                    self._handlePerObjectSettings(object, obj)

                    Job.yieldThread()

        self.setResult(StartJobResult.Finished)
Example #4
0
    def __init__(self):
        super().__init__()

        # Find out where the engine is located, and how it is called. This depends on how Cura is packaged and which OS we are running on.
        default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", "CuraEngine")
        if hasattr(sys, "frozen"):
            default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "CuraEngine")
        if Platform.isWindows():
            default_engine_location += ".exe"
        default_engine_location = os.path.abspath(default_engine_location)
        Preferences.getInstance().addPreference("backend/location", default_engine_location)

        self._scene = Application.getInstance().getController().getScene()
        self._scene.sceneChanged.connect(self._onSceneChanged)

        # Workaround to disable layer view processing if layer view is not active.
        self._layer_view_active = False
        Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
        self._onActiveViewChanged()
        self._stored_layer_data = []

        #Triggers for when to (re)start slicing:
        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
        self._onGlobalStackChanged()

        self._active_extruder_stack = None
        ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
        self._onActiveExtruderChanged()

        #When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
        #This timer will group them up, and only slice for the last setting changed signal.
        #TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction.
        self._change_timer = QTimer()
        self._change_timer.setInterval(500)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self.slice)

        #Listeners for receiving messages from the back-end.
        self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
        self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
        self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
        self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
        self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates
        #self._message_handlers["cura.proto.ObjectPrintTime"] = self._onObjectPrintTimeMessage
        self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage

        self._start_slice_job = None
        self._slicing = False #Are we currently slicing?
        self._restart = False #Back-end is currently restarting?
        self._enabled = True #Should we be slicing? Slicing might be paused when, for instance, the user is dragging the mesh around.
        self._always_restart = True #Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness.
        self._process_layers_job = None #The currently active job to process layers, or None if it is not processing layers.

        self._error_message = None #Pop-up message that shows errors.

        self.backendQuit.connect(self._onBackendQuit)
        self.backendConnected.connect(self._onBackendConnected)

        #When a tool operation is in progress, don't slice. So we need to listen for tool operations.
        Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted)
        Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped)
Example #5
0
    def run(self):
        stack = Application.getInstance().getGlobalContainerStack()
        if not stack:
            self.setResult(StartJobResult.Error)
            return

        # Don't slice if there is a setting with an error value.
        if self._checkStackForErrors(stack):
            self.setResult(StartJobResult.SettingError)
            return

        # Don't slice if there is a per object setting with an error value.
        for node in DepthFirstIterator(self._scene.getRoot()):
            if type(node) is not SceneNode or not node.isSelectable():
                continue

            if self._checkStackForErrors(node.callDecoration("getStack")):
                self.setResult(StartJobResult.SettingError)
                return

        with self._scene.getSceneLock():
            # Remove old layer data.
            for node in DepthFirstIterator(self._scene.getRoot()):
                if node.callDecoration("getLayerData"):
                    node.getParent().removeChild(node)
                    break

            # Get the objects in their groups to print.
            object_groups = []
            if stack.getProperty("print_sequence", "value") == "one_at_a_time":
                for node in OneAtATimeIterator(self._scene.getRoot()):
                    temp_list = []

                    # Node can't be printed, so don't bother sending it.
                    if getattr(node, "_outside_buildarea", False):
                        continue

                    children = node.getAllChildren()
                    children.append(node)
                    for child_node in children:
                        if type(child_node
                                ) is SceneNode and child_node.getMeshData(
                                ) and child_node.getMeshData().getVertices(
                                ) is not None:
                            temp_list.append(child_node)

                    if temp_list:
                        object_groups.append(temp_list)
                    Job.yieldThread()
                if len(object_groups) == 0:
                    Logger.log(
                        "w",
                        "No objects suitable for one at a time found, or no correct order found"
                    )
            else:
                temp_list = []
                for node in DepthFirstIterator(self._scene.getRoot()):
                    if type(node) is SceneNode and node.getMeshData(
                    ) and node.getMeshData().getVertices() is not None:
                        if not getattr(node, "_outside_buildarea", False):
                            temp_list.append(node)
                    Job.yieldThread()

                if temp_list:
                    object_groups.append(temp_list)

            if not object_groups:
                self.setResult(StartJobResult.NothingToSlice)
                return

            self._buildGlobalSettingsMessage(stack)

            for extruder_stack in ExtruderManager.getInstance(
            ).getMachineExtruders(stack.getBottom().getId()):
                self._buildExtruderMessage(extruder_stack)

            for group in object_groups:
                group_message = self._slice_message.addRepeatedMessage(
                    "object_lists")
                if group[0].getParent().callDecoration("isGroup"):
                    self._handlePerObjectSettings(group[0].getParent(),
                                                  group_message)
                for object in group:
                    mesh_data = object.getMeshData().getTransformed(
                        object.getWorldTransformation())

                    obj = group_message.addRepeatedMessage("objects")
                    obj.id = id(object)
                    verts = numpy.array(mesh_data.getVertices())

                    # Convert from Y up axes to Z up axes. Equals a 90 degree rotation.
                    verts[:, [1, 2]] = verts[:, [2, 1]]
                    verts[:, 1] *= -1

                    obj.vertices = verts

                    self._handlePerObjectSettings(object, obj)

                    Job.yieldThread()

        self.setResult(StartJobResult.Finished)
Example #6
0
    def __init__(self):
        super().__init__()

        # Find out where the engine is located, and how it is called. This depends on how Cura is packaged and which OS we are running on.
        default_engine_location = os.path.join(Application.getInstallPrefix(),
                                               "bin", "CuraEngine")
        if hasattr(sys, "frozen"):
            default_engine_location = os.path.join(
                os.path.dirname(os.path.abspath(sys.executable)), "CuraEngine")
        if Platform.isWindows():
            default_engine_location += ".exe"
        default_engine_location = os.path.abspath(default_engine_location)
        Preferences.getInstance().addPreference("backend/location",
                                                default_engine_location)

        self._scene = Application.getInstance().getController().getScene()
        self._scene.sceneChanged.connect(self._onSceneChanged)

        # Workaround to disable layer view processing if layer view is not active.
        self._layer_view_active = False
        Application.getInstance().getController().activeViewChanged.connect(
            self._onActiveViewChanged)
        self._onActiveViewChanged()
        self._stored_layer_data = []

        #Triggers for when to (re)start slicing:
        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(
            self._onGlobalStackChanged)
        self._onGlobalStackChanged()

        self._active_extruder_stack = None
        ExtruderManager.getInstance().activeExtruderChanged.connect(
            self._onActiveExtruderChanged)
        self._onActiveExtruderChanged()

        #When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
        #This timer will group them up, and only slice for the last setting changed signal.
        #TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction.
        self._change_timer = QTimer()
        self._change_timer.setInterval(500)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self.slice)

        #Listeners for receiving messages from the back-end.
        self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
        self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
        self._message_handlers[
            "cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
        self._message_handlers[
            "cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
        self._message_handlers[
            "cura.proto.ObjectPrintTime"] = self._onObjectPrintTimeMessage
        self._message_handlers[
            "cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage

        self._start_slice_job = None
        self._slicing = False  #Are we currently slicing?
        self._restart = False  #Back-end is currently restarting?
        self._enabled = True  #Should we be slicing? Slicing might be paused when, for instance, the user is dragging the mesh around.
        self._always_restart = True  #Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness.
        self._process_layers_job = None  #The currently active job to process layers, or None if it is not processing layers.

        self._error_message = None  #Pop-up message that shows errors.

        self.backendQuit.connect(self._onBackendQuit)
        self.backendConnected.connect(self._onBackendConnected)

        #When a tool operation is in progress, don't slice. So we need to listen for tool operations.
        Application.getInstance().getController().toolOperationStarted.connect(
            self._onToolOperationStarted)
        Application.getInstance().getController().toolOperationStopped.connect(
            self._onToolOperationStopped)