diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 1c01b1fc8a..c8daca7f92 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -588,6 +588,46 @@ class ExtruderManager(QObject): return result + ## Get all extruder values for a certain setting. This function will skip the user settings container. + # + # This is exposed to SettingFunction so it can be used in value functions. + # + # \param key The key of the setting to retrieve values for. + # + # \return A list of values for all extruders. If an extruder does not have a value, it will not be in the list. + # If no extruder has the value, the list will contain the global value. + @staticmethod + def getDefaultExtruderValues(key): + global_stack = Application.getInstance().getGlobalContainerStack() + context = PropertyEvaluationContext(global_stack) + context.context["evaluate_from_container_index"] = 1 # skip the user settings container + context.context["override_operators"] = { + "extruderValue": ExtruderManager.getDefaultExtruderValue, + "extruderValues": ExtruderManager.getDefaultExtruderValues, + "resolveOrValue": ExtruderManager.getDefaultResolveOrValue + } + + result = [] + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + # only include values from extruders that are "active" for the current machine instance + if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value", context = context): + continue + + value = extruder.getRawProperty(key, "value", context = context) + + if value is None: + continue + + if isinstance(value, SettingFunction): + value = value(extruder, context = context) + + result.append(value) + + if not result: + result.append(global_stack.getProperty(key, "value", context = context)) + + return result + ## Get all extruder values for a certain setting. # # This is exposed to qml for display purposes @@ -622,11 +662,24 @@ class ExtruderManager(QObject): return value ## Get the default value from the given extruder. This function will skip the user settings container. + # + # This is exposed to SettingFunction to use in value functions. + # + # \param extruder_index The index of the extruder to get the value from. + # \param key The key of the setting to get the value of. + # + # \return The value of the setting for the specified extruder or for the + # global stack if not found. @staticmethod def getDefaultExtruderValue(extruder_index, key): extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index) - context = PropertyEvaluationContext() + context = PropertyEvaluationContext(extruder) context.context["evaluate_from_container_index"] = 1 # skip the user settings container + context.context["override_operators"] = { + "extruderValue": ExtruderManager.getDefaultExtruderValue, + "extruderValues": ExtruderManager.getDefaultExtruderValues, + "resolveOrValue": ExtruderManager.getDefaultResolveOrValue + } if extruder: value = extruder.getRawProperty(key, "value", context = context) @@ -650,3 +703,25 @@ class ExtruderManager(QObject): resolved_value = global_stack.getProperty(key, "value") return resolved_value + + ## Get the resolve value or value for a given key without looking the first container (user container) + # + # This is the effective value for a given key, it is used for values in the global stack. + # This is exposed to SettingFunction to use in value functions. + # \param key The key of the setting to get the value of. + # + # \return The effective value + @staticmethod + def getDefaultResolveOrValue(key): + global_stack = Application.getInstance().getGlobalContainerStack() + context = PropertyEvaluationContext(global_stack) + context.context["evaluate_from_container_index"] = 1 # skip the user settings container + context.context["override_operators"] = { + "extruderValue": ExtruderManager.getDefaultExtruderValue, + "extruderValues": ExtruderManager.getDefaultExtruderValues, + "resolveOrValue": ExtruderManager.getDefaultResolveOrValue + } + + resolved_value = global_stack.getProperty(key, "value", context = context) + + return resolved_value diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 2eb951f721..88218c2f1e 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -96,18 +96,18 @@ class GlobalStack(CuraContainerStack): if not self.definition.findDefinitions(key = key): return None + if context is None: + context = PropertyEvaluationContext() + context.pushContainer(self) + # Handle the "resolve" property. - if self._shouldResolve(key, property_name): + if self._shouldResolve(key, property_name, context): self._resolving_settings.add(key) resolve = super().getProperty(key, "resolve", context) self._resolving_settings.remove(key) if resolve is not None: return resolve - if context is None: - context = PropertyEvaluationContext() - context.pushContainer(self) - # Handle the "limit_to_extruder" property. limit_to_extruder = super().getProperty(key, "limit_to_extruder", context) if limit_to_extruder is not None: @@ -151,7 +151,7 @@ class GlobalStack(CuraContainerStack): # Determine whether or not we should try to get the "resolve" property instead of the # requested property. - def _shouldResolve(self, key: str, property_name: str) -> bool: + def _shouldResolve(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> bool: if property_name is not "value": # Do not try to resolve anything but the "value" property return False @@ -163,7 +163,7 @@ class GlobalStack(CuraContainerStack): # track all settings that are being resolved. return False - setting_state = super().getProperty(key, "state") + setting_state = super().getProperty(key, "state", context = context) if setting_state is not None and setting_state != InstanceState.Default: # When the user has explicitly set a value, we should ignore any resolve and # just return that value. diff --git a/cura/Settings/UserChangesModel.py b/cura/Settings/UserChangesModel.py index d47468b808..93274d61c9 100644 --- a/cura/Settings/UserChangesModel.py +++ b/cura/Settings/UserChangesModel.py @@ -70,8 +70,11 @@ class UserChangesModel(ListModel): # Override "getExtruderValue" with "getDefaultExtruderValue" so we can get the default values user_changes = containers.pop(0) default_value_resolve_context = PropertyEvaluationContext(stack) + default_value_resolve_context.context["evaluate_from_container_index"] = 1 # skip the user settings container default_value_resolve_context.context["override_operators"] = { - "extruderValue": ExtruderManager.getDefaultExtruderValue + "extruderValue": ExtruderManager.getDefaultExtruderValue, + "extruderValues": ExtruderManager.getDefaultExtruderValues, + "resolveOrValue": ExtruderManager.getDefaultResolveOrValue } for setting_key in user_changes.getAllKeys():