Browse Source

Merge pull request #3524 from fieldOfView/fix_support_eraser_grouping

Fix support eraser grouping
Ian Paschal 7 years ago
parent
commit
19792fc1a6

+ 11 - 1
cura/CuraApplication.py

@@ -1105,7 +1105,7 @@ class CuraApplication(QtApplication):
                 continue
             if not node.getMeshData() and not node.callDecoration("isGroup"):
                 continue  # Node that doesnt have a mesh and is not a group.
-            if node.getParent() and node.getParent().callDecoration("isGroup"):
+            if node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent().callDecoration("isSliceable"):
                 continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
             if not node.isSelectable():
                 continue  # i.e. node with layer data
@@ -1383,6 +1383,12 @@ class CuraApplication(QtApplication):
         group_node.setPosition(center)
         group_node.setCenterPosition(center)
 
+        # Remove nodes that are directly parented to another selected node from the selection so they remain parented
+        selected_nodes = Selection.getAllSelectedObjects().copy()
+        for node in selected_nodes:
+            if node.getParent() in selected_nodes and not node.getParent().callDecoration("isGroup"):
+                Selection.remove(node)
+
         # Move selected nodes into the group-node
         Selection.applyOperation(SetParentOperation, group_node)
 
@@ -1401,6 +1407,10 @@ class CuraApplication(QtApplication):
                 group_parent = node.getParent()
                 children = node.getChildren().copy()
                 for child in children:
+                    # Ungroup only 1 level deep
+                    if child.getParent() != node:
+                        continue
+
                     # Set the parent of the children to the parent of the group-node
                     op.addOperation(SetParentOperation(child, group_parent))
 

+ 8 - 5
cura/MultiplyObjectsJob.py

@@ -33,6 +33,7 @@ class MultiplyObjectsJob(Job):
         root = scene.getRoot()
         arranger = Arrange.create(scene_root=root)
         nodes = []
+
         for node in self._objects:
             # If object is part of a group, multiply group
             current_node = node
@@ -49,18 +50,20 @@ class MultiplyObjectsJob(Job):
             for i in range(self._count):
                 # We do place the nodes one by one, as we want to yield in between.
                 if not node_too_big:
-                    node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
+                    new_node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
                 if node_too_big or not solution_found:
                     found_solution_for_all = False
-                    new_location = node.getPosition()
+                    new_location = new_node.getPosition()
                     new_location = new_location.set(z = 100 - i * 20)
-                    node.setPosition(new_location)
+                    new_node.setPosition(new_location)
 
                 # Same build plate
                 build_plate_number = current_node.callDecoration("getBuildPlateNumber")
-                node.callDecoration("setBuildPlateNumber", build_plate_number)
+                new_node.callDecoration("setBuildPlateNumber", build_plate_number)
+                for child in new_node.getChildren():
+                    child.callDecoration("setBuildPlateNumber", build_plate_number)
 
-                nodes.append(node)
+                nodes.append(new_node)
                 current_progress += 1
                 status_message.setProgress((current_progress / total_progress) * 100)
                 Job.yieldThread()

+ 1 - 1
cura/Scene/BuildPlateDecorator.py

@@ -15,7 +15,7 @@ class BuildPlateDecorator(SceneNodeDecorator):
         self._build_plate_number = nr
         if isinstance(self._node, CuraSceneNode):
             self._node.transformChanged()  # trigger refresh node without introducing a new signal
-        if self._node and self._node.callDecoration("isGroup"):
+        if self._node:
             for child in self._node.getChildren():
                 child.callDecoration("setBuildPlateNumber", nr)
 

+ 2 - 5
plugins/3MFReader/ThreeMFReader.py

@@ -16,7 +16,6 @@ from UM.Mesh.MeshBuilder import MeshBuilder
 from UM.Mesh.MeshReader import MeshReader
 from UM.Scene.GroupDecorator import GroupDecorator
 
-from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
 from cura.Settings.ExtruderManager import ExtruderManager
 from cura.Scene.CuraSceneNode import CuraSceneNode
 from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
@@ -81,7 +80,7 @@ class ThreeMFReader(MeshReader):
 
         active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
 
-        um_node = CuraSceneNode()
+        um_node = CuraSceneNode() # This adds a SettingOverrideDecorator
         um_node.addDecorator(BuildPlateDecorator(active_build_plate))
         um_node.setName(node_name)
         transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
@@ -110,8 +109,6 @@ class ThreeMFReader(MeshReader):
 
         # Add the setting override decorator, so we can add settings to this node.
         if settings:
-            um_node.addDecorator(SettingOverrideDecorator())
-
             global_container_stack = Application.getInstance().getGlobalContainerStack()
 
             # Ensure the correct next container for the SettingOverride decorator is set.
@@ -140,7 +137,7 @@ class ThreeMFReader(MeshReader):
                     continue
                 setting_container.setProperty(key, "value", setting_value)
 
-        if len(um_node.getChildren()) > 0:
+        if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None:
             group_decorator = GroupDecorator()
             um_node.addDecorator(group_decorator)
         um_node.setSelectable(True)

+ 3 - 12
plugins/SupportEraser/SupportEraser.py

@@ -19,10 +19,8 @@ from cura.Scene.CuraSceneNode import CuraSceneNode
 
 from cura.PickingPass import PickingPass
 
-from UM.Operations.GroupedOperation import GroupedOperation
 from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
 from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
-from cura.Operations.SetParentOperation import SetParentOperation
 
 from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
 from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
@@ -105,15 +103,12 @@ class SupportEraser(Tool):
         mesh = MeshBuilder()
         mesh.addCube(10,10,10)
         node.setMeshData(mesh.build())
-        node.setPosition(position)
 
         active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
-
-        node.addDecorator(SettingOverrideDecorator())
         node.addDecorator(BuildPlateDecorator(active_build_plate))
         node.addDecorator(SliceableObjectDecorator())
 
-        stack = node.callDecoration("getStack") # created by SettingOverrideDecorator
+        stack = node.callDecoration("getStack") # created by SettingOverrideDecorator that is automatically added to CuraSceneNode
         settings = stack.getTop()
 
         definition = stack.getSettingDefinition("anti_overhang_mesh")
@@ -122,13 +117,9 @@ class SupportEraser(Tool):
         new_instance.resetState()  # Ensure that the state is not seen as a user state.
         settings.addInstance(new_instance)
 
-        root = self._controller.getScene().getRoot()
-
-        op = GroupedOperation()
-        # First add the node to the scene, so it gets the expected transform
-        op.addOperation(AddSceneNodeOperation(node, root))
-        op.addOperation(SetParentOperation(node, parent))
+        op = AddSceneNodeOperation(node, parent)
         op.push()
+        node.setPosition(position, CuraSceneNode.TransformSpace.World)
 
         Application.getInstance().getController().getScene().sceneChanged.emit(node)