Browse Source

copy_paste in a grid
arrange all objects in grid
place in grid

Co-authored-by: Casper Lamboo <c.lamboo@ultimaker.com>

CURA-7951

saumya.jain 1 year ago
parent
commit
b62725b4f0

+ 11 - 4
cura/Arranging/ArrangeObjectsJob.py

@@ -8,6 +8,7 @@ from UM.Logger import Logger
 from UM.Message import Message
 from UM.Scene.SceneNode import SceneNode
 from UM.i18n import i18nCatalog
+from cura.Arranging.GridArrange import GridArrange
 from cura.Arranging.Nest2DArrange import arrange
 
 i18n_catalog = i18nCatalog("cura")
@@ -15,12 +16,12 @@ i18n_catalog = i18nCatalog("cura")
 
 class ArrangeObjectsJob(Job):
     def __init__(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode], min_offset=8,
-                 lock_rotation: bool = False) -> None:
+                 grid_arrange: bool = False) -> None:
         super().__init__()
         self._nodes = nodes
         self._fixed_nodes = fixed_nodes
         self._min_offset = min_offset
-        self._lock_rotation = lock_rotation
+        self._grid_arrange = grid_arrange
 
     def run(self):
         found_solution_for_all = False
@@ -32,8 +33,14 @@ class ArrangeObjectsJob(Job):
         status_message.show()
 
         try:
-            found_solution_for_all = arrange(self._nodes, Application.getInstance().getBuildVolume(), self._fixed_nodes,
-                                             lock_rotation=self._lock_rotation)
+
+            if self._grid_arrange:
+                grid_arrange = GridArrange(self._nodes, Application.getInstance().getBuildVolume(), self._fixed_nodes)
+                found_solution_for_all = grid_arrange.arrange()
+
+            else:
+                found_solution_for_all = arrange(self._nodes, Application.getInstance().getBuildVolume(), self._fixed_nodes)
+
         except:  # If the thread crashes, the message should still close
             Logger.logException("e", "Unable to arrange the objects on the buildplate. The arrange algorithm has crashed.")
 

+ 7 - 1
cura/Arranging/GridArrange.py

@@ -26,7 +26,13 @@ class GridArrange:
         self._build_volume_bounding_box = build_volume.getBoundingBox()
         self._fixed_nodes = fixed_nodes
 
-    def arrange(self) -> Tuple[GroupedOperation, int]:
+    def arrange(self)-> bool:
+
+        grouped_operation, not_fit_count = self.createGroupOperationForArrange()
+        grouped_operation.push()
+        return not_fit_count == 0
+
+    def createGroupOperationForArrange(self) -> Tuple[GroupedOperation, int]:
         self._grid_width = 0
         self._grid_height = 0
         for node in self._nodes_to_arrange:

+ 6 - 6
cura/CuraActions.py

@@ -18,6 +18,7 @@ from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
 from UM.Operations.TranslateOperation import TranslateOperation
 
 import cura.CuraApplication
+from cura.Arranging.GridArrange import GridArrange
 from cura.Operations.SetParentOperation import SetParentOperation
 from cura.MultiplyObjectsJob import MultiplyObjectsJob
 from cura.Settings.SetObjectExtruderOperation import SetObjectExtruderOperation
@@ -84,16 +85,16 @@ class CuraActions(QObject):
         operation.push()
 
     @pyqtSlot(int, bool)
-    def multiplySelection(self, count: int, lock_rotation: bool) -> None:
+    def multiplySelection(self, count: int, grid_placement: bool) -> None:
         """Multiply all objects in the selection
 
         :param count: The number of times to multiply the selection.
-        :param lock_rotation: If set to true the orientation of the object will remain the same
+        :param grid_placement: If set to true objects are placed in a grid
         """
 
         min_offset = cura.CuraApplication.CuraApplication.getInstance().getBuildVolume().getEdgeDisallowedSize() + 2  # Allow for some rounding errors
         job = MultiplyObjectsJob(Selection.getAllSelectedObjects(), count, min_offset=max(min_offset, 8),
-                                 lock_rotation=lock_rotation)
+                                 grid_arrange=grid_placement)
         job.start()
 
     @pyqtSlot()
@@ -231,9 +232,8 @@ class CuraActions(QObject):
             if node.callDecoration("isSliceable"):
                 fixed_nodes.append(node)
         # Add the new nodes to the scene, and arrange them
-        group_operation, not_fit_count = createGroupOperationForArrange(nodes, application.getBuildVolume(),
-                                                                        fixed_nodes, factor=10000,
-                                                                        add_new_nodes_in_scene=True)
+        grid_arrange = GridArrange(nodes, application.getBuildVolume(), fixed_nodes)
+        group_operation, not_fit_count = grid_arrange.createGroupOperationForArrange()
         group_operation.push()
 
         # deselect currently selected nodes, and select the new nodes

+ 5 - 5
cura/CuraApplication.py

@@ -1441,7 +1441,7 @@ class CuraApplication(QtApplication):
 
     # Single build plate
     @pyqtSlot(bool)
-    def arrangeAll(self, lock_rotation: bool) -> None:
+    def arrangeAll(self, grid_arrangement: bool) -> None:
         nodes_to_arrange = []
         active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
         locked_nodes = []
@@ -1471,18 +1471,18 @@ class CuraApplication(QtApplication):
                         locked_nodes.append(node)
                     else:
                         nodes_to_arrange.append(node)
-        self.arrange(nodes_to_arrange, locked_nodes, lock_rotation)
+        self.arrange(nodes_to_arrange, locked_nodes, grid_arrangement)
 
