def _loadAscii(self, mesh_builder, f):
        num_verts = 0
        for lines in f:
            for line in lines.split("\r"):
                if "vertex" in line:
                    num_verts += 1

        mesh_builder.reserveFaceCount(num_verts / 3)
        f.seek(0, os.SEEK_SET)
        vertex = 0
        face = [None, None, None]
        for lines in f:
            for line in lines.split("\r"):
                if "vertex" in line:
                    face[vertex] = line.split()[1:]
                    vertex += 1
                    if vertex == 3:
                        mesh_builder.addFaceByPoints(
                            float(face[0][0]), float(face[0][2]), -float(face[0][1]),
                            float(face[1][0]), float(face[1][2]), -float(face[1][1]),
                            float(face[2][0]), float(face[2][2]), -float(face[2][1])
                        )
                        vertex = 0

                Job.yieldThread()
Beispiel #2
0
    def _buildExtruderMessage(self, stack: ContainerStack) -> None:
        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))
        if not self._all_extruders_settings:
            self._cacheAllExtruderSettings()

        if self._all_extruders_settings is None:
            return

        extruder_nr = stack.getProperty("extruder_nr", "value")
        settings = self._all_extruders_settings[str(extruder_nr)].copy()

        # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
        settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "")

        # Replace the setting tokens in start and end g-code.
        extruder_nr = stack.getProperty("extruder_nr", "value")
        settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], extruder_nr)
        settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], extruder_nr)

        for key, value in settings.items():
            # Do not send settings that are not settable_per_extruder.
            if not stack.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage("settings")
            setting.name = key
            setting.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #3
0
    def _buildGlobalSettingsMessage(self, stack):
        keys = stack.getAllKeys()
        settings = {}
        for key in keys:
            settings[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        start_gcode = settings["machine_start_gcode"]
        #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        bed_temperature_settings = {"material_bed_temperature", "material_bed_temperature_layer_0"}
        settings["material_bed_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in bed_temperature_settings))
        print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"}
        settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))

        settings["print_bed_temperature"] = settings["material_bed_temperature"]
        settings["print_temperature"] = settings["material_print_temperature"]

        settings["time"] = time.strftime('%H:%M:%S')
        settings["date"] = time.strftime('%d-%m-%Y')
        settings["day"] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][int(time.strftime('%w'))]

        for key, value in settings.items(): #Add all submessages for each individual setting.
            setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            if key == "machine_start_gcode" or key == "machine_end_gcode" or key == "machine_extruder_start_code" or key == "machine_extruder_end_code": #If it's a g-code message, use special formatting.
                setting_message.value = self._expandGcodeTokens(key, value, settings)
            else:
                setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #4
0
    def _buildGlobalSettingsMessage(self, stack):
        keys = stack.getAllKeys()
        settings = {}
        for key in keys:
            # Use resolvement value if available, or take the value
            resolved_value = stack.getProperty(key, "resolve")
            if resolved_value is not None:
                # There is a resolvement value. Check if we need to use it.
                user_container = stack.findContainer({"type": "user"})
                quality_changes_container = stack.findContainer({"type": "quality_changes"})
                if user_container.hasProperty(key,"value") or quality_changes_container.hasProperty(key,"value"):
                    # Normal case
                    settings[key] = stack.getProperty(key, "value")
                else:
                    settings[key] = resolved_value
            else:
                # Normal case
                settings[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        start_gcode = settings["machine_start_gcode"]
        settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode

        for key, value in settings.items(): #Add all submessages for each individual setting.
            setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            if key == "machine_start_gcode" or key == "machine_end_gcode": #If it's a g-code message, use special formatting.
                setting_message.value = self._expandGcodeTokens(key, value, settings)
            else:
                setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #5
0
    def load_file(self, file_name, mesh_builder, _use_numpystl = False):
        file_read = False
        if _use_numpystl:
            Logger.log("i", "Using NumPy-STL to load STL data.")
            try:
                self._loadWithNumpySTL(file_name, mesh_builder)
                file_read = True
            except:
                Logger.logException("e", "Reading file failed with Numpy-STL!")
        
        if not file_read:
            Logger.log("i", "Using legacy code to load STL data.")
            f = open(file_name, "rb")
            if not self._loadBinary(mesh_builder, f):
                f.close()
                f = open(file_name, "rt", encoding = "utf-8")
                try:
                    self._loadAscii(mesh_builder, f)
                except UnicodeDecodeError:
                    return None
                f.close()
            Job.yieldThread()  # Yield somewhat to ensure the GUI has time to update a bit.

        mesh_builder.calculateNormals(fast = True)
        mesh_builder.setFileName(file_name)
Beispiel #6
0
    def _buildGlobalSettingsMessage(self, stack):
        settings = self._buildReplacementTokens(stack)

        # Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        start_gcode = settings["machine_start_gcode"]
        bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
        settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
        print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
        settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) == None

        # Replace the setting tokens in start and end g-code.
        # Use values from the first used extruder by default so we get the expected temperatures
        initial_extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")

        settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], initial_extruder_nr)
        settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], initial_extruder_nr)

        # Add all sub-messages for each individual setting.
        for key, value in settings.items():
            setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
    def read(self, file_name):
        mesh_builder = MeshBuilder()
        scene_node = SceneNode()

        if use_numpystl:
            self._loadWithNumpySTL(file_name, mesh_builder)
        else:
            f = open(file_name, "rb")
            if not self._loadBinary(mesh_builder, f):
                f.close()
                f = open(file_name, "rt")
                try:
                    self._loadAscii(mesh_builder, f)
                except UnicodeDecodeError:
                    return None
                f.close()

            Job.yieldThread() # Yield somewhat to ensure the GUI has time to update a bit.

        mesh_builder.calculateNormals(fast = True)

        mesh = mesh_builder.build()
        Logger.log("d", "Loaded a mesh with %s vertices", mesh_builder.getVertexCount())
        scene_node.setMeshData(mesh)
        return scene_node
Beispiel #8
0
    def _handlePerObjectSettings(self, node: CuraSceneNode, message: Arcus.PythonMessage):
        stack = node.callDecoration("getStack")

        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if not stack:
            return

        # Check all settings for relations, so we can also calculate the correct values for dependent settings.
        top_of_stack = stack.getTop()  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            self._addRelations(changed_setting_keys, instance.definition.relations)
            Job.yieldThread()

        # Ensure that the engine is aware what the build extruder is.
        changed_setting_keys.add("extruder_nr")

        # Get values for all changed settings
        for key in changed_setting_keys:
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            extruder = int(round(float(stack.getProperty(key, "limit_to_extruder"))))

            # Check if limited to a specific extruder, but not overridden by per-object settings.
            if extruder >= 0 and key not in changed_setting_keys:
                limited_stack = ExtruderManager.getInstance().getActiveExtruderStacks()[extruder]
            else:
                limited_stack = stack

            setting.value = str(limited_stack.getProperty(key, "value")).encode("utf-8")

            Job.yieldThread()
