Browse Source

CURA-4525 automatic build plate menu items using BuildPlateModel

Jack Ha 7 years ago
parent
commit
bd8aa8d989

+ 60 - 0
cura/BuildPlateModel.py

@@ -1,2 +1,62 @@
+from UM.Qt.ListModel import ListModel
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from UM.Scene.SceneNode import SceneNode
+from UM.Logger import Logger
+from UM.Application import Application
 
 
+class BuildPlateModel(ListModel):
+    maxBuildPlateChanged = pyqtSignal()
+    activeBuildPlateChanged = pyqtSignal()
+
+    def __init__(self):
+        super().__init__()
+        Application.getInstance().getController().getScene().sceneChanged.connect(self.updateMaxBuildPlate)  # it may be a bit inefficient when changing a lot simultaneously
+
+        self._max_build_plate = 1  # default
+        self._active_build_plate = 0
+
+    @pyqtSlot(int)
+    def setActiveBuildPlate(self, nr):
+        if nr == self._active_build_plate:
+            return
+        Logger.log("d", "Select build plate: %s" % nr)
+        self._active_build_plate = nr
+
+        self.activeBuildPlateChanged.emit()
+
+    @pyqtProperty(int, notify = activeBuildPlateChanged)
+    def activeBuildPlate(self):
+        return self._active_build_plate
+
+    ##  Return the highest build plate number
+    @pyqtProperty(int, notify = maxBuildPlateChanged)
+    def maxBuildPlate(self):
+        return self._max_build_plate
+
+    def updateMaxBuildPlate(self, source):
+        if not issubclass(type(source), SceneNode):
+            return
+        max_build_plate = self._calcMaxBuildPlate()
+        changed = False
+        if max_build_plate != self._max_build_plate:
+            self._max_build_plate = max_build_plate
+            changed = True
+        if changed:
+            self.maxBuildPlateChanged.emit()
+            build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)]
+            self.setItems(build_plates)
+            self.itemsChanged.emit()
+
+    def _calcMaxBuildPlate(self):
+        max_build_plate = 0
+        for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
+            if node.callDecoration("isSliceable"):
+                build_plate_number = node.callDecoration("getBuildPlateNumber")
+                max_build_plate = max(build_plate_number, max_build_plate)
+        return max_build_plate
+
+    @staticmethod
+    def createBuildPlateModel():
+        return BuildPlateModel()

+ 1 - 1
cura/ConvexHullNode.py

@@ -64,7 +64,7 @@ class ConvexHullNode(SceneNode):
             ConvexHullNode.shader.setUniformValue("u_diffuseColor", self._color)
             ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
 
-        if self.getParent() and self.getParent().callDecoration("getBuildPlateNumber") == Application.getInstance().activeBuildPlate:
+        if self.getParent() and self.getParent().callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate:
             if self.getMeshData():
                 renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
                 if self._convex_hull_head_mesh:

+ 12 - 52
cura/CuraApplication.py

@@ -40,7 +40,6 @@ from cura.ConvexHullDecorator import ConvexHullDecorator
 from cura.SetParentOperation import SetParentOperation
 from cura.SliceableObjectDecorator import SliceableObjectDecorator
 from cura.BlockSlicingDecorator import BlockSlicingDecorator
-# research
 from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
 from cura.Scene.CuraSceneNode import CuraSceneNode
 
@@ -83,6 +82,7 @@ from cura.Settings.GlobalStack import GlobalStack
 from cura.Settings.ExtruderStack import ExtruderStack
 
 from cura.ObjectManager import ObjectManager
+from cura.BuildPlateModel import BuildPlateModel
 
 from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
 from UM.FlameProfiler import pyqtSlot
@@ -211,6 +211,7 @@ class CuraApplication(QtApplication):
         self._machine_manager = None    # This is initialized on demand.
         self._material_manager = None
         self._object_manager = None
+        self._build_plate_model = None
         self._setting_inheritance_manager = None
         self._simple_mode_settings_manager = None
 
@@ -258,7 +259,6 @@ class CuraApplication(QtApplication):
         self._i18n_catalog = i18nCatalog("cura")
 
         self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
