From eecdceffdbfd20cf15a8fe6c4c66870cb75686ee Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 28 Aug 2023 15:42:04 +0200 Subject: [PATCH] Fix available height when adding modifier mesh in One at a Time printing Cura lowers the available build volume height when more than 1 model is loaded. This count should include grouped nodes as one (since they will be slice as one and thus not affect the gantry), and should not include modifier meshes or support meshes (since support-meshes are always printed with the first model anyway). Fixes https://github.com/Ultimaker/Cura/issues/16566 --- cura/BuildVolume.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 0d6ecf5810..5b4e00e8d6 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -120,6 +120,8 @@ class BuildVolume(SceneNode): # Objects loaded at the moment. We are connected to the property changed events of these objects. self._scene_objects = set() # type: Set[SceneNode] + # Number of toplevel printable meshes. If there is more than one, the build volume needs to take account of the gantry height in One at a Time printing. + self._root_printable_object_count = 0 self._scene_change_timer = QTimer() self._scene_change_timer.setInterval(200) @@ -151,6 +153,7 @@ class BuildVolume(SceneNode): def _onSceneChangeTimerFinished(self): root = self._application.getController().getScene().getRoot() new_scene_objects = set(node for node in BreadthFirstIterator(root) if node.callDecoration("isSliceable")) + if new_scene_objects != self._scene_objects: for node in new_scene_objects - self._scene_objects: #Nodes that were added to the scene. self._updateNodeListeners(node) @@ -166,6 +169,26 @@ class BuildVolume(SceneNode): self.rebuild() self._scene_objects = new_scene_objects + + # This also needs to be called when objects are grouped/ungrouped, + # which is not reflected in a change in self._scene_objects + self._updateRootPrintableObjectCount() + + def _updateRootPrintableObjectCount(self): + # Get the number of models in the scene root, excluding modifier meshes and counting grouped models as 1 + root = self._application.getController().getScene().getRoot() + scene_objects = set(node for node in BreadthFirstIterator(root) if node.callDecoration("isSliceable") or node.callDecoration("isGroup")) + + new_root_printable_object_count = len(list(node for node in scene_objects if node.getParent() == root and not ( + node_stack := node.callDecoration("getStack") and ( + node.callDecoration("getStack").getProperty("anti_overhang_mesh", "value") or + node.callDecoration("getStack").getProperty("support_mesh", "value") or + node.callDecoration("getStack").getProperty("cutting_mesh", "value") or + node.callDecoration("getStack").getProperty("infill_mesh", "value") + )) + )) + if new_root_printable_object_count != self._root_printable_object_count: + self._root_printable_object_count = new_root_printable_object_count self._onSettingPropertyChanged("print_sequence", "value") # Create fake event, so right settings are triggered. def _updateNodeListeners(self, node: SceneNode): @@ -647,7 +670,7 @@ class BuildVolume(SceneNode): self._width = self._global_container_stack.getProperty("machine_width", "value") machine_height = self._global_container_stack.getProperty("machine_height", "value") - if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: + if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and self._root_printable_object_count > 1: new_height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height) if self._height > new_height: @@ -689,9 +712,12 @@ class BuildVolume(SceneNode): update_extra_z_clearance = True for setting_key in self._changed_settings_since_last_rebuild: + if setting_key in ["print_sequence", "support_mesh", "infill_mesh", "cutting_mesh", "anti_overhang_mesh"]: + self._updateRootPrintableObjectCount() + if setting_key == "print_sequence": machine_height = self._global_container_stack.getProperty("machine_height", "value") - if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: + if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and self._root_printable_object_count > 1: new_height = min( self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height)