Beispiel #9
0
 def _buildGlobalInheritsStackMessage(self, stack):
     for key in stack.getAllKeys():
         extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
         if extruder_position >= 0:  # Set to a specific extruder.
             setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder")
             setting_extruder.name = key
             setting_extruder.extruder = extruder_position
         Job.yieldThread()
Beispiel #10
0
 def _buildExtruderMessage(self, stack):
     message = self._slice_message.addRepeatedMessage("extruders")
     message.id = int(stack.getMetaDataEntry("position"))
     for key in stack.getAllKeys():
         setting = message.getMessage("settings").addRepeatedMessage("settings")
         setting.name = key
         setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
         Job.yieldThread()
Beispiel #11
0
 def _handlePerObjectSettings(self, node, message):
     stack = node.callDecoration("getStack")
     if stack:
         for key in stack.getAllKeys():
             setting = message.addRepeatedMessage("settings")
             setting.name = key
             setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
             Job.yieldThread()
Beispiel #12
0
    def run(self):
        loading_message = Message(i18n_catalog.i18nc("@info:status", "Loading <filename>{0}</filename>", self._filename), lifetime = 0, dismissable = False)
        loading_message.setProgress(-1)
        loading_message.show()

        Job.yieldThread() # Yield to any other thread that might want to do something else.

        try:
            begin_time = time.time()
            node = self._handler.read(self._filename)
            end_time = time.time()
            Logger.log("d", "Loading mesh took %s seconds", end_time - begin_time)
        except Exception as e:
            print(e)
        if not node:
            loading_message.hide()

            result_message = Message(i18n_catalog.i18nc("@info:status", "Failed to load <filename>{0}</filename>", self._filename))
            result_message.show()
            return
        if node.getMeshData():
            node.getMeshData().setFileName(self._filename)
        # Scale down to maximum bounds size if that is available
        if hasattr(Application.getInstance().getController().getScene(), "_maximum_bounds"):
            max_bounds = Application.getInstance().getController().getScene()._maximum_bounds
            node._resetAABB()
            bounding_box = node.getBoundingBox()
            timeout_counter = 0
            #As the calculation of the bounding box is in a seperate thread it might be that it's not done yet.
            while bounding_box.width == 0 or bounding_box.height == 0 or bounding_box.depth == 0:
                bounding_box = node.getBoundingBox()
                time.sleep(0.1)
                timeout_counter += 1
                if timeout_counter > 10:
                    break
            if max_bounds.width < bounding_box.width or max_bounds.height < bounding_box.height or max_bounds.depth < bounding_box.depth:
                scale_factor_width = max_bounds.width / bounding_box.width
                scale_factor_height = max_bounds.height / bounding_box.height
                scale_factor_depth = max_bounds.depth / bounding_box.depth
                scale_factor = min(scale_factor_width,scale_factor_height,scale_factor_depth)

                scale_vector = Vector(scale_factor, scale_factor, scale_factor)
                display_scale_factor = scale_factor * 100

                if Preferences.getInstance().getValue("mesh/scale_to_fit") == True:
                    scale_message = Message(i18n_catalog.i18nc("@info:status", "Auto scaled object to {0}% of original size", ("%i" % display_scale_factor)))

                    try:
                        node.scale(scale_vector)
                        scale_message.show()
                    except Exception as e:
                        print(e)

        self.setResult(node)

        loading_message.hide()
        result_message = Message(i18n_catalog.i18nc("@info:status", "Loaded <filename>{0}</filename>", self._filename))
        result_message.show()
Beispiel #13
0
    def run(self):
        status_message = Message(i18n_catalog.i18nc("@info:status", "Finding new location for objects"), lifetime = 0, dismissable=False, progress = 0)
        status_message.show()
        arranger = Arrange.create(fixed_nodes = self._fixed_nodes)

        # Collect nodes to be placed
        nodes_arr = []  # fill with (size, node, offset_shape_arr, hull_shape_arr)
        for node in self._nodes:
            offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = self._min_offset)
            nodes_arr.append((offset_shape_arr.arr.shape[0] * offset_shape_arr.arr.shape[1], node, offset_shape_arr, hull_shape_arr))

        # Sort the nodes with the biggest area first.
        nodes_arr.sort(key=lambda item: item[0])
        nodes_arr.reverse()

        # Place nodes one at a time
        start_priority = 0
        last_priority = start_priority
        last_size = None
        grouped_operation = GroupedOperation()
        found_solution_for_all = True
        for idx, (size, node, offset_shape_arr, hull_shape_arr) in enumerate(nodes_arr):
            # For performance reasons, we assume that when a location does not fit,
            # it will also not fit for the next object (while what can be untrue).
            # We also skip possibilities by slicing through the possibilities (step = 10)
            if last_size == size:  # This optimization works if many of the objects have the same size
                start_priority = last_priority
            else:
                start_priority = 0
            best_spot = arranger.bestSpot(offset_shape_arr, start_prio=start_priority, step=10)
            x, y = best_spot.x, best_spot.y
            node.removeDecorator(ZOffsetDecorator)
            if node.getBoundingBox():
                center_y = node.getWorldPosition().y - node.getBoundingBox().bottom
            else:
                center_y = 0
            if x is not None:  # We could find a place
                last_size = size
                last_priority = best_spot.priority

                arranger.place(x, y, hull_shape_arr)  # take place before the next one

                grouped_operation.addOperation(TranslateOperation(node, Vector(x, center_y, y), set_position = True))
            else:
                Logger.log("d", "Arrange all: could not find spot!")
                found_solution_for_all = False
                grouped_operation.addOperation(TranslateOperation(node, Vector(200, center_y, - idx * 20), set_position = True))

            status_message.setProgress((idx + 1) / len(nodes_arr) * 100)
            Job.yieldThread()

        grouped_operation.push()

        status_message.hide()

        if not found_solution_for_all:
            no_full_solution_message = Message(i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects"))
            no_full_solution_message.show()
Beispiel #14
0
    def run(self):
        if not self._node:
            return
        ## If the scene node is a group, use the hull of the children to calculate its hull.
        if self._node.callDecoration("isGroup"):
            hull = Polygon(numpy.zeros((0, 2), dtype=numpy.int32))
            for child in self._node.getChildren():
                child_hull = child.callDecoration("getConvexHull") 
                if child_hull:
                    hull.setPoints(numpy.append(hull.getPoints(), child_hull.getPoints(), axis = 0))

                if hull.getPoints().size < 3:
                    self._node.callDecoration("setConvexHull", None)
                    self._node.callDecoration("setConvexHullJob", None)
                    return

                Job.yieldThread()

        else: 
            if not self._node.getMeshData():
                return
            mesh = self._node.getMeshData()
            vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
            # Don't use data below 0. TODO; We need a better check for this as this gives poor results for meshes with long edges.
            vertex_data = vertex_data[vertex_data[:,1]>0]
            hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int))

        # First, calculate the normal convex hull around the points
        hull = hull.getConvexHull()

        # Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
        # This is done because of rounding errors.
        hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))

        profile = Application.getInstance().getMachineManager().getActiveProfile()
        if profile:
            if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
                # Printing one at a time and it's not an object in a group
                self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
                head_hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"),numpy.float32)))
                self._node.callDecoration("setConvexHullHead", head_hull)
                hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
            else:
                self._node.callDecoration("setConvexHullHead", None)
        hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
        self._node.callDecoration("setConvexHullNode", hull_node)
        self._node.callDecoration("setConvexHull", hull)
        self._node.callDecoration("setConvexHullJob", None)

        if self._node.getParent().callDecoration("isGroup"):
            job = self._node.getParent().callDecoration("getConvexHullJob")
            if job:
                job.cancel()
            self._node.getParent().callDecoration("setConvexHull", None)
            hull_node = self._node.getParent().callDecoration("getConvexHullNode")
            if hull_node:
                hull_node.setParent(None)
