diff --git a/cura/MultiplyObjectsJob.py b/cura/MultiplyObjectsJob.py index b9f37ec6f8..3444da249f 100644 --- a/cura/MultiplyObjectsJob.py +++ b/cura/MultiplyObjectsJob.py @@ -32,14 +32,19 @@ class MultiplyObjectsJob(Job): root = scene.getRoot() arranger = Arrange.create(scene_root=root) + processed_nodes = [] nodes = [] for node in self._objects: # If object is part of a group, multiply group current_node = node - while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): + while current_node.getParent() and (current_node.getParent().callDecoration("isGroup") or current_node.getParent().callDecoration("isSliceable")): current_node = current_node.getParent() + if current_node in processed_nodes: + continue + processed_nodes.append(current_node) + node_too_big = False if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300: offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset) diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py index 48d271a2f2..428a59f554 100644 --- a/cura/Scene/CuraSceneNode.py +++ b/cura/Scene/CuraSceneNode.py @@ -103,6 +103,25 @@ class CuraSceneNode(SceneNode): return True return False + ## Override of SceneNode._calculateAABB to exclude non-printing-meshes from bounding box + def _calculateAABB(self): + aabb = None + if self._mesh_data: + aabb = self._mesh_data.getExtents(self.getWorldTransformation()) + else: # If there is no mesh_data, use a boundingbox that encompasses the local (0,0,0) + position = self.getWorldPosition() + aabb = AxisAlignedBox(minimum = position, maximum = position) + + for child in self._children: + if child.callDecoration("isNonPrintingMesh"): + # Non-printing-meshes inside a group should not affect push apart or drop to build plate + continue + if aabb is None: + aabb = child.getBoundingBox() + else: + aabb = aabb + child.getBoundingBox() + self._aabb = aabb + ## Taken from SceneNode, but replaced SceneNode with CuraSceneNode def __deepcopy__(self, memo): copy = CuraSceneNode(no_setting_override = True) # Setting override will be added later diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 7884ca30c7..06d9fc3707 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -19,8 +19,10 @@ 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 @@ -56,7 +58,7 @@ class SupportEraser(Tool): modifiers = QApplication.keyboardModifiers() ctrl_is_active = modifiers & Qt.ControlModifier - if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): + if event.type == Event.MousePressEvent and MouseEvent.LeftButton in event.buttons and self._controller.getToolsEnabled(): if ctrl_is_active: self._controller.setActiveTool("TranslateTool") return @@ -117,7 +119,10 @@ class SupportEraser(Tool): new_instance.resetState() # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) - op = AddSceneNodeOperation(node, parent) + op = GroupedOperation() + # First add node to the scene at the correct position/scale, before parenting, so the eraser mesh does not get scaled with the parent + op.addOperation(AddSceneNodeOperation(node, self._controller.getScene().getRoot())) + op.addOperation(SetParentOperation(node, parent)) op.push() node.setPosition(position, CuraSceneNode.TransformSpace.World)