def setExtruderForSelection(self, extruder_id: str) -> None: operation = GroupedOperation() nodes_to_change = [] for node in Selection.getAllSelectedObjects(): # Do not change any nodes that already have the right extruder set. if node.callDecoration("getActiveExtruder") == extruder_id: continue # If the node is a group, apply the active extruder to all children of the group. if node.callDecoration("isGroup"): for grouped_node in BreadthFirstIterator(node): if grouped_node.callDecoration("getActiveExtruder") == extruder_id: continue if grouped_node.callDecoration("isGroup"): continue nodes_to_change.append(grouped_node) continue nodes_to_change.append(node) if not nodes_to_change: # If there are no changes to make, we still need to reset the selected extruders. # This is a workaround for checked menu items being deselected while still being # selected. ExtruderManager.getInstance().resetSelectedObjectExtruders() return for node in nodes_to_change: operation.addOperation(SetObjectExtruderOperation(node, extruder_id)) operation.push()
def _onStackChanged(self): if self._global_container_stack: self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged) extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) for extruder in extruders: extruder.propertyChanged.disconnect(self._onSettingPropertyChanged) self._global_container_stack = Application.getInstance().getGlobalContainerStack() if self._global_container_stack: self._global_container_stack.propertyChanged.connect(self._onSettingPropertyChanged) extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) for extruder in extruders: extruder.propertyChanged.connect(self._onSettingPropertyChanged) self._width = self._global_container_stack.getProperty("machine_width", "value") machine_height = self._global_container_stack.getProperty("machine_height", "value") if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height) if self._height < machine_height: self._build_volume_message.show() else: self._build_volume_message.hide() else: self._height = self._global_container_stack.getProperty("machine_height", "value") self._build_volume_message.hide() self._depth = self._global_container_stack.getProperty("machine_depth", "value") self._shape = self._global_container_stack.getProperty("machine_shape", "value") self._updateDisallowedAreas() self._updateRaftThickness() self.rebuild()
def __init__(self, parent = None): super().__init__(parent) self._width = 0 self._height = 0 self._depth = 0 self._shader = None self._grid_mesh = None self._grid_shader = None self._disallowed_areas = [] self._disallowed_area_mesh = None self._prime_tower_area = None self._prime_tower_area_mesh = None self.setCalculateBoundingBox(False) self._volume_aabb = None self._raft_thickness = 0.0 self._adhesion_type = None self._platform = Platform(self) self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged) self._onGlobalContainerStackChanged() self._active_extruder_stack = None ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged) self._onActiveExtruderStackChanged() self._has_errors = False
def _getSettingFromAllExtruders(self, setting_key, property = "value"): all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, property) all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type") for i in range(len(all_values)): if not all_values[i] and (all_types[i] == "int" or all_types[i] == "float"): all_values[i] = 0 return all_values
def _onGlobalContainerChanged(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 # Ensure that all extruder data is reset if not self._multi_extrusion: default_stack_id = global_container_stack.getId() else: default_stack = ExtruderManager.getInstance().getExtruderStack(0) if default_stack: default_stack_id = default_stack.getId() else: default_stack_id = global_container_stack.getId() root_node = Application.getInstance().getController().getScene().getRoot() for node in DepthFirstIterator(root_node): new_stack_id = default_stack_id # Get position of old extruder stack for this node old_extruder_pos = node.callDecoration("getActiveExtruderPosition") if old_extruder_pos is not None: # Fetch current (new) extruder stack at position new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos) if new_stack: new_stack_id = new_stack.getId() node.callDecoration("setActiveExtruder", new_stack_id) self._updateEnabled()
def _getEdgeDisallowedSize(self): if not self._global_container_stack: return 0 container_stack = self._global_container_stack # If we are printing one at a time, we need to add the bed adhesion size to the disallowed areas of the objects if container_stack.getProperty("print_sequence", "value") == "one_at_a_time": return 0.1 # Return a very small value, so we do draw disallowed area's near the edges. adhesion_type = container_stack.getProperty("adhesion_type", "value") if adhesion_type == "skirt": skirt_distance = self._getSettingFromAdhesionExtruder("skirt_gap") skirt_line_count = self._getSettingFromAdhesionExtruder("skirt_line_count") bed_adhesion_size = skirt_distance + (skirt_line_count * self._getSettingFromAdhesionExtruder("skirt_brim_line_width")) if len(ExtruderManager.getInstance().getUsedExtruderStacks()) > 1: adhesion_extruder_nr = int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value")) extruder_values = ExtruderManager.getInstance().getAllExtruderValues("skirt_brim_line_width") del extruder_values[adhesion_extruder_nr] # Remove the value of the adhesion extruder nr. for value in extruder_values: bed_adhesion_size += value elif adhesion_type == "brim": bed_adhesion_size = self._getSettingFromAdhesionExtruder("brim_line_count") * self._getSettingFromAdhesionExtruder("skirt_brim_line_width") if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: adhesion_extruder_nr = int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value")) extruder_values = ExtruderManager.getInstance().getAllExtruderValues("skirt_brim_line_width") del extruder_values[adhesion_extruder_nr] # Remove the value of the adhesion extruder nr. for value in extruder_values: bed_adhesion_size += value elif adhesion_type == "raft": bed_adhesion_size = self._getSettingFromAdhesionExtruder("raft_margin") elif adhesion_type == "none": bed_adhesion_size = 0 else: raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?") support_expansion = 0 if self._getSettingFromSupportInfillExtruder("support_offset") and self._global_container_stack.getProperty("support_enable", "value"): support_expansion += self._getSettingFromSupportInfillExtruder("support_offset") farthest_shield_distance = 0 if container_stack.getProperty("draft_shield_enabled", "value"): farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value")) if container_stack.getProperty("ooze_shield_enabled", "value"): farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("ooze_shield_dist", "value")) move_from_wall_radius = 0 # Moves that start from outer wall. move_from_wall_radius = max(move_from_wall_radius, max(self._getSettingFromAllExtruders("infill_wipe_dist"))) used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks() avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts","value") for stack in used_extruders] travel_avoid_distance_per_extruder = [stack.getProperty("travel_avoid_distance", "value") for stack in used_extruders] for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): #For each extruder (or just global). if avoid_other_parts_enabled: move_from_wall_radius = max(move_from_wall_radius, avoid_distance) # Now combine our different pieces of data to get the final border size. # Support expansion is added to the bed adhesion, since the bed adhesion goes around support. # Support expansion is added to farthest shield distance, since the shields go around support. border_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size) return border_size
def __init__(self, parent = None): super().__init__(parent) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._global_container_stack = None self._settings_with_inheritance_warning = [] self._active_container_stack = None self._onGlobalContainerChanged() ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged()
def setVisible(self, visible): if not self._node: return if not self._stack: self._node.addDecorator(SettingOverrideDecorator()) self._stack = self._node.callDecoration("getStack") settings = self._stack.getTop() all_instances = settings.findInstances() visibility_changed = False # Flag to check if at the end the signal needs to be emitted # Remove all instances that are not in visibility list for instance in all_instances: if instance.definition.key not in visible: settings.removeInstance(instance.definition.key) visibility_changed = True # Add all instances that are not added, but are in visibility list for item in visible: if not settings.getInstance(item): # Setting was not added already. definition = self._stack.getSettingDefinition(item) if definition: new_instance = SettingInstance(definition, settings) stack_nr = -1 stack = None # Check from what stack we should copy the raw property of the setting from. if self._stack.getProperty("machine_extruder_count", "value") > 1: if definition.limit_to_extruder != "-1": # A limit to extruder function was set and it's a multi extrusion machine. Check what stack we do need to use. stack_nr = str(int(round(float(self._stack.getProperty(item, "limit_to_extruder"))))) # Check if the found stack_number is in the extruder list of extruders. if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value") is not None: stack_nr = -1 # Use the found stack number to get the right stack to copy the value from. if stack_nr in ExtruderManager.getInstance().extruderIds: stack = ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0] else: stack = self._stack # Use the raw property to set the value (so the inheritance doesn't break) if stack is not None: new_instance.setProperty("value", stack.getRawProperty(item, "value")) else: new_instance.setProperty("value", None) new_instance.resetState() # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) visibility_changed = True else: Logger.log("w", "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition", item) if visibility_changed: self.visibilityChanged.emit()
def setVisible(self, visible): if not self._node: return if not self._stack: self._node.addDecorator(SettingOverrideDecorator()) self._stack = self._node.callDecoration("getStack") settings = self._stack.getTop() all_instances = settings.findInstances() visibility_changed = False # Flag to check if at the end the signal needs to be emitted # Remove all instances that are not in visibility list for instance in all_instances: if instance.definition.key not in visible: settings.removeInstance(instance.definition.key) visibility_changed = True # Add all instances that are not added, but are in visibility list for item in visible: if not settings.getInstance(item): definition = self._stack.getSettingDefinition(item) if definition: new_instance = SettingInstance(definition, settings) stack_nr = -1 if definition.limit_to_extruder and self._stack.getProperty("machine_extruder_count", "value") > 1: # Obtain the value from the correct container stack. Only once, upon adding the setting. stack_nr = str( int(round(float(self._stack.getProperty(item, "limit_to_extruder")))) ) # Stack to get the setting from. Round it and remove the fractional part. if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty( "extruder_nr", "value" ): # Property not defined, but we have an extruder number. stack_nr = str(int(round(float(self._stack.getProperty("extruder_nr", "value"))))) if ( stack_nr in ExtruderManager.getInstance().extruderIds ): # We have either a limit_to_extruder or an extruder_nr. stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks( id=ExtruderManager.getInstance().extruderIds[stack_nr] )[0] else: stack = UM.Application.getInstance().getGlobalContainerStack() new_instance.setProperty("value", stack.getRawProperty(item, "value")) new_instance.resetState() # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) visibility_changed = True else: Logger.log( "w", "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition", item, ) if visibility_changed: self.visibilityChanged.emit()
def _onActiveExtruderChanged(self): if self._global_container_stack: # Connect all extruders of the active machine. This might cause a few connects that have already happend, # but that shouldn't cause issues as only new / unique connections are added. extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) if extruders: for extruder in extruders: extruder.propertyChanged.connect(self._onSettingChanged) if self._active_extruder_stack: self._active_extruder_stack.containersChanged.disconnect(self._onChanged) self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack() if self._active_extruder_stack: self._active_extruder_stack.containersChanged.connect(self._onChanged)
def __init__(self, parent = None): super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings")) self._qml_url = "MachineSettingsAction.qml" self._global_container_stack = None self._container_index = 0 self._extruder_container_index = 0 self._container_registry = ContainerRegistry.getInstance() self._container_registry.containerAdded.connect(self._onContainerAdded) self._container_registry.containerRemoved.connect(self._onContainerRemoved) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged) self._backend = Application.getInstance().getBackend()
def __init__(self, parent = None): super().__init__(parent) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._global_container_stack = None self._settings_with_inheritance_warning = [] self._active_container_stack = None self._onGlobalContainerChanged() ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() self._update_timer = QTimer() self._update_timer.setInterval(500) self._update_timer.setSingleShot(True) self._update_timer.timeout.connect(self._update)
def _onGlobalContainerChanged(self) -> None: if self._global_stack: try: self._global_stack.propertyChanged.disconnect(self._onPropertyChanged) except TypeError: pass for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.propertyChanged.disconnect(self._onPropertyChanged) self._global_stack = Application.getInstance().getGlobalContainerStack() if self._global_stack: self._global_stack.propertyChanged.connect(self._onPropertyChanged) for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.propertyChanged.connect(self._onPropertyChanged) self._onPropertyChanged("support_angle", "value") # Force an re-evaluation
def _serialiseSettings(self, stack): prefix = ";SETTING_" + str(GCodeWriter.version) + " " # The prefix to put before each line. prefix_length = len(prefix) container_with_profile = stack.findContainer({"type": "quality"}) flat_global_container = self._createFlattenedContainerInstance(stack.getTop(),container_with_profile) serialized = flat_global_container.serialize() data = {"global_quality": serialized} for extruder in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): extruder_quality = extruder.findContainer({"type": "quality"}) flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality) extruder_serialized = flat_extruder_quality.serialize() data.setdefault("extruder_quality", []).append(extruder_serialized) json_string = json.dumps(data) # Escape characters that have a special meaning in g-code comments. pattern = re.compile("|".join(GCodeWriter.escape_characters.keys())) # Perform the replacement with a regular expression. escaped_string = pattern.sub(lambda m: GCodeWriter.escape_characters[re.escape(m.group(0))], json_string) # Introduce line breaks so that each comment is no longer than 80 characters. Prepend each line with the prefix. result = "" # Lines have 80 characters, so the payload of each line is 80 - prefix. for pos in range(0, len(escaped_string), 80 - prefix_length): result += prefix + escaped_string[pos : pos + 80 - prefix_length] + "\n" return result
def _extruderOffsets(self) -> Dict[int, List[float]]: result = {} for extruder in ExtruderManager.getInstance().getActiveExtruderStacks(): result[int(extruder.getMetaData().get("position", "0"))] = [ extruder.getProperty("machine_nozzle_offset_x", "value"), extruder.getProperty("machine_nozzle_offset_y", "value")] return result
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 _computeDisallowedAreasPrinted(self, used_extruders): result = {} for extruder in used_extruders: result[extruder.getId()] = [] #Currently, the only normally printed object is the prime tower. if ExtruderManager.getInstance().getResolveOrValue("prime_tower_enable") == True: prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value") machine_width = self._global_container_stack.getProperty("machine_width", "value") machine_depth = self._global_container_stack.getProperty("machine_depth", "value") prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value") prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value") if not self._global_container_stack.getProperty("machine_center_is_zero", "value"): prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left. prime_tower_y = prime_tower_y + machine_depth / 2 prime_tower_area = Polygon([ [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size], [prime_tower_x, prime_tower_y - prime_tower_size], [prime_tower_x, prime_tower_y], [prime_tower_x - prime_tower_size, prime_tower_y], ]) prime_tower_area = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(0)) for extruder in used_extruders: result[extruder.getId()].append(prime_tower_area) #The prime tower location is the same for each extruder, regardless of offset. return result
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if not global_container_stack: return {}, {} # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = self._getOrderedExtruderStacksList() # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and qc.getMetaDataEntry("extruder") is not None and (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())} return filtered_quality_changes, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if not global_container_stack: return [] # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks # Fetch the list of useable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set] return quality_list + filtered_quality_changes
def _checkForWarnings(self): warnings = [] print_information = CuraApplication.getInstance().getPrintInformation() if not print_information.materialLengths: Logger.log("w", "There is no material length information. Unable to check for warnings.") return warnings extruder_manager = ExtruderManager.getInstance() for index, extruder in enumerate(self.activePrinter.extruders): if index < len(print_information.materialLengths) and print_information.materialLengths[index] != 0: # The extruder is by this print. # TODO: material length check # Check if the right Printcore is active. variant = extruder_manager.getExtruderStack(index).findContainer({"type": "variant"}) if variant: if variant.getName() != extruder.hotendID: warnings.append(i18n_catalog.i18nc("@label", "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}".format(cura_printcore_name = variant.getName(), remote_printcore_name = extruder.hotendID, extruder_id = index + 1))) else: Logger.log("w", "Unable to find variant.") # Check if the right material is loaded. local_material = extruder_manager.getExtruderStack(index).findContainer({"type": "material"}) if local_material: if extruder.activeMaterial.guid != local_material.getMetaDataEntry("GUID"): Logger.log("w", "Extruder %s has a different material (%s) as Cura (%s)", index + 1, extruder.activeMaterial.guid, local_material.getMetaDataEntry("GUID")) warnings.append(i18n_catalog.i18nc("@label", "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}").format(local_material.getName(), extruder.activeMaterial.name, index + 1)) else: Logger.log("w", "Unable to find material.") return warnings
def extruder_manager(application, container_registry) -> ExtruderManager: if ExtruderManager.getInstance() is not None: # Reset the data ExtruderManager._ExtruderManager__instance = None with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)): with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)): manager = ExtruderManager() return manager
def __init__(self): super().__init__() self._stack = PerObjectContainerStack(stack_id = id(self)) self._stack.setDirty(False) # This stack does not need to be saved. self._stack.addContainer(InstanceContainer(container_id = "SettingOverrideInstanceContainer")) if ExtruderManager.getInstance().extruderCount > 1: self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() else: self._extruder_stack = None self._stack.propertyChanged.connect(self._onSettingChanged) ContainerRegistry.getInstance().addContainer(self._stack) Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack) self.activeExtruderChanged.connect(self._updateNextStack) self._updateNextStack()
def _serialiseSettings(self, stack): prefix = ";SETTING_" + str(GCodeWriter.version) + " " # The prefix to put before each line. prefix_length = len(prefix) container_with_profile = stack.qualityChanges if not container_with_profile: Logger.log("e", "No valid quality profile found, not writing settings to GCode!") return "" flat_global_container = self._createFlattenedContainerInstance(stack.getTop(), container_with_profile) # If the quality changes is not set, we need to set type manually if flat_global_container.getMetaDataEntry("type", None) is None: flat_global_container.addMetaDataEntry("type", "quality_changes") # Ensure that quality_type is set. (Can happen if we have empty quality changes). if flat_global_container.getMetaDataEntry("quality_type", None) is None: flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal")) serialized = flat_global_container.serialize() data = {"global_quality": serialized} for extruder in sorted(ExtruderManager.getInstance().getMachineExtruders(stack.getId()), key = lambda k: k.getMetaDataEntry("position")): extruder_quality = extruder.qualityChanges if not extruder_quality: Logger.log("w", "No extruder quality profile found, not writing quality for extruder %s to file!", extruder.getId()) continue flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality) # If the quality changes is not set, we need to set type manually if flat_extruder_quality.getMetaDataEntry("type", None) is None: flat_extruder_quality.addMetaDataEntry("type", "quality_changes") # Ensure that extruder is set. (Can happen if we have empty quality changes). if flat_extruder_quality.getMetaDataEntry("extruder", None) is None: flat_extruder_quality.addMetaDataEntry("extruder", extruder.getBottom().getId()) # Ensure that quality_type is set. (Can happen if we have empty quality changes). if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None: flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal")) extruder_serialized = flat_extruder_quality.serialize() data.setdefault("extruder_quality", []).append(extruder_serialized) json_string = json.dumps(data) # Escape characters that have a special meaning in g-code comments. pattern = re.compile("|".join(GCodeWriter.escape_characters.keys())) # Perform the replacement with a regular expression. escaped_string = pattern.sub(lambda m: GCodeWriter.escape_characters[re.escape(m.group(0))], json_string) # Introduce line breaks so that each comment is no longer than 80 characters. Prepend each line with the prefix. result = "" # Lines have 80 characters, so the payload of each line is 80 - prefix. for pos in range(0, len(escaped_string), 80 - prefix_length): result += prefix + escaped_string[pos : pos + 80 - prefix_length] + "\n" return result
def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode): mesh_writer = Application.getInstance().getMeshFileHandler().getWriter("3MFWriter") if not mesh_writer: # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace return False # Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it). mesh_writer.setStoreArchive(True) mesh_writer.write(stream, nodes, mode) archive = mesh_writer.getArchive() if archive is None: # This happens if there was no mesh data to write. archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED) global_container_stack = Application.getInstance().getGlobalContainerStack() # Add global container stack data to the archive. self._writeContainerToArchive(global_container_stack, archive) # Also write all containers in the stack to the file for container in global_container_stack.getContainers(): self._writeContainerToArchive(container, archive) # Check if the machine has extruders and save all that data as well. for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()): self._writeContainerToArchive(extruder_stack, archive) for container in extruder_stack.getContainers(): self._writeContainerToArchive(container, archive) # Write preferences to archive original_preferences = Preferences.getInstance() #Copy only the preferences that we use to the workspace. temp_preferences = Preferences() for preference in {"general/visible_settings", "cura/active_mode", "cura/categories_expanded"}: temp_preferences.addPreference(preference, None) temp_preferences.setValue(preference, original_preferences.getValue(preference)) preferences_string = StringIO() temp_preferences.writeToFile(preferences_string) preferences_file = zipfile.ZipInfo("Cura/preferences.cfg") archive.writestr(preferences_file, preferences_string.getvalue()) # Save Cura version version_file = zipfile.ZipInfo("Cura/version.ini") version_config_parser = configparser.ConfigParser() version_config_parser.add_section("versions") version_config_parser.set("versions", "cura_version", Application.getInstance().getVersion()) version_config_parser.set("versions", "build_type", Application.getInstance().getBuildType()) version_config_parser.set("versions", "is_debug_mode", str(Application.getInstance().getIsDebugMode())) version_file_string = StringIO() version_config_parser.write(version_file_string) archive.writestr(version_file, version_file_string.getvalue()) # Close the archive & reset states. archive.close() mesh_writer.setStoreArchive(False) return True
def __init__(self, width, height): super().__init__("layerview", width, height) self._layer_shader = None self._tool_handle_shader = None self._gl = OpenGL.getInstance().getBindingsObject() self._scene = Application.getInstance().getController().getScene() self._extruder_manager = ExtruderManager.getInstance() self._layer_view = None
def _cacheAllExtruderSettings(self): global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) # NB: keys must be strings for the string formatter self._all_extruders_settings = { "-1": self._buildReplacementTokens(global_stack) } for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_nr = extruder_stack.getProperty("extruder_nr", "value") self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
def _getOrderedExtruderStacksList() -> List["ExtruderStack"]: extruder_manager = ExtruderManager.getInstance() extruder_stacks = extruder_manager.getActiveExtruderStacks() active_extruder = extruder_manager.getActiveExtruderStack() if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks return extruder_stacks
def _onActiveExtruderStackChanged(self): extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() if not self._global_container_stack or not extruder_container_stack: return # Make sure there is a definition_changes container to store the machine settings definition_changes_container = extruder_container_stack.definitionChanges if definition_changes_container == self._empty_container: definition_changes_container = CuraStackBuilder.createDefinitionChangesContainer( extruder_container_stack, extruder_container_stack.getId() + "_settings")
def _onGlobalStackChanged(self): if self._global_stack: self._global_stack.propertyChanged.disconnect(self._onSettingValueChanged) self._global_stack.containersChanged.disconnect(self._onChanged) extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_stack.getId()) for extruder in extruders: extruder.propertyChanged.disconnect(self._onSettingValueChanged) self._global_stack = Application.getInstance().getGlobalContainerStack() if self._global_stack: self._global_stack.propertyChanged.connect(self._onSettingValueChanged) self._global_stack.containersChanged.connect(self._onChanged) extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_stack.getId()) for extruder in extruders: extruder.propertyChanged.connect(self._onSettingValueChanged) self._onChanged()
def execute(self, data): """ Entry point of the plugin. data is the list of original g-code instructions, the returned string is the list of modified g-code instructions """ stretcher = Stretcher( ExtruderManager.getInstance().getActiveExtruderStack().getProperty("machine_nozzle_size", "value") , self.getSettingValueByKey("wc_stretch"), self.getSettingValueByKey("pw_stretch")) return stretcher.execute(data)
def _onGlobalStackChanged(self) -> None: if self._global_stack: self._global_stack.propertyChanged.disconnect( self._onSettingValueChanged) self._global_stack.containersChanged.disconnect(self._onChanged) extruders = ExtruderManager.getInstance().getActiveExtruderStacks() for extruder in extruders: extruder.propertyChanged.disconnect( self._onSettingValueChanged) self._global_stack = Application.getInstance().getGlobalContainerStack( ) if self._global_stack: self._global_stack.propertyChanged.connect( self._onSettingValueChanged) self._global_stack.containersChanged.connect(self._onChanged) extruders = ExtruderManager.getInstance().getActiveExtruderStacks() for extruder in extruders: extruder.propertyChanged.connect(self._onSettingValueChanged) self._onChanged()
def initialize(self) -> None: self._multi_build_plate_model = self._application.getMultiBuildPlateModel() self._application.getController().activeViewChanged.connect(self._onActiveViewChanged) if self._multi_build_plate_model: self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged) self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() # extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged) self.backendQuit.connect(self._onBackendQuit) self.backendConnected.connect(self._onBackendConnected) # When a tool operation is in progress, don't slice. So we need to listen for tool operations. self._application.getController().toolOperationStarted.connect(self._onToolOperationStarted) self._application.getController().toolOperationStopped.connect(self._onToolOperationStopped) self._machine_error_checker = self._application.getMachineErrorChecker() self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished)
def setExtruderForSelection(self, extruder_id: str) -> None: operation = GroupedOperation() nodes_to_change = [] for node in Selection.getAllSelectedObjects(): # If the node is a group, apply the active extruder to all children of the group. if node.callDecoration("isGroup"): for grouped_node in BreadthFirstIterator( node ): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if grouped_node.callDecoration( "getActiveExtruder") == extruder_id: continue if grouped_node.callDecoration("isGroup"): continue nodes_to_change.append(grouped_node) continue # Do not change any nodes that already have the right extruder set. if node.callDecoration("getActiveExtruder") == extruder_id: continue nodes_to_change.append(node) if not nodes_to_change: # If there are no changes to make, we still need to reset the selected extruders. # This is a workaround for checked menu items being deselected while still being # selected. ExtruderManager.getInstance().resetSelectedObjectExtruders() return for node in nodes_to_change: operation.addOperation( SetObjectExtruderOperation(node, extruder_id)) operation.push()
def createQualityChanges(self, base_name): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False active_quality_name = self._machine_manager.activeQualityName if active_quality_name == "": Logger.log( "w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return False self._machine_manager.blurSettings.emit() if base_name is None or base_name == "": base_name = active_quality_name unique_name = self._container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. for stack in ExtruderManager.getInstance( ).getActiveGlobalAndExtruderStacks(): user_container = stack.getTop() quality_container = stack.quality quality_changes_container = stack.qualityChanges if not quality_container or not quality_changes_container: Logger.log( "w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue extruder_id = None if stack is global_stack else QualityManager.getInstance( ).getParentMachineDefinition(stack.getBottom()).getId() new_changes = self._createQualityChanges( quality_container, unique_name, Application.getInstance().getGlobalContainerStack().getBottom( ), extruder_id) self._performMerge(new_changes, quality_changes_container, clear_settings=False) self._performMerge(new_changes, user_container) self._container_registry.addContainer(new_changes) stack.replaceContainer( stack.getContainerIndex(quality_changes_container), new_changes) self._machine_manager.activeQualityChanged.emit() return True
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance( ).getGlobalContainerStack() if not global_container_stack: return [] # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() machine_definition = quality_manager.getParentMachineDefinition( global_container_stack.getBottom()) quality_changes_list = quality_manager.findAllQualityChangesForMachine( machine_definition) # Detecting if the machine has multiple extrusion multiple_extrusion = False # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() if active_extruder in extruder_stacks: multiple_extrusion = True extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks # Fetch the list of useable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders( global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set( [x.getMetaDataEntry("quality_type") for x in quality_list]) if multiple_extrusion: # If the printer has multiple extruders then quality changes related to the current extruder are kept filtered_quality_changes = [ qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and qc.getMetaDataEntry( "extruder") == active_extruder.definition.getId() ] else: # If not, the quality changes of the global stack are selected filtered_quality_changes = [ qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set ] return quality_list + filtered_quality_changes
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance( ).getGlobalContainerStack() if global_container_stack is None: return [] global_stack_definition = global_container_stack.getBottom() # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() materials = [global_container_stack.material] if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks materials = [extruder.material for extruder in extruder_stacks] # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. result = QualityManager.getInstance( ).findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # The usable quality types are set quality_type_set = set( [x.getMetaDataEntry("quality_type") for x in result]) # Fetch all qualities available for this machine and the materials selected in extruders all_qualities = QualityManager.getInstance( ).findAllQualitiesForMachineAndMaterials(global_stack_definition, materials) # If in the all qualities there is some of them that are not available due to incompatibility with materials # we also add it so that they will appear in the slide quality bar. However in recomputeItems will be marked as # not available so they will be shown in gray for quality in all_qualities: if quality.getMetaDataEntry( "quality_type") not in quality_type_set: result.append(quality) # if still profiles are found, add a single empty_quality ("Not supported") instance to the drop down list if len(result) == 0: # If not qualities are found we dynamically create a not supported container for this machine + material combination not_supported_container = ContainerRegistry.getInstance( ).findContainers(id="empty_quality")[0] result.append(not_supported_container) return result
def _onActiveExtruderChanged(self): new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack() if not new_active_stack: self._active_container_stack = None return if new_active_stack != self._active_container_stack: # Check if changed if self._active_container_stack: # Disconnect signal from old container (if any) self._active_container_stack.propertyChanged.disconnect(self._onPropertyChanged) self._active_container_stack.containersChanged.disconnect(self._onContainersChanged) self._active_container_stack = new_active_stack self._active_container_stack.propertyChanged.connect(self._onPropertyChanged) self._active_container_stack.containersChanged.connect(self._onContainersChanged) self._update() # Ensure that the settings_with_inheritance_warning list is populated.
def _onActiveExtruderStackChanged(self): extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() if not self._global_container_stack or not extruder_container_stack: return # Make sure there is a definition_changes container to store the machine settings definition_changes_container = extruder_container_stack.findContainer({"type": "definition_changes"}) if not definition_changes_container: definition_changes_container = self._createDefinitionChangesContainer(extruder_container_stack, extruder_container_stack.getId() + "_settings") # Notify the UI in which container to store the machine settings data container_index = extruder_container_stack.getContainerIndex(definition_changes_container) if container_index != self._extruder_container_index: self._extruder_container_index = container_index self.extruderContainerIndexChanged.emit()
def duplicateQualityOrQualityChanges(self, quality_name, base_name): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" machine_definition = global_stack.getBottom() active_stacks = ExtruderManager.getInstance( ).getActiveGlobalAndExtruderStacks() material_containers = [stack.material for stack in active_stacks] result = self._duplicateQualityOrQualityChangesForMachineType( quality_name, base_name, QualityManager.getInstance().getParentMachineDefinition( machine_definition), material_containers) return result[0].getName() if result else ""
def _getFilteredContainersForStack(self, machine_definition: "DefinitionContainerInterface" = None, material_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs): # Fill in any default values. if machine_definition is None: machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() quality_definition_id = machine_definition.getMetaDataEntry("quality_definition") if quality_definition_id is not None: machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = quality_definition_id)[0] if not material_metadata: active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() if active_stacks: material_metadata = [stack.material.getMetaData() for stack in active_stacks] criteria = kwargs filter_by_material = False machine_definition = self.getParentMachineDefinition(machine_definition) criteria["definition"] = machine_definition.getId() found_containers_with_machine_definition = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria) whole_machine_definition = self.getWholeMachineDefinition(machine_definition) if whole_machine_definition.getMetaDataEntry("has_machine_quality"): definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId()) criteria["definition"] = definition_id filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials") # only fall back to "fdmprinter" when there is no container for this machine elif not found_containers_with_machine_definition: criteria["definition"] = "fdmprinter" # Stick the material IDs in a set material_ids = set() for material_instance in material_metadata: if material_instance is not None: # Add the parent material too. for basic_material in self._getBasicMaterialMetadatas(material_instance): material_ids.add(basic_material["id"]) material_ids.add(material_instance["id"]) containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) result = [] for container in containers: # If the machine specifies we should filter by material, exclude containers that do not match any active material. if filter_by_material and container.getMetaDataEntry("material") not in material_ids and "global_quality" not in kwargs: continue result.append(container) return result
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() # Remove support_enable for belt-printers if self._scene.getRoot().callDecoration("getGantryAngle"): for key in ["support_enable", "support_mesh_drop_down"]: try: changed_setting_keys.remove(key) except KeyError: pass # 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 _updateExtraZClearance(self) -> None: extra_z = 0.0 extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()) use_extruders = False for extruder in extruders: if extruder.getProperty("retraction_hop_enabled", "value"): retraction_hop = extruder.getProperty("retraction_hop", "value") if extra_z is None or retraction_hop > extra_z: extra_z = retraction_hop use_extruders = True if not use_extruders: # If no extruders, take global value. if self._global_container_stack.getProperty("retraction_hop_enabled", "value"): extra_z = self._global_container_stack.getProperty("retraction_hop", "value") if extra_z != self._extra_z_clearance: self._extra_z_clearance = extra_z
def __init__(self): super().__init__() self._stack = PerObjectContainerStack(stack_id = "per_object_stack_" + str(id(self))) self._stack.setDirty(False) # This stack does not need to be saved. self._stack.addContainer(InstanceContainer(container_id = "SettingOverrideInstanceContainer")) self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() self._is_non_printing_mesh = False self._stack.propertyChanged.connect(self._onSettingChanged) Application.getInstance().getContainerRegistry().addContainer(self._stack) Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack) self.activeExtruderChanged.connect(self._updateNextStack) self._updateNextStack()
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance( ).getGlobalContainerStack() if not global_container_stack: return {}, {} # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() machine_definition = quality_manager.getParentMachineDefinition( global_container_stack.definition) quality_changes_list = quality_manager.findAllQualityChangesForMachine( machine_definition) extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = self._getOrderedExtruderStacksList() # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders( global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set( [x.getMetaDataEntry("quality_type") for x in quality_list]) # Also show custom profiles based on "Not Supported" quality profile quality_type_set.add( self._empty_quality.getMetaDataEntry("quality_type")) filtered_quality_changes = { qc.getId(): qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and (( qc.getMetaDataEntry("extruder") == active_extruder.definition. getMetaDataEntry("quality_definition") or qc.getMetaDataEntry( "extruder") == active_extruder.definition.getId() ) if qc.getMetaDataEntry("extruder") is not None else True) and ( (qc.getMetaDataEntry("material") == active_extruder.material.id ) if machine_definition. getMetaDataEntry("has_machine_materials") else True) } result = filtered_quality_changes for q in quality_list: if q.getId() != "empty_quality": result[q.getId()] = q return result, { } #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
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 __init__(self, width, height): super().__init__("simulationview", width, height) self._layer_shader = None self._layer_shadow_shader = None self._current_shader = None # This shader will be the shadow or the normal depending if the user wants to see the paths or the layers self._tool_handle_shader = None self._nozzle_shader = None self._old_current_layer = 0 self._old_current_path = 0 self._switching_layers = True # It tracks when the user is moving the layers' slider self._gl = OpenGL.getInstance().getBindingsObject() self._scene = Application.getInstance().getController().getScene() self._extruder_manager = ExtruderManager.getInstance() self._layer_view = None self._compatibility_mode = None
def _getSettingProperty(self, setting_key, property="value"): multi_extrusion = self._global_stack.getProperty( "machine_extruder_count", "value") > 1 if not multi_extrusion: return self._global_stack.getProperty(setting_key, property) extruder_index = self._global_stack.getProperty( setting_key, "limit_to_extruder") if extruder_index == "-1": # If extruder index is -1 use global instead return self._global_stack.getProperty(setting_key, property) extruder_stack_id = ExtruderManager.getInstance().extruderIds[str( extruder_index)] stack = UM.Settings.ContainerRegistry.getInstance( ).findContainerStacks(id=extruder_stack_id)[0] return stack.getProperty(setting_key, property)
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return [] # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks # Fetch the list of useable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. return QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)
def _getFilteredContainersForStack(self, machine_definition=None, material_containers=None, **kwargs): # Fill in any default values. if machine_definition is None: machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() quality_definition_id = machine_definition.getMetaDataEntry("quality_definition") if quality_definition_id is not None: machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id=quality_definition_id)[0] if material_containers is None: active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() material_containers = [stack.findContainer(type="material") for stack in active_stacks] criteria = kwargs filter_by_material = False machine_definition = self.getParentMachineDefinition(machine_definition) whole_machine_definition = self.getWholeMachineDefinition(machine_definition) if whole_machine_definition.getMetaDataEntry("has_machine_quality"): definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId()) criteria["definition"] = definition_id filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials") else: criteria["definition"] = "fdmprinter" # Stick the material IDs in a set if material_containers is None or len(material_containers) == 0: filter_by_material = False else: material_ids = set() for material_instance in material_containers: if material_instance is not None: # Add the parent material too. for basic_material in self._getBasicMaterials(material_instance): material_ids.add(basic_material.getId()) material_ids.add(material_instance.getId()) containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) result = [] for container in containers: # If the machine specifies we should filter by material, exclude containers that do not match any active material. if filter_by_material and container.getMetaDataEntry("material") not in material_ids and not "global_quality" in kwargs: continue result.append(container) 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 _getSettingProperty(self, setting_key, prop = "value"): per_mesh_stack = self._node.callDecoration("getStack") if per_mesh_stack: return per_mesh_stack.getProperty(setting_key, prop) extruder_index = self._global_stack.getProperty(setting_key, "limit_to_extruder") if extruder_index == "-1": # No limit_to_extruder extruder_stack_id = self._node.callDecoration("getActiveExtruder") if not extruder_stack_id: # Decoration doesn't exist extruder_stack_id = ExtruderManager.getInstance().extruderIds["0"] extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] return extruder_stack.getProperty(setting_key, prop) else: # Limit_to_extruder is set. The global stack handles this then return self._global_stack.getProperty(setting_key, prop)
def clearUserContainers(self) -> None: self._machine_manager.blurSettings.emit() send_emits_containers = [] # Go through global and extruder stacks and clear their topmost container (the user settings). for stack in ExtruderManager.getInstance( ).getActiveGlobalAndExtruderStacks(): container = stack.userChanges container.clear() send_emits_containers.append(container) # user changes are possibly added to make the current setup match the current enabled extruders Application.getInstance().getMachineManager().correctExtruderSettings() for container in send_emits_containers: container.sendPostponedEmits()
def _onActiveExtruderChanged(self): if self._global_container_stack: # Connect all extruders of the active machine. This might cause a few connects that have already happend, # but that shouldn't cause issues as only new / unique connections are added. extruders = list(ExtruderManager.getInstance().getMachineExtruders( self._global_container_stack.getId())) if extruders: for extruder in extruders: extruder.propertyChanged.connect(self._onSettingChanged) if self._active_extruder_stack: self._active_extruder_stack.containersChanged.disconnect( self._onChanged) self._active_extruder_stack = cura.Settings.ExtruderManager.getInstance( ).getActiveExtruderStack() if self._active_extruder_stack: self._active_extruder_stack.containersChanged.connect( self._onChanged)
def _cacheAllExtruderSettings(self): global_stack = cast( ContainerStack, CuraApplication.getInstance().getGlobalContainerStack()) # NB: keys must be strings for the string formatter self._all_extruders_settings = { "-1": self._buildReplacementTokens(global_stack) } QCoreApplication.processEvents( ) # Ensure that the GUI does not freeze. for extruder_stack in ExtruderManager.getInstance( ).getActiveExtruderStacks(): extruder_nr = extruder_stack.getProperty("extruder_nr", "value") self._all_extruders_settings[str( extruder_nr)] = self._buildReplacementTokens(extruder_stack) QCoreApplication.processEvents( ) # Ensure that the GUI does not freeze.
def getOverridesForExtruder(self, key, extruder_index): result = [] extruder_stack = ExtruderManager.getInstance().getExtruderStack(extruder_index) if not extruder_stack: Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index) return result definitions = self._global_container_stack.definition.findDefinitions(key = key) if not definitions: Logger.log("w", "Could not find definition for key [%s] (2)", key) return result for key in definitions[0].getAllKeys(): if self._settingIsOverwritingInheritance(key, extruder_stack): result.append(key) return result
def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode): mesh_writer = Application.getInstance().getMeshFileHandler().getWriter( "3MFWriter") if not mesh_writer: # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace return False # Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it). mesh_writer.setStoreArchive(True) mesh_writer.write(stream, nodes, mode) archive = mesh_writer.getArchive() if archive is None: # This happens if there was no mesh data to write. archive = zipfile.ZipFile(stream, "w", compression=zipfile.ZIP_DEFLATED) global_container_stack = Application.getInstance( ).getGlobalContainerStack() # Add global container stack data to the archive. self._writeContainerToArchive(global_container_stack, archive) # Also write all containers in the stack to the file for container in global_container_stack.getContainers(): self._writeContainerToArchive(container, archive) # Check if the machine has extruders and save all that data as well. for extruder_stack in ExtruderManager.getInstance( ).getMachineExtruders(global_container_stack.getId()): self._writeContainerToArchive(extruder_stack, archive) for container in extruder_stack.getContainers(): self._writeContainerToArchive(container, archive) # Write preferences to archive preferences_file = zipfile.ZipInfo("Cura/preferences.cfg") preferences_string = StringIO() Preferences.getInstance().writeToFile(preferences_string) archive.writestr(preferences_file, preferences_string.getvalue()) # Close the archive & reset states. archive.close() mesh_writer.setStoreArchive(False) return True
def __init__(self): super().__init__() self._stack = PerObjectContainerStack(container_id = "per_object_stack_" + str(id(self))) self._stack.setDirty(False) # This stack does not need to be saved. user_container = InstanceContainer(container_id = self._generateUniqueName()) user_container.setMetaDataEntry("type", "user") self._stack.userChanges = user_container self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() self._is_non_printing_mesh = False self._is_non_thumbnail_visible_mesh = False self._stack.propertyChanged.connect(self._onSettingChanged) Application.getInstance().getContainerRegistry().addContainer(self._stack) Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack) self.activeExtruderChanged.connect(self._updateNextStack) self._updateNextStack()
def updateQualityChanges(self): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False self._machine_manager.blurSettings.emit() for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): # Find the quality_changes container for this stack and merge the contents of the top container into it. quality_changes = stack.qualityChanges if not quality_changes or quality_changes.isReadOnly(): Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId()) continue self._performMerge(quality_changes, stack.getTop()) self._machine_manager.activeQualityChanged.emit() return True
def _onGlobalContainerChanged(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 # Ensure that all extruder data is reset if not self._multi_extrusion: default_stack_id = global_container_stack.getId() else: default_stack = ExtruderManager.getInstance().getExtruderStack(0) if default_stack: default_stack_id = default_stack.getId() else: default_stack_id = global_container_stack.getId() root_node = Application.getInstance().getController().getScene().getRoot() for node in DepthFirstIterator(root_node): node.callDecoration("setActiveExtruder", default_stack_id) self._updateEnabled()
def _fetchInstanceContainers(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if not global_container_stack: return [] # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) # Fetch the list of qualities quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, ExtruderManager.getInstance().getActiveExtruderStacks()) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set] return filtered_quality_changes