-        self.getController().getScene().sceneChanged.connect(self.updateMaxBuildPlate)  # it may be a bit inefficient when changing a lot simultaneously
         self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
         self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
 
@@ -389,10 +389,6 @@ class CuraApplication(QtApplication):
 
         self._plugin_registry.addSupportedPluginExtension("curaplugin", "Cura Plugin")
 
-        # research
-        self._num_build_plates = 1  # default
-        self._active_build_plate = 0
-
     def _onEngineCreated(self):
         self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
 
@@ -724,8 +720,8 @@ class CuraApplication(QtApplication):
         qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager",
                                  self.getSimpleModeSettingsManager)
 
-        Logger.log("d", "           #### going to register object manager")
         qmlRegisterSingletonType(ObjectManager, "Cura", 1, 2, "ObjectManager", self.getObjectManager)
+        qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 2, "BuildPlateModel", self.getBuildPlateModel)
 
         qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
         self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
@@ -759,6 +755,11 @@ class CuraApplication(QtApplication):
             self._object_manager = ObjectManager.createObjectManager()
         return self._object_manager
 
+    def getBuildPlateModel(self, *args):
+        if self._build_plate_model is None:
+            self._build_plate_model = BuildPlateModel.createBuildPlateModel()
+        return self._build_plate_model
+
     def getSettingInheritanceManager(self, *args):
         if self._setting_inheritance_manager is None:
             self._setting_inheritance_manager = SettingInheritanceManager.createSettingInheritanceManager()
@@ -881,8 +882,6 @@ class CuraApplication(QtApplication):
     activityChanged = pyqtSignal()
     sceneBoundingBoxChanged = pyqtSignal()
     preferredOutputMimetypeChanged = pyqtSignal()
-    numBuildPlatesChanged = pyqtSignal()
-    activeBuildPlateChanged = pyqtSignal()
 
     @pyqtProperty(bool, notify = activityChanged)
     def platformActivity(self):
@@ -1130,12 +1129,13 @@ class CuraApplication(QtApplication):
                 nodes.append(node)
         job = ArrangeObjectsAllBuildPlatesJob(nodes)
         job.start()
-        self.setActiveBuildPlate(0)
+        self.getBuildPlateModel().setActiveBuildPlate(0)
 
     # Single build plate
     @pyqtSlot()
     def arrangeAll(self):
         nodes = []
+        active_build_plate = self.getBuildPlateModel().activeBuildPlate
         for node in DepthFirstIterator(self.getController().getScene().getRoot()):
             if not issubclass(type(node), SceneNode):
                 continue
@@ -1147,7 +1147,7 @@ class CuraApplication(QtApplication):
                 continue  # i.e. node with layer data
             if not node.callDecoration("isSliceable"):
                 continue  # i.e. node with layer data
-            if node.callDecoration("getBuildPlateNumber") == self._active_build_plate:
+            if node.callDecoration("getBuildPlateNumber") == active_build_plate:
                 # Skip nodes that are too big
                 if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
                     nodes.append(node)
@@ -1284,7 +1284,7 @@ class CuraApplication(QtApplication):
         group_decorator = GroupDecorator()
         group_node.addDecorator(group_decorator)
         group_node.addDecorator(ConvexHullDecorator())
-        group_node.addDecorator(BuildPlateDecorator(self.activeBuildPlate))
+        group_node.addDecorator(BuildPlateDecorator(self.getBuildPlateModel().activeBuildPlate))
         group_node.setParent(self.getController().getScene().getRoot())
         group_node.setSelectable(True)
         center = Selection.getSelectionCenter()
@@ -1510,43 +1510,3 @@ class CuraApplication(QtApplication):
                     node = node.getParent()
 
                 Selection.add(node)
