diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 6d52ce87fd..6b52c629d0 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -502,6 +502,90 @@ class ExtruderManager(QObject): def getInstanceExtruderValues(self, key): return ExtruderManager.getExtruderValues(key) + ## Updates the material container to a material that matches the material diameter set for the printer + def updateMaterialForDiameter(self, extruder_position: int): + + global_stack = Application.getInstance().getGlobalContainerStack() + if not global_stack: + return + + if not global_stack.getMetaDataEntry("has_materials", False): + return + + extruder_stack = global_stack.extruders[str(extruder_position)] + + material_diameter = extruder_stack.material.getProperty("material_diameter", "value") + if not material_diameter: + # in case of "empty" material + material_diameter = 0 + + material_approximate_diameter = str(round(material_diameter)) + machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value") + if not machine_diameter: + if extruder_stack.definition.hasProperty("material_diameter", "value"): + machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value") + else: + machine_diameter = global_stack.definition.getProperty("material_diameter", "value") + machine_approximate_diameter = str(round(machine_diameter)) + + if material_approximate_diameter != machine_approximate_diameter: + Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.") + + if global_stack.getMetaDataEntry("has_machine_materials", False): + materials_definition = global_stack.definition.getId() + has_material_variants = global_stack.getMetaDataEntry("has_variants", False) + else: + materials_definition = "fdmprinter" + has_material_variants = False + + old_material = extruder_stack.material + search_criteria = { + "type": "material", + "approximate_diameter": machine_approximate_diameter, + "material": old_material.getMetaDataEntry("material", "value"), + "brand": old_material.getMetaDataEntry("brand", "value"), + "supplier": old_material.getMetaDataEntry("supplier", "value"), + "color_name": old_material.getMetaDataEntry("color_name", "value"), + "definition": materials_definition + } + if has_material_variants: + search_criteria["variant"] = extruder_stack.variant.getId() + + container_registry = Application.getInstance().getContainerRegistry() + empty_material = container_registry.findInstanceContainers(id = "empty_material")[0] + + if old_material == empty_material: + search_criteria.pop("material", None) + search_criteria.pop("supplier", None) + search_criteria.pop("brand", None) + search_criteria.pop("definition", None) + search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material") + + materials = container_registry.findInstanceContainers(**search_criteria) + if not materials: + # Same material with new diameter is not found, search for generic version of the same material type + search_criteria.pop("supplier", None) + search_criteria.pop("brand", None) + search_criteria["color_name"] = "Generic" + materials = container_registry.findInstanceContainers(**search_criteria) + if not materials: + # Generic material with new diameter is not found, search for preferred material + search_criteria.pop("color_name", None) + search_criteria.pop("material", None) + search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material") + materials = container_registry.findInstanceContainers(**search_criteria) + if not materials: + # Preferred material with new diameter is not found, search for any material + search_criteria.pop("id", None) + materials = container_registry.findInstanceContainers(**search_criteria) + if not materials: + # Just use empty material as a final fallback + materials = [empty_material] + + Logger.log("i", "Selecting new material: %s", materials[0].getId()) + + extruder_stack.material = materials[0] + ## Get the value for a setting from a specific extruder. # # This is exposed to SettingFunction to use in value functions. diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index d6a72b72e4..204b0e2dae 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -3,6 +3,7 @@ from typing import Any, TYPE_CHECKING, Optional +from UM.Application import Application from UM.Decorators import override from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.Settings.ContainerStack import ContainerStack @@ -60,6 +61,12 @@ class ExtruderStack(CuraContainerStack): for key in keys_to_copy: + # Since material_diameter is not on the extruder definition, we need to add it here + # WARNING: this might be very dangerous and should be refactored ASAP! + definition = stack.getSettingDefinition(key) + if definition: + self.definition.addDefinition(definition) + # Only copy the value when this extruder doesn't have the value. if self.definitionChanges.hasProperty(key, "value"): continue @@ -75,6 +82,11 @@ class ExtruderStack(CuraContainerStack): self.definitionChanges.addInstance(new_instance) self.definitionChanges.setDirty(True) + # Make sure the material diameter is up to date for the extruder stack. + if key == "material_diameter": + position = self.getMetaDataEntry("position", "0") + Application.getInstance().getExtruderManager().updateMaterialForDiameter(position) + # NOTE: We cannot remove the setting from the global stack's definition changes container because for # material diameter, it needs to be applied to all extruders, but here we don't know how many extruders # a machine actually has and how many extruders has already been loaded for that machine, so we have to diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index ae1c1663dd..baa0639d3f 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -158,79 +158,4 @@ class MachineSettingsAction(MachineAction): @pyqtSlot(int) def updateMaterialForDiameter(self, extruder_position: int): # Updates the material container to a material that matches the material diameter set for the printer - if not self._global_container_stack: - return - - if not self._global_container_stack.getMetaDataEntry("has_materials", False): - return - - extruder_stack = self._global_container_stack.extruders[str(extruder_position)] - - material_diameter = extruder_stack.material.getProperty("material_diameter", "value") - if not material_diameter: - # in case of "empty" material - material_diameter = 0 - - material_approximate_diameter = str(round(material_diameter)) - machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value") - if not machine_diameter: - if extruder_stack.definition.hasProperty("material_diameter", "value"): - machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value") - else: - machine_diameter = self._global_container_stack.definition.getProperty("material_diameter", "value") - machine_approximate_diameter = str(round(machine_diameter)) - - if material_approximate_diameter != machine_approximate_diameter: - Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.") - - if self._global_container_stack.getMetaDataEntry("has_machine_materials", False): - materials_definition = self._global_container_stack.definition.getId() - has_material_variants = self._global_container_stack.getMetaDataEntry("has_variants", False) - else: - materials_definition = "fdmprinter" - has_material_variants = False - - old_material = extruder_stack.material - search_criteria = { - "type": "material", - "approximate_diameter": machine_approximate_diameter, - "material": old_material.getMetaDataEntry("material", "value"), - "brand": old_material.getMetaDataEntry("brand", "value"), - "supplier": old_material.getMetaDataEntry("supplier", "value"), - "color_name": old_material.getMetaDataEntry("color_name", "value"), - "definition": materials_definition - } - if has_material_variants: - search_criteria["variant"] = extruder_stack.variant.getId() - - if old_material == self._empty_container: - search_criteria.pop("material", None) - search_criteria.pop("supplier", None) - search_criteria.pop("brand", None) - search_criteria.pop("definition", None) - search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material") - - materials = self._container_registry.findInstanceContainers(**search_criteria) - if not materials: - # Same material with new diameter is not found, search for generic version of the same material type - search_criteria.pop("supplier", None) - search_criteria.pop("brand", None) - search_criteria["color_name"] = "Generic" - materials = self._container_registry.findInstanceContainers(**search_criteria) - if not materials: - # Generic material with new diameter is not found, search for preferred material - search_criteria.pop("color_name", None) - search_criteria.pop("material", None) - search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material") - materials = self._container_registry.findInstanceContainers(**search_criteria) - if not materials: - # Preferred material with new diameter is not found, search for any material - search_criteria.pop("id", None) - materials = self._container_registry.findInstanceContainers(**search_criteria) - if not materials: - # Just use empty material as a final fallback - materials = [self._empty_container] - - Logger.log("i", "Selecting new material: %s", materials[0].getId()) - - extruder_stack.material = materials[0] + Application.getInstance().getExtruderManager().updateMaterialForDiameter(extruder_position)