Beispiel #15
0
 def _handlePerObjectSettings(self, node, message):
     stack = node.callDecoration("getStack")
     # Check if the node has a stack attached to it and the stack has any settings in the top container.
     if stack and stack.getTop().getAllKeys():
         # Because we want to use inheritance correctly, we send all settings as seen from the per object stack.
         for key in stack.getAllKeys():
             setting = message.addRepeatedMessage("settings")
             setting.name = key
             setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
             Job.yieldThread()
Beispiel #16
0
    def _buildExtruderMessageFromGlobalStack(self, stack):
        message = self._slice_message.addRepeatedMessage("extruders")

        for key in stack.getAllKeys():
            # Do not send settings that are not settable_per_extruder.
            if not stack.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage("settings")
            setting.name = key
            setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
            Job.yieldThread()
Beispiel #17
0
    def _checkStackForErrors(self, stack):
        if stack is None:
            return False

        for key in stack.getAllKeys():
            validation_state = stack.getProperty(key, "validationState")
            if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
                Logger.log("w", "Setting %s is not valid, but %s. Aborting slicing.", key, validation_state)
                return True
            Job.yieldThread()
        return False
Beispiel #18
0
    def _onJobFinished(self, job: Job) -> None:
        if isinstance(job, WriteFileJob):
            if not job.getResult() or not job.getAddToRecentFiles():
                # For a write file job, if it failed or it doesn't need to be added to the recent files list, we do not
                # add it.
                return
        elif (not isinstance(job, ReadMeshJob) and not isinstance(job, ReadFileJob)) or not job.getResult():
            return

        if isinstance(job, (ReadMeshJob, ReadFileJob, WriteFileJob)):
            self.addFileToRecentFiles(job.getFileName())
Beispiel #19
0
    def run(self):
        status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0,
                                 dismissable=False, progress=0, title = i18n_catalog.i18nc("@info:title", "Placing Object"))
        status_message.show()
        scene = Application.getInstance().getController().getScene()

        total_progress = len(self._objects) * self._count
        current_progress = 0

        root = scene.getRoot()
        arranger = Arrange.create(scene_root=root)
        nodes = []
        for node in self._objects:
            # If object is part of a group, multiply group
            current_node = node
            while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
                current_node = current_node.getParent()

            node_too_big = False
            if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300:
                offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset)
            else:
                node_too_big = True

            found_solution_for_all = True
            for i in range(self._count):
                # We do place the nodes one by one, as we want to yield in between.
                if not node_too_big:
                    node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
                if node_too_big or not solution_found:
                    found_solution_for_all = False
                    new_location = node.getPosition()
                    new_location = new_location.set(z = 100 - i * 20)
                    node.setPosition(new_location)

                nodes.append(node)
                current_progress += 1
                status_message.setProgress((current_progress / total_progress) * 100)
                Job.yieldThread()

            Job.yieldThread()

        if nodes:
            op = GroupedOperation()
            for new_node in nodes:
                op.addOperation(AddSceneNodeOperation(new_node, current_node.getParent()))
            op.push()
        status_message.hide()

        if not found_solution_for_all:
            no_full_solution_message = Message(i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects"), title = i18n_catalog.i18nc("@info:title", "Placing Object"))
            no_full_solution_message.show()
Beispiel #20
0
    def _buildReplacementTokens(self, stack) -> dict:
        result = {}
        for key in stack.getAllKeys():
            result[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        result["print_bed_temperature"] = result["material_bed_temperature"] #Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]

        return result
Beispiel #21
0
    def _buildExtruderMessage(self, stack):
        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))

        material_instance_container = stack.findContainer({"type": "material"})

        for key in stack.getAllKeys():
            setting = message.getMessage("settings").addRepeatedMessage("settings")
            setting.name = key
            if key == "material_guid" and material_instance_container:
                # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
                setting.value = str(material_instance_container.getMetaDataEntry("GUID", "")).encode("utf-8")
            else:
                setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
            Job.yieldThread()