-
-    #### research - hacky place for these kind of thing
-    @pyqtSlot(int)
-    def setActiveBuildPlate(self, nr):
-        if nr == self._active_build_plate:
-            return
-        Logger.log("d", "Select build plate: %s" % nr)
-        self._active_build_plate = nr
-
-        self.activeBuildPlateChanged.emit()
-
-    @pyqtSlot()
-    def newBuildPlate(self):
-        Logger.log("d", "New build plate")
-        #self._num_build_plates += 1
-        self.numBuildPlatesChanged.emit()
-
-    @pyqtProperty(int, notify = numBuildPlatesChanged)
-    def numBuildPlates(self):
-        return self._num_build_plates
-
-    @pyqtProperty(int, notify = activeBuildPlateChanged)
-    def activeBuildPlate(self):
-        return self._active_build_plate
-
-    def updateMaxBuildPlate(self, source):
-        if not issubclass(type(source), SceneNode):
-            return
-        num_build_plates = self._calcMaxBuildPlate()
-        if num_build_plates != self._num_build_plates:
-            self._num_build_plates = num_build_plates
-            self.numBuildPlatesChanged.emit()
-
-    def _calcMaxBuildPlate(self):
-        max_build_plate = 0
-        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
-            if node.callDecoration("isSliceable"):
-                build_plate_number = node.callDecoration("getBuildPlateNumber")
-                max_build_plate = max(build_plate_number, max_build_plate)
-        return max_build_plate

+ 5 - 10
cura/ObjectManager.py

@@ -15,14 +15,15 @@ class ObjectManager(ListModel):
     def __init__(self):
         super().__init__()
         self._last_selected_index = 0
-        Application.getInstance().getController().getScene().sceneChanged.connect(self._update_scene_changed)
+        self._build_plate_model = Application.getInstance().getBuildPlateModel()
+        Application.getInstance().getController().getScene().sceneChanged.connect(self._update)
         Preferences.getInstance().preferenceChanged.connect(self._update)
-        Application.getInstance().activeBuildPlateChanged.connect(self._update)
+        self._build_plate_model.activeBuildPlateChanged.connect(self._update)
 
     def _update(self, *args):
         nodes = []
         filter_current_build_plate = Preferences.getInstance().getValue("view/filter_current_build_plate")
-        active_build_plate_number = Application.getInstance().activeBuildPlate
+        active_build_plate_number = self._build_plate_model.activeBuildPlate
         for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
             if not issubclass(type(node), SceneNode) or (not node.getMeshData() and not node.callDecoration("getLayerData")):
                 continue
@@ -43,12 +44,6 @@ class ObjectManager(ListModel):
 
         self.itemsChanged.emit()
 
-    def _update_scene_changed(self, *args):
-        # if args and type(args[0]) is not CuraSceneNode:
-        #     Logger.log("d", "   ascdf %s", args)
-        #     return
-        self._update(*args)
-
     ##  Either select or deselect an item
     @pyqtSlot(int)
     def changeSelection(self, index):
@@ -77,7 +72,7 @@ class ObjectManager(ListModel):
             Selection.add(node)
             build_plate_number = node.callDecoration("getBuildPlateNumber")
             if build_plate_number is not None and build_plate_number != -1:
-                Application.getInstance().setActiveBuildPlate(build_plate_number)
+                self._build_plate_model.setActiveBuildPlate(build_plate_number)
 
         self._last_selected_index = index
 

+ 2 - 2
cura/Scene/CuraSceneNode.py

@@ -18,10 +18,10 @@ class CuraSceneNode(SceneNode):
         return self._outside_buildarea or self.callDecoration("getBuildPlateNumber") < 0
 
     def isVisible(self):
-        return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().activeBuildPlate
+        return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate
 
     def isSelectable(self) -> bool:
-        return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().activeBuildPlate
+        return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate
 
     ##  Taken from SceneNode, but replaced SceneNode with CuraSceneNode
     def __deepcopy__(self, memo):

+ 3 - 3
plugins/CuraEngineBackend/CuraEngineBackend.py

@@ -70,7 +70,7 @@ class CuraEngineBackend(QObject, Backend):
         # Workaround to disable layer view processing if layer view is not active.
         self._layer_view_active = False
         Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
-        Application.getInstance().activeBuildPlateChanged.connect(self._onActiveViewChanged)
+        Application.getInstance().getBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveViewChanged)
         self._onActiveViewChanged()
         self._stored_layer_data = []
         self._stored_optimized_layer_data = {}  # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
@@ -564,7 +564,7 @@ class CuraEngineBackend(QObject, Backend):
         Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )
 
         # See if we need to process the sliced layers job.
