123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- # Copyright (c) 2018 Ultimaker B.V.
- # Cura is released under the terms of the LGPLv3 or higher.
- from typing import Any, List, Optional, TYPE_CHECKING
- from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
- from UM.Settings.SettingFunction import SettingFunction
- from UM.Logger import Logger
- if TYPE_CHECKING:
- from cura.CuraApplication import CuraApplication
- from cura.Settings.CuraContainerStack import CuraContainerStack
- #
- # This class contains all Cura-related custom functions that can be used in formulas. Some functions requires
- # information such as the currently active machine, so this is made into a class instead of standalone functions.
- #
- class CuraFormulaFunctions:
- def __init__(self, application: "CuraApplication") -> None:
- self._application = application
- # ================
- # Custom Functions
- # ================
- # Gets the default extruder position of the currently active machine.
- def getDefaultExtruderPosition(self) -> str:
- machine_manager = self._application.getMachineManager()
- return machine_manager.defaultExtruderPosition
- # Gets the given setting key from the given extruder position.
- def getValueInExtruder(self, extruder_position: int, property_key: str,
- context: Optional["PropertyEvaluationContext"] = None) -> Any:
- machine_manager = self._application.getMachineManager()
- if extruder_position == -1:
- extruder_position = int(machine_manager.defaultExtruderPosition)
- global_stack = machine_manager.activeMachine
- try:
- extruder_stack = global_stack.extruderList[int(extruder_position)]
- except IndexError:
- if extruder_position != 0:
- Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. Returning the result from extruder 0 instead" % (property_key, extruder_position))
- # This fixes a very specific fringe case; If a profile was created for a custom printer and one of the
- # extruder settings has been set to non zero and the profile is loaded for a machine that has only a single extruder
- # it would cause all kinds of issues (and eventually a crash).
- # See https://github.com/Ultimaker/Cura/issues/5535
- return self.getValueInExtruder(0, property_key, context)
- Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. " % (property_key, extruder_position))
- return None
- value = extruder_stack.getRawProperty(property_key, "value", context = context)
- if isinstance(value, SettingFunction):
- value = value(extruder_stack, context = context)
- return value
- def _getActiveExtruders(self, context: Optional["PropertyEvaluationContext"] = None) -> List[str]:
- machine_manager = self._application.getMachineManager()
- extruder_manager = self._application.getExtruderManager()
- global_stack = machine_manager.activeMachine
- result = []
- for extruder in extruder_manager.getActiveExtruderStacks():
- if not extruder.isEnabled:
- continue
- # 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
- result.append(extruder)
- return result
- # Gets all extruder values as a list for the given property.
- def getValuesInAllExtruders(self, property_key: str,
- context: Optional["PropertyEvaluationContext"] = None) -> List[Any]:
- global_stack = self._application.getMachineManager().activeMachine
- result = []
- for extruder in self._getActiveExtruders(context):
- value = extruder.getRawProperty(property_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(property_key, "value", context = context))
- return result
- # Get the first extruder that adheres to a specific (boolean) property, like 'material_is_support_material'.
- def getAnyExtruderPositionWithOrDefault(self, filter_key: str,
- context: Optional["PropertyEvaluationContext"] = None) -> str:
- for extruder in self._getActiveExtruders(context):
- value = extruder.getRawProperty(filter_key, "value", context=context)
- if value is None or not value:
- continue
- return str(extruder.position)
- return self.getDefaultExtruderPosition()
- # Get the resolve value or value for a given key.
- def getResolveOrValue(self, property_key: str, context: Optional["PropertyEvaluationContext"] = None) -> Any:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- resolved_value = global_stack.getProperty(property_key, "value", context = context)
- return resolved_value
- # Gets the default setting value from given extruder position. The default value is what excludes the values in
- # the user_changes container.
- def getDefaultValueInExtruder(self, extruder_position: int, property_key: str) -> Any:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- try:
- extruder_stack = global_stack.extruderList[extruder_position]
- except IndexError:
- Logger.log("w", "Unable to find extruder on in index %s", extruder_position)
- else:
- context = self.createContextForDefaultValueEvaluation(extruder_stack)
- return self.getValueInExtruder(extruder_position, property_key, context = context)
- # Gets all default setting values as a list from all extruders of the currently active machine.
- # The default values are those excluding the values in the user_changes container.
- def getDefaultValuesInAllExtruders(self, property_key: str) -> List[Any]:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- context = self.createContextForDefaultValueEvaluation(global_stack)
- return self.getValuesInAllExtruders(property_key, context = context)
- # Gets the resolve value or value for a given key without looking the first container (user container).
- def getDefaultResolveOrValue(self, property_key: str) -> Any:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- context = self.createContextForDefaultValueEvaluation(global_stack)
- return self.getResolveOrValue(property_key, context = context)
- # Gets the value for the given setting key starting from the given container index.
- def getValueFromContainerAtIndex(self, property_key: str, container_index: int,
- context: Optional["PropertyEvaluationContext"] = None) -> Any:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- context = self.createContextForDefaultValueEvaluation(global_stack)
- context.context["evaluate_from_container_index"] = container_index
- return global_stack.getProperty(property_key, "value", context = context)
- # Gets the extruder value for the given setting key starting from the given container index.
- def getValueFromContainerAtIndexInExtruder(self, extruder_position: int, property_key: str, container_index: int,
- context: Optional["PropertyEvaluationContext"] = None) -> Any:
- machine_manager = self._application.getMachineManager()
- global_stack = machine_manager.activeMachine
- if extruder_position == -1:
- extruder_position = int(machine_manager.defaultExtruderPosition)
- global_stack = machine_manager.activeMachine
- try:
- extruder_stack = global_stack.extruderList[int(extruder_position)]
- except IndexError:
- Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. " % (property_key, extruder_position))
- return None
- context = self.createContextForDefaultValueEvaluation(extruder_stack)
- context.context["evaluate_from_container_index"] = container_index
- return self.getValueInExtruder(extruder_position, property_key, context)
- # Creates a context for evaluating default values (skip the user_changes container).
- def createContextForDefaultValueEvaluation(self, source_stack: "CuraContainerStack") -> "PropertyEvaluationContext":
- context = PropertyEvaluationContext(source_stack)
- context.context["evaluate_from_container_index"] = 1 # skip the user settings container
- context.context["override_operators"] = {
- "extruderValue": self.getDefaultValueInExtruder,
- "extruderValues": self.getDefaultValuesInAllExtruders,
- "resolveOrValue": self.getDefaultResolveOrValue,
- }
- return context
|