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()
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()
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 _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()
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)
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
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()
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()
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()
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()
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()
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()
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)
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()
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()
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
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())
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()
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
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()
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})
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)
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})
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)
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)
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()
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
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()
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 })
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()
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()
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
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()
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
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()
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()
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()
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()
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
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})
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()
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()
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
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()
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()
def test_getSetError(): job = Job() exception = Exception("Some Error :(") job.setError(exception) assert job.getError() == exception assert job.hasError()
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()
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
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
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()
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)
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()
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
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
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()