-        active_build_plate = Application.getInstance().activeBuildPlate
+        active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
         if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()) and active_build_plate == self._start_slice_job_build_plate:
             self._startProcessSlicedLayersJob(active_build_plate)
         # self._onActiveViewChanged()
@@ -682,7 +682,7 @@ class CuraEngineBackend(QObject, Backend):
         application = Application.getInstance()
         view = application.getController().getActiveView()
         if view:
-            active_build_plate = application.activeBuildPlate
+            active_build_plate = application.getBuildPlateModel().activeBuildPlate
             if view.getPluginId() == "LayerView":  # If switching to layer view, we should process the layers if that hasn't been done yet.
                 self._layer_view_active = True
                 # There is data and we're not slicing at the moment

+ 1 - 1
plugins/LayerView/LayerPass.py

@@ -66,7 +66,7 @@ class LayerPass(RenderPass):
         self.bind()
 
         tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay)
-        active_build_plate = Application.getInstance().activeBuildPlate
+        active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
 
         for node in DepthFirstIterator(self._scene.getRoot()):
 

+ 1 - 3
plugins/SolidView/SolidView.py

@@ -71,11 +71,9 @@ class SolidView(View):
             else:
                 self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))
 
-        activeBuildPlateNumber = Application.getInstance().activeBuildPlate
-
         for node in DepthFirstIterator(scene.getRoot()):
             if not node.render(renderer):
-                if node.getMeshData() and node.isVisible():  #  and (node.callDecoration("getBuildPlateNumber") == activeBuildPlateNumber):
+                if node.getMeshData() and node.isVisible():
                     uniforms = {}
                     shade_factor = 1.0
 

+ 5 - 2
resources/qml/Cura.qml

@@ -324,6 +324,7 @@ UM.MainWindow
                 }
             }
 
+            /*
             Button
             {
                 id: openFileButton;
@@ -339,17 +340,19 @@ UM.MainWindow
                 }
                 action: Cura.Actions.open;
             }
+            */
 
             Button
             {
                 id: objectsButton;
                 text: catalog.i18nc("@action:button","Objects");
-                iconSource: UM.Theme.getIcon("load")
+                iconSource: UM.Theme.getIcon("plus")
                 style: UM.Theme.styles.tool_button
                 tooltip: '';
                 anchors
                 {
-                    top: openFileButton.bottom;
+                    top: topbar.bottom;
+                    //top: openFileButton.bottom;
                     topMargin: UM.Theme.getSize("default_margin").height;
                     left: parent.left;
                 }

+ 14 - 14
resources/qml/Menus/ContextMenu.qml

@@ -7,7 +7,7 @@ import QtQuick.Dialogs 1.2
 import QtQuick.Window 2.1
 
 import UM 1.2 as UM
-import Cura 1.0 as Cura
+import Cura 1.2 as Cura
 
 Menu
 {
@@ -40,21 +40,21 @@ Menu
     }
 
     MenuSeparator {}
-    MenuItem {
-        text: "build plate 0";
-        onTriggered: CuraActions.setBuildPlateForSelection(0);
-        checkable: true
-        checked: false
-    }
-    MenuItem {
-        text: "build plate 1";
-        onTriggered: CuraActions.setBuildPlateForSelection(1);
-        checkable: true
-        checked: false
+    Instantiator
+    {
+        model: Cura.BuildPlateModel
+        MenuItem {
+            text: Cura.BuildPlateModel.getItem(index).name;
+            onTriggered: CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.getItem(index).buildPlateNumber);
+            checkable: true
+            checked: Cura.BuildPlateModel.getItem(index).buildPlateNumber == Cura.BuildPlateModel.activeBuildPlate
+        }
+        onObjectAdded: base.insertItem(index, object);
+        onObjectRemoved: base.removeItem(object)
     }
     MenuItem {
-        text: "build plate 2";
-        onTriggered: CuraActions.setBuildPlateForSelection(2);
+        text: "New build plate";
+        onTriggered: CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.maxBuildPlate + 1);
         checkable: true
         checked: false
     }

Some files were not shown because too many files changed in this diff