CuraSceneController.py 5.1 KB

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