Beispiel #22
0
    def run(self):
        layer_data = None
        for node in DepthFirstIterator(self._scene.getRoot()):
            layer_data = node.callDecoration("getLayerData")
            if layer_data:
                break

        if self._cancel or not layer_data:
            return

        layer_mesh = MeshBuilder()
        for i in range(self._solid_layers):
            layer_number = self._layer_number - i
            if layer_number < 0:
                continue

            try:
                layer = layer_data.getLayer(layer_number).createMesh()
            except Exception:
                Logger.logException("w", "An exception occurred while creating layer mesh.")
                return

            if not layer or layer.getVertices() is None:
                continue

            layer_mesh.addIndices(layer_mesh.getVertexCount() + layer.getIndices())
            layer_mesh.addVertices(layer.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 = numpy.ones((1, 4), dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0
            brightness[0, 3] = 1.0
            layer_mesh.addColors(layer.getColors() * brightness)

            if self._cancel:
                return

            Job.yieldThread()

        if self._cancel:
            return

        Job.yieldThread()
        jump_mesh = layer_data.getLayer(self._layer_number).createJumps()
        if not jump_mesh or jump_mesh.getVertices() is None:
            jump_mesh = None

        self.setResult({"layers": layer_mesh.build(), "jumps": jump_mesh})
Beispiel #23
0
    def run(self) -> None:
        if self._handler is None:
            Logger.log("e", "FileHandler was not set.")
            return None
        reader = self._handler.getReaderForFile(self._filename)
        if not reader:
            result_message = Message(i18n_catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Cannot open files of the type of <filename>{0}</filename>", self._filename), lifetime=0, title = i18n_catalog.i18nc("@info:title", "Invalid File"))
            result_message.show()
            return

        # Give the plugin a chance to display a dialog before showing the loading UI
        try:
            pre_read_result = reader.preRead(self._filename)
        except:
            Logger.logException("e", "Failed to pre-read the file %s", self._filename)
            pre_read_result = MeshReader.PreReadResult.failed

        if pre_read_result != MeshReader.PreReadResult.accepted:
            if pre_read_result == MeshReader.PreReadResult.failed:
                result_message = Message(i18n_catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Failed to load <filename>{0}</filename>", self._filename),
                                         lifetime=0,
                                         title = i18n_catalog.i18nc("@info:title", "Invalid File"))
                result_message.show()
            return

        self._loading_message = Message(self._filename,
                                        lifetime=0,
                                        dismissable=False,
                                        title = i18n_catalog.i18nc("@info:title", "Loading"))
        self._loading_message.setProgress(-1)
        self._loading_message.show()

        Job.yieldThread()  # Yield to any other thread that might want to do something else.
        begin_time = time.time()
        try:
            self.setResult(self._handler.readerRead(reader, self._filename))
        except:
            Logger.logException("e", "Exception occurred while loading file %s", self._filename)
        finally:
            end_time = time.time()
            Logger.log("d", "Loading file took %0.1f seconds", end_time - begin_time)
            if self._result is None:
                self._loading_message.hide()
                result_message = Message(i18n_catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Failed to load <filename>{0}</filename>", self._filename), lifetime=0, title = i18n_catalog.i18nc("@info:title", "Invalid File"))
                result_message.show()
                return
            self._loading_message.hide()
 def run(self):
     Job.yieldThread()
     if self._writer.write(self._stream, self._node, self._mode):
         self._stream.seek(0)
         select_bool = str(Preferences.getInstance().getValue("octoprint/select")).lower()
         print_bool = str(Preferences.getInstance().getValue("octoprint/print")).lower()
         url = Preferences.getInstance().getValue("octoprint/base_url") + "api/files/local"
         api_key = Preferences.getInstance().getValue("octoprint/api_key")
         result = requests.post(url,
                                files={'file': (self._file_name, self._stream),
                                       'select': ('', select_bool),
                                       'print': ('', print_bool)},
                                headers={'User-agent': 'Cura AutoUploader Plugin',
                                         'X-Api-Key': api_key})
         self.setResult(result)
     else:
         self.setResult(False)
Beispiel #25
0
    def run(self):
        layer_data = None
        for node in DepthFirstIterator(self._scene.getRoot()):
            layer_data = node.callDecoration("getLayerData")
            if layer_data:
                break

        if self._cancel or not layer_data:
            return

        layer_mesh = MeshBuilder()
        for i in range(self._solid_layers):
            layer_number = self._layer_number - i
            if layer_number < 0:
                continue

            try:
                layer = layer_data.getLayer(layer_number).createMesh()
            except Exception as e:
                print(e)
                return

            if not layer or layer.getVertices() is None:
                continue

            layer_mesh.addVertices(layer.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
            layer_mesh.addColors(layer.getColors() * brightness)

            if self._cancel:
                return

            Job.yieldThread()

        if self._cancel:
            return

        Job.yieldThread()
        jump_mesh = layer_data.getLayer(self._layer_number).createJumps()
        if not jump_mesh or jump_mesh.getVertices() is None:
            jump_mesh = None

        self.setResult({"layers": layer_mesh.build(), "jumps": jump_mesh})
Beispiel #26
0
    def _generateGlicerConfig(self, filename: str, settings: Dict) -> None:
        root = eltree.Element("root")
        normalize = "normalize_when_load"
        sub = eltree.SubElement(root,
                                "param",
                                attrib={
                                    'NAME': normalize,
                                    'PARAM': ''
                                })
        sub.text = "0"
        for region, params in params_dict.items():
            for name, value in params.items():
                sub = eltree.SubElement(root,
                                        "param",
                                        attrib={
                                            'NAME': name,
                                            'REGION': region,
                                            'PARAM': ''
                                        })
                setting_value = settings.get(value.get("stack_key", ""), None)
                if setting_value is not None:
                    if isinstance(setting_value, bool):
                        if setting_value:
                            setting_value = "1"
                        else:
                            setting_value = "0"
                    if name in [
                            "rsize", "first_offset", "last_offset",
                            "support_base_r"
                    ]:
                        setting_value /= 2
                    if name == "skin_width":
                        setting_value = setting_value if setting_value <= 4 else 4
                    if name == "supportangle":
                        supports_enabled = settings.get(
                            "support_enable_cylindrical", False)
                        setting_value = 90 - setting_value if supports_enabled else "0"

                else:
                    setting_value = value.get("default_value", "")
                sub.text = setting_value.__str__()
                Job.yieldThread()
        settings_string = eltree.tostring(
            root, encoding='Windows-1251').decode("Windows-1251")
        with open(filename, mode='w') as f:
            f.write(settings_string)
Beispiel #27
0
    def load_file(self, file_name, mesh_builder, _use_numpystl = False):
        if _use_numpystl:
            self._loadWithNumpySTL(file_name, mesh_builder)
        else:
            f = open(file_name, "rb")
            if not self._loadBinary(mesh_builder, f):
                f.close()
                f = open(file_name, "rt")
                try:
                    self._loadAscii(mesh_builder, f)
                except UnicodeDecodeError:
                    return None
                f.close()
            Job.yieldThread()  # Yield somewhat to ensure the GUI has time to update a bit.

        mesh_builder.calculateNormals(fast = True)
        mesh_builder.setFileName(file_name)
Beispiel #28
0
    def _buildGlobalInheritsStackMessage(self, stack: ContainerStack) -> None:
        """Sends for some settings which extruder they should fallback to if not set.

        This is only set for settings that have the limit_to_extruder
        property.

        :param stack: The global stack with all settings, from which to read the
            limit_to_extruder property.
        """

        for key in stack.getAllKeys():
            extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
            if extruder_position >= 0:  # Set to a specific extruder.
                setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder")
                setting_extruder.name = key
                setting_extruder.extruder = extruder_position
            Job.yieldThread()
Beispiel #29
0
    def _buildReplacementTokens(self, stack) -> dict:
        result = {}
        for key in stack.getAllKeys():
            result[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]

        initial_extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")
        result["initial_extruder_nr"] = initial_extruder_nr

        return result
Beispiel #30
0
    def load_file(self, file_name, mesh_builder, _use_numpystl = False):
        if _use_numpystl:
            self._loadWithNumpySTL(file_name, mesh_builder)
        else:
            f = open(file_name, "rb")
            if not self._loadBinary(mesh_builder, f):
                f.close()
                f = open(file_name, "rt")
                try:
                    self._loadAscii(mesh_builder, f)
                except UnicodeDecodeError:
                    return None
                f.close()
            Job.yieldThread()  # Yield somewhat to ensure the GUI has time to update a bit.

        mesh_builder.calculateNormals(fast = True)
        mesh_builder.setFileName(file_name)
Beispiel #31
0
 def _buildGlobalInheritsStackMessage(self, stack):
     for key in stack.getAllKeys():
         extruder = int(
             round(float(stack.getProperty(key, "limit_to_extruder"))))
         if key == "adhesion_extruder_nr" and int(
                 stack.getProperty(key, "value")) == -1:
             if "Left" in ExtruderManager.getInstance(
             ).getUsedExtruderStacks()[0].getName():
                 extruder = 0
             else:
                 extruder = 1
         if extruder >= 0:  #Set to a specific extruder.
             setting_extruder = self._slice_message.addRepeatedMessage(
                 "limit_to_extruder")
             setting_extruder.name = key
             setting_extruder.extruder = extruder
         Job.yieldThread()
Beispiel #32
0
    def run(self):
        layer_data = None
        for node in DepthFirstIterator(self._scene.getRoot()):
            layer_data = node.callDecoration("getLayerData")
            if layer_data:
                break

        if self._cancel or not layer_data:
            return

        layer_mesh = MeshData()
        for i in range(self._solid_layers):
            layer_number = self._layer_number - i
            if layer_number < 0:
                continue

            try:
                layer = layer_data.getLayer(layer_number).createMesh()
            except Exception as e:
                print(e)
                return

            if not layer or layer.getVertices() is None:
                continue

            layer_mesh.addVertices(layer.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
            layer_mesh.addColors(layer.getColors() * brightness)

            if self._cancel:
                return

            Job.yieldThread()

        if self._cancel:
            return

        Job.yieldThread()
        jump_mesh = layer_data.getLayer(self._layer_number).createJumps()
        if not jump_mesh or jump_mesh.getVertices() is None:
            jump_mesh = None

        self.setResult({ "layers": layer_mesh, "jumps": jump_mesh })
Beispiel #33
0
    def _handlePerObjectSettings(self, node: CuraSceneNode,
                                 message: Arcus.PythonMessage):
        """Check if a node has per object settings and ensure that they are set correctly in the message

        :param node: Node to check.
        :param message: object_lists message to put the per object settings in
        """

        stack = node.callDecoration("getStack")

        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if not stack:
            return

        # Check all settings for relations, so we can also calculate the correct values for dependent settings.
        top_of_stack = stack.getTop()  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            self._addRelations(changed_setting_keys,
                               instance.definition.relations)
            Job.yieldThread()

        # Ensure that the engine is aware what the build extruder is.
        changed_setting_keys.add("extruder_nr")

        # Get values for all changed settings
        for key in changed_setting_keys:
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            extruder = int(
                round(float(stack.getProperty(key, "limit_to_extruder"))))

            # Check if limited to a specific extruder, but not overridden by per-object settings.
            if extruder >= 0 and key not in changed_setting_keys:
                limited_stack = ExtruderManager.getInstance(
                ).getActiveExtruderStacks()[extruder]
            else:
                limited_stack = stack

            setting.value = str(limited_stack.getProperty(
                key, "value")).encode("utf-8")

            Job.yieldThread()
Beispiel #34
0
    def _buildGlobalSettingsMessage(self, stack):
        keys = stack.getAllKeys()
        settings = {}
        for key in keys:
            settings[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        start_gcode = settings["machine_start_gcode"]
        #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        bed_temperature_settings = {
            "material_bed_temperature", "material_bed_temperature_layer_0"
        }
        settings["material_bed_temp_prepend"] = all(
            ("{" + setting + "}" not in start_gcode
             for setting in bed_temperature_settings))
        print_temperature_settings = {
            "material_print_temperature", "material_print_temperature_layer_0",
            "default_material_print_temperature",
            "material_initial_print_temperature",
            "material_final_print_temperature", "material_standby_temperature"
        }
        settings["material_print_temp_prepend"] = all(
            ("{" + setting + "}" not in start_gcode
             for setting in print_temperature_settings))

        settings["print_bed_temperature"] = settings[
            "material_bed_temperature"]
        settings["print_temperature"] = settings["material_print_temperature"]

        settings["time"] = time.strftime('%H:%M:%S')
        settings["date"] = time.strftime('%d-%m-%Y')
        settings["day"] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri',
                           'Sat'][int(time.strftime('%w'))]

        for key, value in settings.items(
        ):  #Add all submessages for each individual setting.
            setting_message = self._slice_message.getMessage(
                "global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            if key == "machine_start_gcode" or key == "machine_end_gcode" or key == "machine_extruder_start_code" or key == "machine_extruder_end_code":  #If it's a g-code message, use special formatting.
                setting_message.value = self._expandGcodeTokens(
                    key, value, settings)
            else:
                setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
    def run(self):
        for node in self._nodes:
            transformed_vertices = node.getMeshDataTransformed().getVertices()

            result = Tweak(transformed_vertices, extended_mode = self._extended_mode, verbose=False, progress_callback=self.updateProgress)

            [v, phi] = result.euler_parameter

            # Convert the new orientation into quaternion
            new_orientation = Quaternion.fromAngleAxis(phi, Vector(-v[0], -v[1], -v[2]))
            # Rotate the axis frame.
            rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1, 0, 0))
            new_orientation = rotation * new_orientation

            # Ensure node gets the new orientation
            node.rotate(new_orientation, SceneNode.TransformSpace.World)

            Job.yieldThread()
Beispiel #36
0
    def _buildReplacementTokens(self, stack) -> dict:
        result = {}
        for key in stack.getAllKeys():
            value = stack.getProperty(key, "value")
            result[key] = value
            Job.yieldThread()

        result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]

        initial_extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")
        result["initial_extruder_nr"] = initial_extruder_nr

        return result
Beispiel #37
0
    def _buildExtruderMessage(self, stack):
        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))

        material_instance_container = stack.findContainer({"type": "material"})

        for key in stack.getAllKeys():
            # Do not send settings that are not settable_per_extruder.
            if not stack.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage("settings")
            setting.name = key
            if key == "material_guid" and material_instance_container:
                # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
                setting.value = str(material_instance_container.getMetaDataEntry("GUID", "")).encode("utf-8")
            else:
                setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
            Job.yieldThread()
Beispiel #38
0
    def _checkStackForErrors(self, stack: ContainerStack) -> bool:
        """Check if a stack has any errors."""
        """returns true if it has errors, false otherwise."""

        top_of_stack = cast(InstanceContainer,
                            stack.getTop())  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            if instance is None:
                continue
            self._addRelations(changed_setting_keys,
                               instance.definition.relations)
            Job.yieldThread()

        for changed_setting_key in changed_setting_keys:
            if not stack.getProperty(changed_setting_key, "enabled"):
                continue

            validation_state = stack.getProperty(changed_setting_key,
                                                 "validationState")

            if validation_state is None:
                definition = cast(
                    SettingDefinition,
                    stack.getSettingDefinition(changed_setting_key))
                validator_type = SettingDefinition.getValidatorForType(
                    definition.type)
                if validator_type:
                    validator = validator_type(changed_setting_key)
                    validation_state = validator(stack)
            if validation_state in (ValidatorState.Exception,
                                    ValidatorState.MaximumError,
                                    ValidatorState.MinimumError,
                                    ValidatorState.Invalid):
                Logger.log(
                    "w", "Setting %s is not valid, but %s. Aborting slicing.",
                    changed_setting_key, validation_state)
                return True
            Job.yieldThread()

        return False
Beispiel #39
0
    def _buildGlobalSettingsMessage(self, stack: ContainerStack) -> None:
        settings = self._buildReplacementTokens(stack)

        # Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        start_gcode = settings["machine_start_gcode"]
        bed_temperature_settings = [
            "material_bed_temperature", "material_bed_temperature_layer_0"
        ]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(
            bed_temperature_settings
        )  # match {setting} as well as {setting, extruder_nr}
        settings["material_bed_temp_prepend"] = re.search(
            pattern, start_gcode) == None
        print_temperature_settings = [
            "material_print_temperature", "material_print_temperature_layer_0",
            "default_material_print_temperature",
            "material_initial_print_temperature",
            "material_final_print_temperature", "material_standby_temperature"
        ]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(
            print_temperature_settings
        )  # match {setting} as well as {setting, extruder_nr}
        settings["material_print_temp_prepend"] = re.search(
            pattern, start_gcode) == None

        # Replace the setting tokens in start and end g-code.
        # Use values from the first used extruder by default so we get the expected temperatures
        initial_extruder_stack = CuraApplication.getInstance(
        ).getExtruderManager().getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty(
            "extruder_nr", "value")

        settings["machine_start_gcode"] = self._expandGcodeTokens(
            settings["machine_start_gcode"], initial_extruder_nr)
        settings["machine_end_gcode"] = self._expandGcodeTokens(
            settings["machine_end_gcode"], initial_extruder_nr)

        # Add all sub-messages for each individual setting.
        for key, value in settings.items():
            setting_message = self._slice_message.getMessage(
                "global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #40
0
    def run(self):
        status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0,
                                 dismissable=False, progress=0)
        status_message.show()
        scene = Application.getInstance().getController().getScene()
        node = scene.findObject(self._object_id)

        if not node and self._object_id != 0:  # Workaround for tool handles overlapping the selected object
            node = Selection.getSelectedObject(0)

        # If object is part of a group, multiply group
        current_node = node
        while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
            current_node = current_node.getParent()

        root = scene.getRoot()
        arranger = Arrange.create(scene_root=root)
        offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset)
        nodes = []
        found_solution_for_all = True
        for i in range(self._count):
            # We do place the nodes one by one, as we want to yield in between.
            node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
            if not solution_found:
                found_solution_for_all = False
                new_location = node.getPosition()
                new_location = new_location.set(z = 100 - i * 20)
                node.setPosition(new_location)

            nodes.append(node)
            Job.yieldThread()
            status_message.setProgress((i + 1) / self._count * 100)

        if nodes:
            op = GroupedOperation()
            for new_node in nodes:
                op.addOperation(AddSceneNodeOperation(new_node, current_node.getParent()))
            op.push()
        status_message.hide()

        if not found_solution_for_all:
            no_full_solution_message = Message(i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects"))
            no_full_solution_message.show()
Beispiel #41
0
    def _buildGlobalSettingsMessage(self, stack):
        settings = self._buildReplacementTokens(stack)

        start_gcode = settings["machine_start_gcode"]
        #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        bed_temperature_settings = {"material_bed_temperature", "material_bed_temperature_layer_0"}
        settings["material_bed_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in bed_temperature_settings))
        print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"}
        settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))

        #Replace the setting tokens in start and end g-code.
        settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], settings)
        settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], settings)

        for key, value in settings.items(): #Add all submessages for each individual setting.
            setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #42
