SettingOverrideDecorator.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # Copyright (c) 2016 Ultimaker B.V.
  2. # Cura is released under the terms of the AGPLv3 or higher.
  3. import copy
  4. from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
  5. from UM.Signal import Signal, signalemitter
  6. from UM.Settings.ContainerStack import ContainerStack
  7. from UM.Settings.InstanceContainer import InstanceContainer
  8. from UM.Settings.ContainerRegistry import ContainerRegistry
  9. import UM.Logger
  10. import cura.Settings
  11. from UM.Application import Application
  12. ## A decorator that adds a container stack to a Node. This stack should be queried for all settings regarding
  13. # the linked node. The Stack in question will refer to the global stack (so that settings that are not defined by
  14. # this stack still resolve.
  15. @signalemitter
  16. class SettingOverrideDecorator(SceneNodeDecorator):
  17. ## Event indicating that the user selected a different extruder.
  18. activeExtruderChanged = Signal()
  19. def __init__(self):
  20. super().__init__()
  21. self._stack = ContainerStack(stack_id = id(self))
  22. self._stack.setDirty(False) # This stack does not need to be saved.
  23. self._instance = InstanceContainer(container_id = "SettingOverrideInstanceContainer")
  24. self._stack.addContainer(self._instance)
  25. if cura.Settings.ExtruderManager.getInstance().extruderCount > 1:
  26. self._extruder_stack = cura.Settings.ExtruderManager.getInstance().getExtruderStack(0).getId()
  27. else:
  28. self._extruder_stack = None
  29. self._stack.propertyChanged.connect(self._onSettingChanged)
  30. ContainerRegistry.getInstance().addContainer(self._stack)
  31. Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack)
  32. self.activeExtruderChanged.connect(self._updateNextStack)
  33. self._updateNextStack()
  34. def __deepcopy__(self, memo):
  35. ## Create a fresh decorator object
  36. deep_copy = SettingOverrideDecorator()
  37. ## Copy the instance
  38. deep_copy._instance = copy.deepcopy(self._instance, memo)
  39. # Properly set the right extruder on the copy
  40. deep_copy.setActiveExtruder(self._extruder_stack)
  41. ## Set the copied instance as the first (and only) instance container of the stack.
  42. deep_copy._stack.replaceContainer(0, deep_copy._instance)
  43. return deep_copy
  44. ## Gets the currently active extruder to print this object with.
  45. #
  46. # \return An extruder's container stack.
  47. def getActiveExtruder(self):
  48. return self._extruder_stack
  49. ## Gets the signal that emits if the active extruder changed.
  50. #
  51. # This can then be accessed via a decorator.
  52. def getActiveExtruderChangedSignal(self):
  53. return self.activeExtruderChanged
  54. ## Gets the currently active extruders position
  55. #
  56. # \return An extruder's position, or None if no position info is available.
  57. def getActiveExtruderPosition(self):
  58. containers = ContainerRegistry.getInstance().findContainers(id = self.getActiveExtruder())
  59. if containers:
  60. container_stack = containers[0]
  61. return container_stack.getMetaDataEntry("position", default=None)
  62. def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function
  63. if property_name == "value": # Only reslice if the value has changed.
  64. Application.getInstance().getBackend().forceSlice()
  65. ## Makes sure that the stack upon which the container stack is placed is
  66. # kept up to date.
  67. def _updateNextStack(self):
  68. if self._extruder_stack:
  69. extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = self._extruder_stack)
  70. if extruder_stack:
  71. if self._stack.getNextStack():
  72. old_extruder_stack_id = self._stack.getNextStack().getId()
  73. else:
  74. old_extruder_stack_id = ""
  75. self._stack.setNextStack(extruder_stack[0])
  76. if self._stack.getNextStack().getId() != old_extruder_stack_id: #Only reslice if the extruder changed.
  77. Application.getInstance().getBackend().forceSlice()
  78. else:
  79. UM.Logger.log("e", "Extruder stack %s below per-object settings does not exist.", self._extruder_stack)
  80. else:
  81. self._stack.setNextStack(Application.getInstance().getGlobalContainerStack())
  82. ## Changes the extruder with which to print this node.
  83. #
  84. # \param extruder_stack_id The new extruder stack to print with.
  85. def setActiveExtruder(self, extruder_stack_id):
  86. self._extruder_stack = extruder_stack_id
  87. self._updateNextStack()
  88. self.activeExtruderChanged.emit()
  89. def getStack(self):
  90. return self._stack