Browse Source

Merge pull request #3033 from Ultimaker/CURA-4708_fix_definition_changes_extruder_stacks

CURA-4708 Fix definition_changes containers for extruder stacks
ChrisTerBeke 7 years ago
parent
commit
0b7519dff2

+ 43 - 3
cura/Settings/CuraContainerRegistry.py

@@ -14,6 +14,7 @@ from UM.Decorators import override
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.ContainerStack import ContainerStack
 from UM.Settings.InstanceContainer import InstanceContainer
+from UM.Settings.SettingInstance import SettingInstance
 from UM.Application import Application
 from UM.Logger import Logger
 from UM.Message import Message
@@ -430,11 +431,42 @@ class CuraContainerRegistry(ContainerRegistry):
         extruder_stack.setDefinition(extruder_definition)
         extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
 
+        from cura.CuraApplication import CuraApplication
+
+        # create a new definition_changes container for the extruder stack
+        definition_changes_id = self.uniqueName(extruder_stack.getId() + "_settings")
+        definition_changes_name = definition_changes_id
+        definition_changes = InstanceContainer(definition_changes_id)
+        definition_changes.setName(definition_changes_name)
+        definition_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
+        definition_changes.addMetaDataEntry("type", "definition_changes")
+        definition_changes.addMetaDataEntry("definition", extruder_definition.getId())
+
+        # move definition_changes settings if exist
+        for setting_key in definition_changes.getAllKeys():
+            if machine.definition.getProperty(setting_key, "settable_per_extruder"):
+                setting_value = machine.definitionChanges.getProperty(setting_key, "value")
+                if setting_value is not None:
+                    # move it to the extruder stack's definition_changes
+                    setting_definition = machine.getSettingDefinition(setting_key)
+                    new_instance = SettingInstance(setting_definition, definition_changes)
+                    new_instance.setProperty("value", setting_value)
+                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
+                    definition_changes.addInstance(new_instance)
+                    definition_changes.setDirty(True)
+
+                    machine.definitionChanges.removeInstance(setting_key, postpone_emit = True)
+
+        self.addContainer(definition_changes)
+        extruder_stack.setDefinitionChanges(definition_changes)
+
         # create empty user changes container otherwise
-        user_container = InstanceContainer(extruder_stack.id + "_user")
+        user_container_id = self.uniqueName(extruder_stack.getId() + "_user")
+        user_container_name = user_container_id
+        user_container = InstanceContainer(user_container_id)
+        user_container.setName(user_container_name)
         user_container.addMetaDataEntry("type", "user")
         user_container.addMetaDataEntry("machine", extruder_stack.getId())
-        from cura.CuraApplication import CuraApplication
         user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
         user_container.setDefinition(machine.definition.getId())
 
@@ -444,7 +476,15 @@ class CuraContainerRegistry(ContainerRegistry):
             for user_setting_key in machine.userChanges.getAllKeys():
                 settable_per_extruder = machine.getProperty(user_setting_key, "settable_per_extruder")
                 if settable_per_extruder:
-                    user_container.addInstance(machine.userChanges.getInstance(user_setting_key))
+                    setting_value = machine.getProperty(user_setting_key, "value")
+
+                    setting_definition = machine.getSettingDefinition(user_setting_key)
+                    new_instance = SettingInstance(setting_definition, definition_changes)
+                    new_instance.setProperty("value", setting_value)
+                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
+                    user_container.addInstance(new_instance)
+                    user_container.setDirty(True)
+
                     machine.userChanges.removeInstance(user_setting_key, postpone_emit = True)
 
         self.addContainer(user_container)

+ 29 - 0
cura/Settings/ExtruderStack.py

@@ -8,6 +8,7 @@ from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
 from UM.Settings.ContainerStack import ContainerStack
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
+from UM.Settings.SettingInstance import SettingInstance
 
 from . import Exceptions
 from .CuraContainerStack import CuraContainerStack