0
    def _handlePerObjectSettings(self, node, message):
        profile = node.callDecoration("getProfile")
        if profile:
            for key, value in profile.getAllSettingValues().items():
                setting = message.addRepeatedMessage("settings")
                setting.name = key
                setting.value = str(value).encode()

                Job.yieldThread()

        object_settings = node.callDecoration("getAllSettingValues")
        if not object_settings:
            return
        for key, value in object_settings.items():
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            setting.value = str(value).encode()

            Job.yieldThread()
Beispiel #43
0
    def _handlePerObjectSettings(self, node, message):
        profile = node.callDecoration("getProfile")
        if profile:
            for key, value in profile.getAllSettingValues().items():
                setting = message.addRepeatedMessage("settings")
                setting.name = key
                setting.value = str(value).encode()

                Job.yieldThread()

        object_settings = node.callDecoration("getAllSettingValues")
        if not object_settings:
            return
        for key, value in object_settings.items():
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            setting.value = str(value).encode()

            Job.yieldThread()
Beispiel #44
0
    def _buildReplacementTokens(self, stack: ContainerStack) -> Dict[str, Any]:
        result = {}
        for key in stack.getAllKeys():
            value = stack.getProperty(key, "value")
            result[key] = value
            Job.yieldThread()

        result["print_bed_temperature"] = result[
            "material_bed_temperature"]  # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["travel_speed"] = result["speed_travel"]
        result["time"] = time.strftime("%H:%M:%S")  #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
                         "Sat"][int(time.strftime("%w"))]
        result["initial_extruder_nr"] = CuraApplication.getInstance(
        ).getExtruderManager().getInitialExtruderNr()

        return result