-    def arrange(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode], lock_rotation: bool = False) -> None:
+    def arrange(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode], grid_arrangement: bool = False) -> None:
         """Arrange a set of nodes given a set of fixed nodes
 
         :param nodes: nodes that we have to place
         :param fixed_nodes: nodes that are placed in the arranger before finding spots for nodes
-        :param lock_rotation: If set to true the orientation of the object will remain the same
+        :param grid_arrangement: If set to true if objects are to be placed in a grid
         """
 
         min_offset = self.getBuildVolume().getEdgeDisallowedSize() + 2  # Allow for some rounding errors
-        job = ArrangeObjectsJob(nodes, fixed_nodes, min_offset=max(min_offset, 8), lock_rotation=lock_rotation)
+        job = ArrangeObjectsJob(nodes, fixed_nodes, min_offset=max(min_offset, 8), grid_arrange =grid_arrangement)
         job.start()
 
     @pyqtSlot()

+ 12 - 14
cura/MultiplyObjectsJob.py

@@ -21,12 +21,12 @@ i18n_catalog = i18nCatalog("cura")
 
 
 class MultiplyObjectsJob(Job):
-    def __init__(self, objects, count: int, min_offset: int = 8, lock_rotation: bool = False):
+    def __init__(self, objects, count: int, min_offset: int = 8, grid_arrange: bool = False):
         super().__init__()
         self._objects = objects
         self._count: int = count
         self._min_offset: int = min_offset
-        self._lock_rotation: bool = lock_rotation
+        self._grid_arrange: bool = grid_arrange
 
     def run(self) -> None:
         status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime = 0,
@@ -78,18 +78,16 @@ class MultiplyObjectsJob(Job):
         found_solution_for_all = True
         group_operation = GroupedOperation()
         if nodes:
-            grid_arrange = GridArrange(nodes,Application.getInstance().getBuildVolume(),
-                                                                            fixed_nodes)
-
-            group_operation, not_fit_count = grid_arrange.arrange()
-            print("group_operation", group_operation)
-            # group_operation, not_fit_count = createGroupOperationForArrange(nodes,
-            #                                                                 Application.getInstance().getBuildVolume(),
-            #                                                                 fixed_nodes,
-            #                                                                 factor=10000,
-            #                                                                 add_new_nodes_in_scene=True,
-            #                                                                 lock_rotation=self._lock_rotation)
-            found_solution_for_all = not_fit_count == 0
+            if(self._grid_arrange):
+                grid_arrange = GridArrange(nodes,Application.getInstance().getBuildVolume(),fixed_nodes)
+                group_operation, not_fit_count = grid_arrange.createGroupOperationForArrange()
+
+            else:
+                group_operation, not_fit_count = createGroupOperationForArrange(nodes,
+                                                                                Application.getInstance().getBuildVolume(),
+                                                                                fixed_nodes,
+                                                                                factor=10000,
+                                                                                add_new_nodes_in_scene=True)
 
         if nodes_to_add_without_arrange:
             for nested_node in nodes_to_add_without_arrange:

+ 3 - 3
resources/qml/Actions.qml

@@ -41,7 +41,7 @@ Item
     property alias deleteAll: deleteAllAction
     property alias reloadAll: reloadAllAction
     property alias arrangeAll: arrangeAllAction
-    property alias arrangeAllLock: arrangeAllLockAction
+    property alias arrangeAllGrid: arrangeAllGridAction
     property alias arrangeSelection: arrangeSelectionAction
     property alias arrangeSelectionLock: arrangeSelectionLockAction
     property alias resetAllTranslation: resetAllTranslationAction
@@ -464,8 +464,8 @@ Item
 
     Action
     {
-        id: arrangeAllLockAction
-        text: catalog.i18nc("@action:inmenu menubar:edit","Arrange All Models Without Rotation")
+        id: arrangeAllGridAction
+        text: catalog.i18nc("@action:inmenu menubar:edit","Arrange All Models in a grid")
         onTriggered: Printer.arrangeAll(true)
         shortcut: "Shift+Ctrl+R"
     }

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

@@ -66,7 +66,7 @@ Cura.Menu
     Cura.MenuSeparator {}
     Cura.MenuItem { action: Cura.Actions.selectAll }
     Cura.MenuItem { action: Cura.Actions.arrangeAll }
-    Cura.MenuItem { action: Cura.Actions.arrangeAllLock }
+    Cura.MenuItem { action: Cura.Actions.arrangeAllGrid }
     Cura.MenuItem { action: Cura.Actions.deleteAll }
     Cura.MenuItem { action: Cura.Actions.reloadAll }
     Cura.MenuItem { action: Cura.Actions.resetAllTranslation }
@@ -110,7 +110,7 @@ Cura.Menu
         minimumWidth: UM.Theme.getSize("small_popup_dialog").width
         minimumHeight: UM.Theme.getSize("small_popup_dialog").height
 
-        onAccepted: CuraActions.multiplySelection(copiesField.value, lockRotationField.checked)
+        onAccepted: CuraActions.multiplySelection(copiesField.value, gridPlacementSelected.checked)
 
         buttonSpacing: UM.Theme.getSize("thin_margin").width
 
@@ -158,8 +158,8 @@ Cura.Menu
 
             UM.CheckBox
             {
-                id: lockRotationField
-                text: catalog.i18nc("@label", "Lock Rotation")
+                id: gridPlacementSelected
+                text: catalog.i18nc("@label", "Grid Placement")
             }
         }
     }