@@ -16,6 +17,11 @@ from .ExtruderManager import ExtruderManager
 if TYPE_CHECKING:
     from cura.Settings.GlobalStack import GlobalStack
 
+
+_EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS = ["machine_nozzle_size",
+                                                  "material_diameter"]
+
+
 ##  Represents an Extruder and its related containers.
 #
 #
@@ -39,6 +45,29 @@ class ExtruderStack(CuraContainerStack):
         # For backward compatibility: Register the extruder with the Extruder Manager
         ExtruderManager.getInstance().registerExtruder(self, stack.id)
 
+        # Now each machine will have at least one extruder stack. If this is the first extruder, the extruder-specific
+        # settings such as nozzle size and material diameter should be moved from the machine's definition_changes to
+        # the this extruder's definition_changes.
+        #
+        # We do this here because it is tooooo expansive to do it in the version upgrade: During the version upgrade,
+        # when we are upgrading a definition_changes container file, there is NO guarantee that other files such as
+        # machine an extruder stack files are upgraded before this, so we cannot read those files assuming they are in
+        # the latest format.
+        if self.getMetaDataEntry("position") == "0":
+            for key in _EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS:
+                setting_value = stack.definitionChanges.getProperty(key, "value")
+                if setting_value is None:
+                    continue
+
+                setting_definition = stack.getSettingDefinition(key)
+                new_instance = SettingInstance(setting_definition, self.definitionChanges)
+                new_instance.setProperty("value", setting_value)
+                new_instance.resetState()  # Ensure that the state is not seen as a user state.
+                self.definitionChanges.addInstance(new_instance)
+                self.definitionChanges.setDirty(True)
+
+                stack.definitionChanges.removeInstance(key, postpone_emit = True)
+
     @override(ContainerStack)
     def getNextStack(self) -> Optional["GlobalStack"]:
         return super().getNextStack()

+ 1 - 138
plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py

@@ -122,26 +122,6 @@ class VersionUpgrade30to31(VersionUpgrade):
             if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
                 self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
 
-        if parser["metadata"]["type"] == "definition_changes":
-            if parser["general"]["definition"] == "custom":
-
-                # We are only interested in machine_nozzle_size
-                if parser.has_option("values", "machine_nozzle_size"):
-                    machine_nozzle_size = parser["values"]["machine_nozzle_size"]
-
-                    machine_extruder_count = '1' # by default it is 1 and the value cannot be stored in the global stack
-                    if parser.has_option("values", "machine_extruder_count"):
-                        machine_extruder_count = parser["values"]["machine_extruder_count"]
-
-                    if machine_extruder_count == '1':
-                        definition_name = parser["general"]["name"]
-                        machine_extruders = self._getSingleExtrusionMachineExtruders(definition_name)
-
-                        # For single extruder machine we need only first extruder
-                        if len(machine_extruders) != 0:
-                            self._updateSingleExtruderDefinitionFile(machine_extruders, machine_nozzle_size)
-                            parser.remove_option("values", "machine_nozzle_size")
-
         # Update version numbers
         parser["general"]["version"] = "2"
         parser["metadata"]["setting_version"] = "4"
@@ -220,123 +200,6 @@ class VersionUpgrade30to31(VersionUpgrade):
 
         return quality_changes_containers
 