Beispiel #45
0
    def run(self) -> None:
        layer_data = None
        for node in DepthFirstIterator(self._scene.getRoot()):  # type: ignore
            layer_data = node.callDecoration("getLayerData")
            if layer_data:
                break
        if self._cancel or not layer_data:
            return
        layer_mesh = MeshBuilder()
        for i in range(self._solid_layers):
            layer_number = self._layer_number - i
            if layer_number < 0:
                continue
            try:
                layer = layer_data.getLayer(layer_number).createMesh()
            except Exception:
                Logger.logException(
                    "w", "An exception occurred while creating layer mesh.")
                return
            if not layer or layer.getVertices() is None:
                continue
            layer_mesh.addIndices(layer_mesh.getVertexCount() +
                                  layer.getIndices())
            layer_mesh.addVertices(layer.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 = numpy.ones(
                (1, 4), dtype=numpy.float32) * (2.0 -
                                                (i / self._solid_layers)) / 2.0
            brightness[0, 3] = 1.0
            layer_mesh.addColors(layer.getColors() * brightness)
            if self._cancel:
                return
            Job.yieldThread()
        if self._cancel:
            return
        Job.yieldThread()
        jump_mesh = layer_data.getLayer(self._layer_number).createJumps()
        if not jump_mesh or jump_mesh.getVertices() is None:
            jump_mesh = None

        self.setResult({"layers": layer_mesh.build(), "jumps": jump_mesh})
Beispiel #46
0
    def _buildExtruderMessage(self, stack):
        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))

        settings = self._buildReplacementTokens(stack)

        # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
        settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "")

        # Replace the setting tokens in start and end g-code.
        settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], settings)
        settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], settings)

        for key, value in settings.items():
            # Do not send settings that are not settable_per_extruder.
            if not stack.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage("settings")
            setting.name = key
            setting.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #47
0
    def _handlePerObjectSettings(self, node, message):
        stack = node.callDecoration("getStack")
        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if stack:
            # Check all settings for relations, so we can also calculate the correct values for dependant settings.
            changed_setting_keys = set(stack.getTop().getAllKeys())
            for key in stack.getTop().getAllKeys():
                instance = stack.getTop().getInstance(key)
                self._addRelations(changed_setting_keys, instance.definition.relations)
                Job.yieldThread()

            # Ensure that the engine is aware what the build extruder is
            if stack.getProperty("machine_extruder_count", "value") > 1:
                changed_setting_keys.add("extruder_nr")

            # Get values for all changed settings
            for key in changed_setting_keys:
                setting = message.addRepeatedMessage("settings")
                setting.name = key
                setting.value = str(stack.getProperty(key, "value")).encode("utf-8")
                Job.yieldThread()
