CuraSceneController.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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.BuildPlateModel import BuildPlateModel
  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. class CuraSceneController(QObject):
  11. def __init__(self, objects_model: ObjectsModel, build_plate_model: BuildPlateModel):
  12. super().__init__()
  13. self._objects_model = objects_model
  14. self._build_plate_model = build_plate_model
  15. self._active_build_plate = -1
  16. self._last_selected_index = 0
  17. self._max_build_plate = 1 # default
  18. Application.getInstance().getController().getScene().sceneChanged.connect(self.updateMaxBuildPlate) # it may be a bit inefficient when changing a lot simultaneously
  19. def updateMaxBuildPlate(self, *args):
  20. if args:
  21. source = args[0]
  22. else:
  23. source = None
  24. if not issubclass(type(source), SceneNode):
  25. return
  26. max_build_plate = self._calcMaxBuildPlate()
  27. changed = False
  28. if max_build_plate != self._max_build_plate:
  29. self._max_build_plate = max_build_plate
  30. changed = True
  31. if changed:
  32. self._build_plate_model.setMaxBuildPlate(self._max_build_plate)
  33. build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)]
  34. self._build_plate_model.setItems(build_plates)
  35. # self.buildPlateItemsChanged.emit() # TODO: necessary after setItems?
  36. def _calcMaxBuildPlate(self):
  37. max_build_plate = 0
  38. for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
  39. if node.callDecoration("isSliceable"):
  40. build_plate_number = node.callDecoration("getBuildPlateNumber")
  41. max_build_plate = max(build_plate_number, max_build_plate)
  42. return max_build_plate
  43. ## Either select or deselect an item
  44. @pyqtSlot(int)
  45. def changeSelection(self, index):
  46. modifiers = QApplication.keyboardModifiers()
  47. ctrl_is_active = modifiers & Qt.ControlModifier
  48. shift_is_active = modifiers & Qt.ShiftModifier
  49. if ctrl_is_active:
  50. item = self._objects_model.getItem(index)
  51. node = item["node"]
  52. if Selection.isSelected(node):
  53. Selection.remove(node)
  54. else:
  55. Selection.add(node)
  56. elif shift_is_active:
  57. polarity = 1 if index + 1 > self._last_selected_index else -1
  58. for i in range(self._last_selected_index, index + polarity, polarity):
  59. item = self._objects_model.getItem(i)
  60. node = item["node"]
  61. Selection.add(node)
  62. else:
  63. # Single select
  64. item = self._objects_model.getItem(index)
  65. node = item["node"]
  66. Selection.clear()
  67. Selection.add(node)
  68. build_plate_number = node.callDecoration("getBuildPlateNumber")
  69. if build_plate_number is not None and build_plate_number != -1:
  70. self._build_plate_model.setActiveBuildPlate(build_plate_number)
  71. self._last_selected_index = index
  72. @pyqtSlot(int)
  73. def setActiveBuildPlate(self, nr):
  74. if nr == self._active_build_plate:
  75. return
  76. Logger.log("d", "Select build plate: %s" % nr)
  77. self._active_build_plate = nr
  78. Selection.clear()
  79. self._build_plate_model.setActiveBuildPlate(nr)
  80. self._objects_model.setActiveBuildPlate(nr)
  81. @staticmethod
  82. def createCuraSceneController():
  83. objects_model = Application.getInstance().getObjectsModel()
  84. build_plate_model = Application.getInstance().getBuildPlateModel()
  85. return CuraSceneController(objects_model = objects_model, build_plate_model = build_plate_model)