-    def _getSingleExtrusionMachineExtruders(self, definition_name):
-
-        machine_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.MachineStack)
-
-        machine_instance_id = None
-
-        # Find machine instances
-        for item in os.listdir(machine_instances_dir):
-            file_path = os.path.join(machine_instances_dir, item)
-            if not os.path.isfile(file_path):
-                continue
-
-            parser = configparser.ConfigParser(interpolation=None)
-            try:
-                parser.read([file_path])
-            except:
-                # skip, it is not a valid stack file
-                continue
-
-            if not parser.has_option("metadata", "type"):
-                continue
-            if "machine" != parser["metadata"]["type"]:
-                continue
-
-            if not parser.has_option("general", "id"):
-                continue
-
-            id = parser["general"]["id"]
-            if id + "_settings" != definition_name:
-                continue
-            else:
-                machine_instance_id = id
-                break
-
-        if machine_instance_id is not None:
-
-            extruders_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack)
-                        #"machine",[extruders]
-            extruder_instances = []
-
-            # Find all custom extruders for found machines
-            for item in os.listdir(extruders_instances_dir):
-                file_path = os.path.join(extruders_instances_dir, item)
-                if not os.path.isfile(file_path):
-                    continue
-
-                parser = configparser.ConfigParser(interpolation=None)
-                try:
-                    parser.read([file_path])
-                except:
-                    # skip, it is not a valid stack file
-                    continue
-
-                if not parser.has_option("metadata", "type"):
-                    continue
-                if "extruder_train" != parser["metadata"]["type"]:
-                    continue
-
-                if not parser.has_option("metadata", "machine"):
-                    continue
-                if not parser.has_option("metadata", "position"):
-                    continue
-
-                if machine_instance_id != parser["metadata"]["machine"]:
-                    continue
-
-                extruder_instances.append(parser)
-
-        return extruder_instances
-
-    # Find extruder definition at index 0 and update its values
-    def _updateSingleExtruderDefinitionFile(self, extruder_instances_per_machine, machine_nozzle_size):
-
-        defintion_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer)
-
-        for item in os.listdir(defintion_instances_dir):
-            file_path = os.path.join(defintion_instances_dir, item)
-            if not os.path.isfile(file_path):
-                continue
-
-            parser = configparser.ConfigParser(interpolation=None)
-            try:
-                parser.read([file_path])
-            except:
-                # skip, it is not a valid stack file
-                continue
-
-            if not parser.has_option("general", "name"):
-                continue
-            name = parser["general"]["name"]
-            custom_extruder_at_0_position = None
-            for extruder_instance in extruder_instances_per_machine:
-
-                definition_position = extruder_instance["metadata"]["position"]
-
-                if definition_position == "0":
-                    custom_extruder_at_0_position = extruder_instance
-                    break
-
-            # If not null, then parsed file is for first extuder and then can be updated. I need to update only
-            # first, because this update for single extuder machine
-            if custom_extruder_at_0_position is not None:
-
-                #Add new value
-                parser["values"]["machine_nozzle_size"] = machine_nozzle_size
-
-                definition_output = io.StringIO()
-                parser.write(definition_output)
-
-                with open(file_path, "w") as f:
-                    f.write(definition_output.getvalue())
-
-                return True
-
-        return False
-
-
     def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes):
         suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower())
         machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "")
@@ -369,4 +232,4 @@ class VersionUpgrade30to31(VersionUpgrade):
         quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer)
 
         with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w") as f:
-            f.write(extruder_quality_changes_output.getvalue())
+            f.write(extruder_quality_changes_output.getvalue())

+ 21 - 0
resources/definitions/fdmextruder.def.json

@@ -181,6 +181,27 @@
                 }
             }
         },
+        "material": {
+            "label": "Material",
+            "icon": "category_material",
+            "description": "Material",
+            "type": "category",
+            "children": {
+                "material_diameter": {
+                    "label": "Diameter",
+                    "description": "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament.",
+                    "unit": "mm",
+                    "type": "float",
+                    "default_value": 2.85,
+                    "minimum_value": "0.0001",
+                    "minimum_value_warning": "0.4",
+                    "maximum_value_warning": "3.5",
+                    "enabled": "machine_gcode_flavor != \"UltiGCode\"",
+                    "settable_per_mesh": false,
+                    "settable_per_extruder": true
+                }
+            }
+        },
         "platform_adhesion":
         {
             "label": "Build Plate Adhesion",