Просмотр исходного кода

Merge pull request #4618 from Ultimaker/CURA-5834_fix_material_model_update

CURA-5834 Fix material model update
Remco Burema 6 лет назад
Родитель
Сommit
3dab627670

+ 15 - 5
cura/Machines/MaterialManager.py

@@ -365,7 +365,7 @@ class MaterialManager(QObject):
         nozzle_name = None
         if extruder_stack.variant.getId() != "empty_variant":
             nozzle_name = extruder_stack.variant.getName()
-        diameter = extruder_stack.approximateMaterialDiameter
+        diameter = extruder_stack.getApproximateMaterialDiameter()
 
         # Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
         return self.getAvailableMaterials(machine.definition, nozzle_name, buildplate_name, diameter)
@@ -478,12 +478,22 @@ class MaterialManager(QObject):
 
         buildplate_name = global_stack.getBuildplateName()
         machine_definition = global_stack.definition
+
+        # The extruder-compatible material diameter in the extruder definition may not be the correct value because
+        # the user can change it in the definition_changes container.
         if extruder_definition is None:
-            extruder_definition = global_stack.extruders[position].definition
+            extruder_stack_or_definition = global_stack.extruders[position]
+            is_extruder_stack = True
+        else:
+            extruder_stack_or_definition = extruder_definition
+            is_extruder_stack = False
+
+        if extruder_stack_or_definition and parseBool(global_stack.getMetaDataEntry("has_materials", False)):
+            if is_extruder_stack:
+                material_diameter = extruder_stack_or_definition.getCompatibleMaterialDiameter()
+            else:
+                material_diameter = extruder_stack_or_definition.getProperty("material_diameter", "value")
 
-        if extruder_definition and parseBool(global_stack.getMetaDataEntry("has_materials", False)):
-            # At this point the extruder_definition is not None
-            material_diameter = extruder_definition.getProperty("material_diameter", "value")
             if isinstance(material_diameter, SettingFunction):
                 material_diameter = material_diameter(global_stack)
             approximate_material_diameter = str(round(material_diameter))

+ 2 - 0
cura/Machines/Models/BaseMaterialsModel.py

@@ -64,9 +64,11 @@ class BaseMaterialsModel(ListModel):
 
         if self._extruder_stack is not None:
             self._extruder_stack.pyqtContainersChanged.disconnect(self._update)
+            self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._update)
         self._extruder_stack = global_stack.extruders.get(str(self._extruder_position))
         if self._extruder_stack is not None:
             self._extruder_stack.pyqtContainersChanged.connect(self._update)
+            self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
         # Force update the model when the extruder stack changes
         self._update()
 

+ 1 - 1
cura/Settings/CuraStackBuilder.py

@@ -129,7 +129,7 @@ class CuraStackBuilder:
 
         # get material container for extruders
         material_container = application.empty_material_container