Beispiel #48
0
    def _checkStackForErrors(self, stack: ContainerStack) -> bool:
        if stack is None:
            return False

        # if there are no per-object settings we don't need to check the other settings here
        stack_top = stack.getTop()
        if stack_top is None or not stack_top.getAllKeys():
            return False

        for key in stack.getAllKeys():
            validation_state = stack.getProperty(key, "validationState")
            if validation_state in (ValidatorState.Exception,
                                    ValidatorState.MaximumError,
                                    ValidatorState.MinimumError,
                                    ValidatorState.Invalid):
                Logger.log(
                    "w", "Setting %s is not valid, but %s. Aborting slicing.",
                    key, validation_state)
                return True
            Job.yieldThread()
        return False
Beispiel #49
0
    def _buildExtruderMessage(self, stack: ContainerStack) -> None:
        """Create extruder message from stack"""

        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))
        if not self._all_extruders_settings:
            self._cacheAllExtruderSettings()

        if self._all_extruders_settings is None:
            return

        extruder_nr = stack.getProperty("extruder_nr", "value")
        settings = self._all_extruders_settings[str(extruder_nr)].copy()

        # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
        settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "")

        # Replace the setting tokens in start and end g-code.
        extruder_nr = stack.getProperty("extruder_nr", "value")
        settings["machine_extruder_start_code"] = self._expandGcodeTokens(
            settings["machine_extruder_start_code"], extruder_nr)
        settings["machine_extruder_end_code"] = self._expandGcodeTokens(
            settings["machine_extruder_end_code"], extruder_nr)

        global_definition = cast(
            ContainerInterface,
            cast(ContainerStack, stack.getNextStack()).getBottom())
        own_definition = cast(ContainerInterface, stack.getBottom())

        for key, value in settings.items():
            # Do not send settings that are not settable_per_extruder.
            # Since these can only be set in definition files, we only have to ask there.
            if not global_definition.getProperty(key, "settable_per_extruder") and \
                    not own_definition.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage(
                "settings")
            setting.name = key
            setting.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #50
0
    def _buildGlobalSettingsMessage(self, stack):
        keys = stack.getAllKeys()
        settings = {}
        for key in keys:
            # Use resolvement value if available, or take the value
            resolved_value = stack.getProperty(key, "resolve")
            if resolved_value is not None:
                # There is a resolvement value. Check if we need to use it.
                user_container = stack.findContainer({"type": "user"})
                quality_changes_container = stack.findContainer(
                    {"type": "quality_changes"})
                if user_container.hasProperty(
                        key, "value") or quality_changes_container.hasProperty(
                            key, "value"):
                    # Normal case
                    settings[key] = stack.getProperty(key, "value")
                else:
                    settings[key] = resolved_value
            else:
                # Normal case
                settings[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        start_gcode = settings["machine_start_gcode"]
        settings[
            "material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode  #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        settings[
            "material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode

        for key, value in settings.items(
        ):  #Add all submessages for each individual setting.
            setting_message = self._slice_message.getMessage(
                "global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            if key == "machine_start_gcode" or key == "machine_end_gcode":  #If it's a g-code message, use special formatting.
                setting_message.value = self._expandGcodeTokens(
                    key, value, settings)
            else:
                setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #51
0
def test_getSetError():
    job = Job()
    exception = Exception("Some Error :(")
    job.setError(exception)

    assert job.getError() == exception
    assert job.hasError()
Beispiel #52
0
    def _buildGlobalSettingsMessage(self, stack):
        settings = self._buildReplacementTokens(stack)

        # Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        start_gcode = settings["machine_start_gcode"]
        bed_temperature_settings = {
            "material_bed_temperature", "material_bed_temperature_layer_0"
        }
        settings["material_bed_temp_prepend"] = all(
            ("{" + setting + "}" not in start_gcode
             for setting in bed_temperature_settings))
        print_temperature_settings = {
            "material_print_temperature", "material_print_temperature_layer_0",
            "default_material_print_temperature",
            "material_initial_print_temperature",
            "material_final_print_temperature", "material_standby_temperature"
        }
        settings["material_print_temp_prepend"] = all(
            ("{" + setting + "}" not in start_gcode
             for setting in print_temperature_settings))

        # Replace the setting tokens in start and end g-code.
        # Use values from the first used extruder by default so we get the expected temperatures
        initial_extruder_stack = Application.getInstance().getExtruderManager(
        ).getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty(
            "extruder_nr", "value")

        settings["machine_start_gcode"] = self._expandGcodeTokens(
            settings["machine_start_gcode"], initial_extruder_nr)
        settings["machine_end_gcode"] = self._expandGcodeTokens(
            settings["machine_end_gcode"], initial_extruder_nr)

        # Add all sub-messages for each individual setting.
        for key, value in settings.items():
            setting_message = self._slice_message.getMessage(
                "global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #53
0
    def _buildReplacementTokens(self, stack: ContainerStack) -> Dict[str, Any]:
        """Creates a dictionary of tokens to replace in g-code pieces.

        This indicates what should be replaced in the start and end g-codes.
        :param stack: The stack to get the settings from to replace the tokens with.
        :return: A dictionary of replacement tokens to the values they should be replaced with.
        """

        result = {}
        for key in stack.getAllKeys():
            result[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["travel_speed"] = result["speed_travel"]
        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]
        result["initial_extruder_nr"] = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()

        return result
Beispiel #54
0
    def _loadBinary(self, mesh_builder, f):
        f.read(80)  # Skip the header

        num_faces = struct.unpack("<I", f.read(4))[0]
        # On ascii files, the num_faces will be big, due to 4 ascii bytes being seen as an unsigned int.
        if num_faces < 1 or num_faces > 1000000000:
            return False
        f.seek(0, os.SEEK_END)
        file_size = f.tell()
        f.seek(84, os.SEEK_SET)
        if file_size < num_faces * 50 + 84:
            return False

        mesh_builder.reserveFaceCount(num_faces)
        for idx in range(0, num_faces):
            data = struct.unpack(b"<ffffffffffffH", f.read(50))
            mesh_builder.addFaceByPoints(data[3], data[5], -data[4], data[6],
                                         data[8], -data[7], data[9], data[11],
                                         -data[10])
            Job.yieldThread()

        return True
Beispiel #55
0
    def run(self):
        if self._handler is None:
            Logger.log("e", "FileHandler was not set.")
            return None
        reader = self._handler.getReaderForFile(self._filename)
        if not reader:
            result_message = Message(i18n_catalog.i18nc("@info:status", "Cannot open file type <filename>{0}</filename>", self._filename), lifetime=0)
            result_message.show()
            return

        # Give the plugin a chance to display a dialog before showing the loading UI
        pre_read_result = reader.preRead(self._filename)

        if pre_read_result != MeshReader.PreReadResult.accepted:
            if pre_read_result == MeshReader.PreReadResult.failed:
                result_message = Message(i18n_catalog.i18nc("@info:status", "Failed to load <filename>{0}</filename>", self._filename), lifetime=0)
                result_message.show()
            return

        self._loading_message = Message(i18n_catalog.i18nc("@info:status", "Loading <filename>{0}</filename>", self._filename), lifetime=0, dismissable=False)
        self._loading_message.setProgress(-1)
        self._loading_message.show()

        Job.yieldThread()  # Yield to any other thread that might want to do something else.

        try:
            begin_time = time.time()
            self.setResult(self._handler.readerRead(reader, self._filename))
            end_time = time.time()
            Logger.log("d", "Loading file took %s seconds", end_time - begin_time)
        except:
            Logger.logException("e", "Exception occurred while loading file %s", self._filename)
        finally:
            if self._result is None:
                self._loading_message.hide()
                result_message = Message(i18n_catalog.i18nc("@info:status", "Failed to load <filename>{0}</filename>", self._filename), lifetime=0)
                result_message.show()
                return
            self._loading_message.hide()
Beispiel #56
0
    def run(self):
        while self._process.poll() is None:
            Job.yieldThread()
            if self._is_cancelled:
                return

        if self._build_plate_number is None:
            self.setResult(StartJobResult.Error)
            return
        object_list = self._slice_message.getRepeatedMessage("object_lists", 0)
        radius = self._global_stack.getProperty("spherical_mode_base_radius",
                                                "value")
        layer_height = self._global_stack.getProperty("layer_height", "value")
        layers_skip = int(radius // layer_height) + 2
        for index in range(len(self._output_path)):
            files = glob.glob(self._output_path[index] + "*" + ".stl")

            obj = object_list.getRepeatedMessage("objects", index)
            files = files[layers_skip:]
            for file_idx, filename in enumerate(files):
                if file_idx == 0:
                    obj.filename = filename
                else:
                    new_obj = object_list.addRepeatedMessage("objects")
                    new_obj.id = id(filename)
                    new_obj.name = obj.name + str(file_idx)
                    for setting_idx in range(
                            obj.repeatedMessageCount("settings")):
                        obj_setting = obj.getRepeatedMessage(
                            "settings", setting_idx)
                        new_obj_setting = new_obj.addRepeatedMessage(
                            "settings")
                        new_obj_setting.name = obj_setting.name
                        new_obj_setting.value = obj_setting.value
                    new_obj.filename = filename
            #cli.filename = 'C:\\Users\\frylo\\AppData\\Local\\Temp\\test2_perimeterinflll.cli'

        self.setResult(StartJobResult.Finished)
Beispiel #57
0
    def _buildGlobalSettingsMessage(self, stack: ContainerStack) -> None:
        """Sends all global settings to the engine.

        The settings are taken from the global stack. This does not include any
        per-extruder settings or per-object settings.
        """

        if not self._all_extruders_settings:
            self._cacheAllExtruderSettings()

        if self._all_extruders_settings is None:
            return

        settings = self._all_extruders_settings["-1"].copy()

        # Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
        start_gcode = settings["machine_start_gcode"]
        # Remove all the comments from the start g-code
        start_gcode = re.sub(r";.+?(\n|$)", "\n", start_gcode)
        bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
        settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
        print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature", "print_temperature"]
        pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
        settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) is None

        # Replace the setting tokens in start and end g-code.
        # Use values from the first used extruder by default so we get the expected temperatures
        initial_extruder_nr = CuraApplication.getInstance().getExtruderManager().getInitialExtruderNr()
        settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], initial_extruder_nr)
        settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], initial_extruder_nr)

        # Add all sub-messages for each individual setting.
        for key, value in settings.items():
            setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
            setting_message.name = key
            setting_message.value = str(value).encode("utf-8")
            Job.yieldThread()
