diff options
author | Ghostkeeper <rubend@tutanota.com> | 2021-10-18 14:23:29 +0300 |
---|---|---|
committer | Ghostkeeper <rubend@tutanota.com> | 2021-10-18 14:23:29 +0300 |
commit | 0d350b5f96e614b1c2652ebe52941ef390a20ebf (patch) | |
tree | c25caf9ffdb3d761d9e907be38d6eb8a559a6951 /cura | |
parent | 5ed57e403c082d5d78c0f311c489b98368d974f6 (diff) | |
parent | 89c5a38afa10a2ebc8415f3d1a5c6daad5d1d8e8 (diff) |
Merge branch '4.12' into CURA-8609_sync_materials_to_printer
Diffstat (limited to 'cura')
-rw-r--r-- | cura/Arranging/Nest2DArrange.py | 42 | ||||
-rwxr-xr-x | cura/BuildVolume.py | 5 | ||||
-rwxr-xr-x | cura/CuraApplication.py | 4 | ||||
-rw-r--r-- | cura/Machines/Models/QualityProfilesDropDownMenuModel.py | 4 | ||||
-rw-r--r-- | cura/MultiplyObjectsJob.py | 39 |
5 files changed, 65 insertions, 29 deletions
diff --git a/cura/Arranging/Nest2DArrange.py b/cura/Arranging/Nest2DArrange.py index fdac63cd9d..ebe96202f2 100644 --- a/cura/Arranging/Nest2DArrange.py +++ b/cura/Arranging/Nest2DArrange.py @@ -110,18 +110,11 @@ def findNodePlacement(nodes_to_arrange: List["SceneNode"], build_volume: "BuildV return found_solution_for_all, node_items -def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fixed_nodes: Optional[List["SceneNode"]] = None, factor = 10000, add_new_nodes_in_scene: bool = False) -> bool: - """ - Find placement for a set of scene nodes, and move them by using a single grouped operation. - :param nodes_to_arrange: The list of nodes that need to be moved. - :param build_volume: The build volume that we want to place the nodes in. It gets size & disallowed areas from this. - :param fixed_nodes: List of nods that should not be moved, but should be used when deciding where the others nodes - are placed. - :param factor: The library that we use is int based. This factor defines how accuracte we want it to be. - :param add_new_nodes_in_scene: Whether to create new scene nodes before applying the transformations and rotations - - :return: found_solution_for_all: Whether the algorithm found a place on the buildplate for all the objects - """ +def createGroupOperationForArrange(nodes_to_arrange: List["SceneNode"], + build_volume: "BuildVolume", + fixed_nodes: Optional[List["SceneNode"]] = None, + factor = 10000, + add_new_nodes_in_scene: bool = False) -> Tuple[GroupedOperation, int]: scene_root = Application.getInstance().getController().getScene().getRoot() found_solution_for_all, node_items = findNodePlacement(nodes_to_arrange, build_volume, fixed_nodes, factor) @@ -143,6 +136,27 @@ def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fi grouped_operation.addOperation( TranslateOperation(node, Vector(200, node.getWorldPosition().y, -not_fit_count * 20), set_position = True)) not_fit_count += 1 - grouped_operation.push() - return found_solution_for_all + return grouped_operation, not_fit_count + + +def arrange(nodes_to_arrange: List["SceneNode"], + build_volume: "BuildVolume", + fixed_nodes: Optional[List["SceneNode"]] = None, + factor = 10000, + add_new_nodes_in_scene: bool = False) -> bool: + """ + Find placement for a set of scene nodes, and move them by using a single grouped operation. + :param nodes_to_arrange: The list of nodes that need to be moved. + :param build_volume: The build volume that we want to place the nodes in. It gets size & disallowed areas from this. + :param fixed_nodes: List of nods that should not be moved, but should be used when deciding where the others nodes + are placed. + :param factor: The library that we use is int based. This factor defines how accuracte we want it to be. + :param add_new_nodes_in_scene: Whether to create new scene nodes before applying the transformations and rotations + + :return: found_solution_for_all: Whether the algorithm found a place on the buildplate for all the objects + """ + + grouped_operation, not_fit_count = createGroupOperationForArrange(nodes_to_arrange, build_volume, fixed_nodes, factor, add_new_nodes_in_scene) + grouped_operation.push() + return not_fit_count != 0 diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index cf397e395e..e0c43c4876 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -1078,9 +1078,10 @@ class BuildVolume(SceneNode): # setting does *not* have a limit_to_extruder setting (which means that we can't ask the global extruder what # the value is. adhesion_extruder = self._global_container_stack.getProperty("adhesion_extruder_nr", "value") - skirt_brim_line_width = self._global_container_stack.extruderList[int(adhesion_extruder)].getProperty("skirt_brim_line_width", "value") + adhesion_stack = self._global_container_stack.extruderList[int(adhesion_extruder)] + skirt_brim_line_width = adhesion_stack.getProperty("skirt_brim_line_width", "value") - initial_layer_line_width_factor = self._global_container_stack.getProperty("initial_layer_line_width_factor", "value") + initial_layer_line_width_factor = adhesion_stack.getProperty("initial_layer_line_width_factor", "value") # Use brim width if brim is enabled OR the prime tower has a brim. if adhesion_type == "brim": brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value") diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 01ded93124..3d4ec1209f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -750,7 +750,9 @@ class CuraApplication(QtApplication): @pyqtSlot(str, result = QUrl) def getDefaultPath(self, key): default_path = self.getPreferences().getValue("local_file/%s" % key) - return QUrl.fromLocalFile(default_path) + if os.path.exists(default_path): + return QUrl.fromLocalFile(default_path) + return QUrl() @pyqtSlot(str, str) def setDefaultPath(self, key, default_path): diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 7aa30c6f82..f7316e9c09 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -41,10 +41,6 @@ class QualityProfilesDropDownMenuModel(ListModel): machine_manager.activeQualityGroupChanged.connect(self._onChange) machine_manager.activeMaterialChanged.connect(self._onChange) machine_manager.activeVariantChanged.connect(self._onChange) - machine_manager.extruderChanged.connect(self._onChange) - - extruder_manager = application.getExtruderManager() - extruder_manager.extrudersChanged.connect(self._onChange) self._layer_height_unit = "" # This is cached diff --git a/cura/MultiplyObjectsJob.py b/cura/MultiplyObjectsJob.py index 4c1caf137c..1446ae687e 100644 --- a/cura/MultiplyObjectsJob.py +++ b/cura/MultiplyObjectsJob.py @@ -6,11 +6,15 @@ from typing import List from UM.Application import Application from UM.Job import Job +from UM.Math.Vector import Vector from UM.Message import Message +from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation +from UM.Operations.GroupedOperation import GroupedOperation +from UM.Operations.TranslateOperation import TranslateOperation from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.i18n import i18nCatalog -from cura.Arranging.Nest2DArrange import arrange +from cura.Arranging.Nest2DArrange import arrange, createGroupOperationForArrange i18n_catalog = i18nCatalog("cura") @@ -43,11 +47,11 @@ class MultiplyObjectsJob(Job): # Only count sliceable objects if node_.callDecoration("isSliceable"): fixed_nodes.append(node_) - + nodes_to_add_without_arrange = [] 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") or current_node.getParent().callDecoration("isSliceable")): + while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): current_node = current_node.getParent() if current_node in processed_nodes: @@ -56,19 +60,38 @@ class MultiplyObjectsJob(Job): for _ in range(self._count): new_node = copy.deepcopy(node) - # Same build plate build_plate_number = current_node.callDecoration("getBuildPlateNumber") new_node.callDecoration("setBuildPlateNumber", build_plate_number) for child in new_node.getChildren(): child.callDecoration("setBuildPlateNumber", build_plate_number) - - nodes.append(new_node) + if not current_node.getParent().callDecoration("isSliceable"): + nodes.append(new_node) + else: + # The node we're trying to place has another node that is sliceable as a parent. + # As such, we shouldn't arrange it (but it should be added to the scene!) + nodes_to_add_without_arrange.append(new_node) + new_node.setParent(current_node.getParent()) found_solution_for_all = True + group_operation = GroupedOperation() if nodes: - found_solution_for_all = arrange(nodes, Application.getInstance().getBuildVolume(), fixed_nodes, - factor = 10000, add_new_nodes_in_scene = True) + group_operation, not_fit_count = createGroupOperationForArrange(nodes, + Application.getInstance().getBuildVolume(), + fixed_nodes, + factor = 10000, + add_new_nodes_in_scene = True) + found_solution_for_all = not_fit_count == 0 + + if nodes_to_add_without_arrange: + for nested_node in nodes_to_add_without_arrange: + group_operation.addOperation(AddSceneNodeOperation(nested_node, nested_node.getParent())) + # Move the node a tiny bit so it doesn't overlap with the existing one. + # This doesn't fix it if someone creates more than one duplicate, but it at least shows that something + # happened (and after moving it, it's clear that there are more underneath) + group_operation.addOperation(TranslateOperation(nested_node, Vector(2.5, 2.5, 2.5))) + + group_operation.push() status_message.hide() if not found_solution_for_all: |