CuraSceneController.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from UM.Logger import Logger
  2. from PyQt5.QtCore import Qt, pyqtSlot, QObject
  3. from PyQt5.QtWidgets import QApplication
  4. from cura.ObjectsModel import ObjectsModel
  5. from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
  6. from UM.Application import Application
  7. from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
  8. from UM.Scene.SceneNode import SceneNode
  9. from UM.Scene.Selection import Selection
  10. from UM.Signal import Signal
  11. class CuraSceneController(QObject):
  12. activeBuildPlateChanged = Signal()
  13. def __init__(self, objects_model: ObjectsModel, multi_build_plate_model: MultiBuildPlateModel) -> None:
  14. super().__init__()
  15. self._objects_model = objects_model
  16. self._multi_build_plate_model = multi_build_plate_model
  17. self._active_build_plate = -1
  18. self._last_selected_index = 0
  19. self._max_build_plate = 1 # default
  20. Application.getInstance().getController().getScene().sceneChanged.connect(self.updateMaxBuildPlate) # it may be a bit inefficient when changing a lot simultaneously
  21. def updateMaxBuildPlate(self, *args):
  22. if args:
  23. source = args[0]
  24. else:
  25. source = None
  26. if not isinstance(source, SceneNode):
  27. return
  28. max_build_plate = self._calcMaxBuildPlate()
  29. changed = False
  30. if max_build_plate != self._max_build_plate:
  31. self._max_build_plate = max_build_plate
  32. changed = True
  33. if changed:
  34. self._multi_build_plate_model.setMaxBuildPlate(self._max_build_plate)
  35. build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)]
  36. self._multi_build_plate_model.setItems(build_plates)
  37. if self._active_build_plate > self._max_build_plate:
  38. build_plate_number = 0
  39. if self._last_selected_index >= 0: # go to the buildplate of the item you last selected
  40. item = self._objects_model.getItem(self._last_selected_index)
  41. if "node" in item:
  42. node = item["node"]
  43. build_plate_number = node.callDecoration("getBuildPlateNumber")
  44. self.setActiveBuildPlate(build_plate_number)
  45. # self.buildPlateItemsChanged.emit() # TODO: necessary after setItems?
  46. def _calcMaxBuildPlate(self):
  47. max_build_plate = 0
  48. for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
  49. if node.callDecoration("isSliceable"):
  50. build_plate_number = node.callDecoration("getBuildPlateNumber")
  51. if build_plate_number is None:
  52. build_plate_number = 0
  53. max_build_plate = max(build_plate_number, max_build_plate)
  54. return max_build_plate
  55. ## Either select or deselect an item
  56. @pyqtSlot(int)
  57. def changeSelection(self, index):
  58. modifiers = QApplication.keyboardModifiers()
  59. ctrl_is_active = modifiers & Qt.ControlModifier
  60. shift_is_active = modifiers & Qt.ShiftModifier
  61. if ctrl_is_active:
  62. item = self._objects_model.getItem(index)
  63. node = item["node"]
  64. if Selection.isSelected(node):
  65. Selection.remove(node)
  66. else:
  67. Selection.add(node)
  68. elif shift_is_active:
  69. polarity = 1 if index + 1 > self._last_selected_index else -1
  70. for i in range(self._last_selected_index, index + polarity, polarity):
  71. item = self._objects_model.getItem(i)
  72. node = item["node"]
  73. Selection.add(node)
  74. else:
  75. # Single select
  76. item = self._objects_model.getItem(index)
  77. node = item["node"]
  78. build_plate_number = node.callDecoration("getBuildPlateNumber")
  79. if build_plate_number is not None and build_plate_number != -1:
  80. self.setActiveBuildPlate(build_plate_number)
  81. Selection.clear()
  82. Selection.add(node)
  83. self._last_selected_index = index
  84. @pyqtSlot(int)
  85. def setActiveBuildPlate(self, nr):
  86. if nr == self._active_build_plate:
  87. return
  88. Logger.log("d", "Select build plate: %s" % nr)
  89. self._active_build_plate = nr
  90. Selection.clear()
  91. self._multi_build_plate_model.setActiveBuildPlate(nr)
  92. self._objects_model.setActiveBuildPlate(nr)
  93. self.activeBuildPlateChanged.emit()
  94. @staticmethod
  95. def createCuraSceneController():
  96. objects_model = Application.getInstance().getObjectsModel()
  97. multi_build_plate_model = Application.getInstance().getMultiBuildPlateModel()
  98. return CuraSceneController(objects_model = objects_model, multi_build_plate_model = multi_build_plate_model)