-        material_node = material_manager.getDefaultMaterial(global_stack, extruder_position, extruder_variant_name,
+        material_node = material_manager.getDefaultMaterial(global_stack, str(extruder_position), extruder_variant_name,
                                                             extruder_definition = extruder_definition)
         if material_node and material_node.getContainer():
             material_container = material_node.getContainer()

+ 25 - 6
cura/Settings/ExtruderStack.py

@@ -65,16 +65,33 @@ class ExtruderStack(CuraContainerStack):
     def getLoadingPriority(cls) -> int:
         return 3
 
+    compatibleMaterialDiameterChanged = pyqtSignal()
+
     ##  Return the filament diameter that the machine requires.
     #
     #   If the machine has no requirement for the diameter, -1 is returned.
     #   \return The filament diameter for the printer
-    @property
-    def materialDiameter(self) -> float:
+    def getCompatibleMaterialDiameter(self) -> float:
         context = PropertyEvaluationContext(self)
         context.context["evaluate_from_container_index"] = _ContainerIndexes.Variant
 
-        return self.getProperty("material_diameter", "value", context = context)
+        return float(self.getProperty("material_diameter", "value", context = context))
+
+    def setCompatibleMaterialDiameter(self, value: float) -> None:
+        old_approximate_diameter = self.getApproximateMaterialDiameter()
+        if self.getCompatibleMaterialDiameter() != value:
+            self.definitionChanges.setProperty("material_diameter", "value", value)
+            self.compatibleMaterialDiameterChanged.emit()
+
+            # Emit approximate diameter changed signal if needed
+            if old_approximate_diameter != self.getApproximateMaterialDiameter():
+                self.approximateMaterialDiameterChanged.emit()
+
+    compatibleMaterialDiameter = pyqtProperty(float, fset = setCompatibleMaterialDiameter,
+                                              fget = getCompatibleMaterialDiameter,
+                                              notify = compatibleMaterialDiameterChanged)
+
+    approximateMaterialDiameterChanged = pyqtSignal()
 
     ##  Return the approximate filament diameter that the machine requires.
     #
@@ -84,9 +101,11 @@ class ExtruderStack(CuraContainerStack):
     #   If the machine has no requirement for the diameter, -1 is returned.
     #
     #   \return The approximate filament diameter for the printer
-    @pyqtProperty(float)
-    def approximateMaterialDiameter(self) -> float:
-        return round(float(self.materialDiameter))
+    def getApproximateMaterialDiameter(self) -> float:
+        return round(self.getCompatibleMaterialDiameter())
+
+    approximateMaterialDiameter = pyqtProperty(float, fget = getApproximateMaterialDiameter,
+                                               notify = approximateMaterialDiameterChanged)
 
     ##  Overridden from ContainerStack
     #

+ 2 - 6
cura/Settings/MachineManager.py

@@ -1279,11 +1279,7 @@ class MachineManager(QObject):
             if extruder.variant.getId() != empty_variant_container.getId():
                 current_nozzle_name = extruder.variant.getMetaDataEntry("name")
 
-            from UM.Settings.Interfaces import PropertyEvaluationContext
-            from cura.Settings.CuraContainerStack import _ContainerIndexes
-            context = PropertyEvaluationContext(extruder)
-            context.context["evaluate_from_container_index"] = _ContainerIndexes.DefinitionChanges
-            material_diameter = extruder.getProperty("material_diameter", "value", context)
+            material_diameter = extruder.getCompatibleMaterialDiameter()
             candidate_materials = self._material_manager.getAvailableMaterials(
                 self._global_container_stack.definition,
                 current_nozzle_name,
@@ -1418,7 +1414,7 @@ class MachineManager(QObject):
         position = str(position)
         extruder_stack = self._global_container_stack.extruders[position]
         nozzle_name = extruder_stack.variant.getName()
-        material_diameter = extruder_stack.approximateMaterialDiameter
+        material_diameter = extruder_stack.getApproximateMaterialDiameter()
         material_node = self._material_manager.getMaterialNode(machine_definition_id, nozzle_name, buildplate_name,
                                                                material_diameter, root_material_id)
         self.setMaterial(position, material_node)

+ 1 - 1
plugins/3MFReader/ThreeMFWorkspaceReader.py

@@ -926,7 +926,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
             build_plate_id = global_stack.variant.getId()
 
             # get material diameter of this extruder
-            machine_material_diameter = extruder_stack.materialDiameter
+            machine_material_diameter = extruder_stack.getCompatibleMaterialDiameter()
             material_node = material_manager.getMaterialNode(global_stack.definition.getId(),
                                                              extruder_stack.variant.getName(),
                                                              build_plate_id,

+ 26 - 3
plugins/MachineSettingsAction/MachineSettingsAction.qml

@@ -408,6 +408,10 @@ Cura.MachineAction
                                     manager.updateMaterialForDiameter(settingsTabs.currentIndex - 1);
                                 }
                             }
+                            function setValueFunction(value)
+                            {
+                                Cura.MachineManager.activeStack.compatibleMaterialDiameter = value
+                            }
                             property bool isExtruderSetting: true
                         }
 
@@ -564,6 +568,7 @@ Cura.MachineAction
             property bool _forceUpdateOnChange: (typeof(forceUpdateOnChange) === 'undefined') ? false : forceUpdateOnChange
             property string _label: (typeof(label) === 'undefined') ? "" : label
             property string _tooltip: (typeof(tooltip) === 'undefined') ? propertyProvider.properties.description : tooltip
+            property var _setValueFunction: (typeof(setValueFunction) === 'undefined') ? undefined : setValueFunction
 
             UM.SettingPropertyProvider
             {
@@ -616,14 +621,32 @@ Cura.MachineAction
                         {
                             if (propertyProvider && text != propertyProvider.properties.value)
                             {
-                                propertyProvider.setPropertyValue("value", text);
+                                // For some properties like the extruder-compatible material diameter, they need to
+                                // trigger many updates, such as the available materials, the current material may
+                                // need to be switched, etc. Although setting the diameter can be done directly via
+                                // the provider, all the updates that need to be triggered then need to depend on
+                                // the metadata update, a signal that can be fired way too often. The update functions
+                                // can have if-checks to filter out the irrelevant updates, but still it incurs unnecessary
+                                // overhead.
+                                // The ExtruderStack class has a dedicated function for this call "setCompatibleMaterialDiameter()",
+                                // and it triggers the diameter update signals only when it is needed. Here it is optionally
+                                // choose to use setCompatibleMaterialDiameter() or other more specific functions that
+                                // are available.
+                                if (_setValueFunction !== undefined)
+                                {
+                                    _setValueFunction(text)
+                                }
+                                else
+                                {
+                                    propertyProvider.setPropertyValue("value", text)
+                                }
                                 if(_forceUpdateOnChange)
                                 {
-                                    manager.forceUpdate();
+                                    manager.forceUpdate()
                                 }
                                 if(_afterOnEditingFinished)
                                 {
-                                    _afterOnEditingFinished();
+                                    _afterOnEditingFinished()
                                 }
                             }
                         }