Beispiel #58
0
    def _buildReplacementTokens(self, stack) -> dict:
        result = {}
        for key in stack.getAllKeys():
            result[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        result["print_bed_temperature"] = result[
            "material_bed_temperature"]  # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["time"] = time.strftime("%H:%M:%S")  #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
                         "Sat"][int(time.strftime("%w"))]

        for extruder_stack in ExtruderManager.getInstance(
        ).getMachineExtruders(
                Application.getInstance().getGlobalContainerStack().getId()):
            num = extruder_stack.getMetaDataEntry("position")
            for key in extruder_stack.getAllKeys():
                if extruder_stack.getProperty(
                        key, "settable_per_extruder") == False:
                    continue
                if key in [
                        "material_soften_temperature",
                        "material_wipe_temperature",
                        "material_probe_temperature",
                        "material_print_temperature"
                ]:
                    result["%s_%s" % (key, num)] = extruder_stack.getProperty(
                        key, "value")

        initial_extruder_stack = Application.getInstance().getExtruderManager(
        ).getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty(
            "extruder_nr", "value")
        result["initial_extruder_nr"] = initial_extruder_nr

        return result
Beispiel #59
0
    def _buildReplacementTokens(self, stack) -> dict:
        default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
        result = {}
        for key in stack.getAllKeys():
            setting_type = stack.definition.getProperty(key, "type")
            value = stack.getProperty(key, "value")
            if setting_type == "extruder" and value == -1:
                # replace with the default value
                value = default_extruder_position
            result[key] = value
            Job.yieldThread()

        result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
        result["print_temperature"] = result["material_print_temperature"]
        result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
        result["date"] = time.strftime("%d-%m-%Y")
        result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]

        initial_extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0]
        initial_extruder_nr = initial_extruder_stack.getProperty("extruder_nr", "value")
        result["initial_extruder_nr"] = initial_extruder_nr

        return result
Beispiel #60
0
    def _buildExtruderMessage(self, stack):
        message = self._slice_message.addRepeatedMessage("extruders")
        message.id = int(stack.getMetaDataEntry("position"))

        material_instance_container = stack.findContainer({"type": "material"})

        settings = {}
        for key in stack.getAllKeys():
            settings[key] = stack.getProperty(key, "value")
            Job.yieldThread()

        settings["print_bed_temperature"] = settings[
            "material_bed_temperature"]  #Renamed settings.
        settings["print_temperature"] = settings["material_print_temperature"]
        settings["time"] = time.strftime("%H:%M:%S")  #Some extra settings.
        settings["date"] = time.strftime("%d-%m-%Y")
        settings["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
                           "Sat"][int(time.strftime("%w"))]

        for key, value in settings.items():
            # Do not send settings that are not settable_per_extruder.
            if not stack.getProperty(key, "settable_per_extruder"):
                continue
            setting = message.getMessage("settings").addRepeatedMessage(
                "settings")
            setting.name = key
            if key == "material_guid" and material_instance_container:
                # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it.
                setting.value = str(
                    material_instance_container.getMetaDataEntry(
                        "GUID", "")).encode("utf-8")
            elif key == "machine_extruder_start_code" or key == "machine_extruder_end_code":
                setting.value = self._expandGcodeTokens(key, value, settings)
            else:
                setting.value = str(stack.getProperty(key,
                                                      "value")).encode("utf-8")
            Job.yieldThread()