From 2b05a370ca7afca70276b28958ac87a60f3d149a Mon Sep 17 00:00:00 2001 From: alexandr-vladimirov Date: Thu, 4 Jan 2024 06:30:23 +0300 Subject: [PATCH 01/46] Allow to set print sequence manually --- conandata.yml | 8 + cura/CuraApplication.py | 26 ++- cura/HitChecker.py | 88 ++++++++++ cura/OneAtATimeIterator.py | 113 ++++--------- cura/PrintOrderManager.py | 171 +++++++++++++++++++ cura/Scene/CuraSceneNode.py | 12 ++ cura/UI/ObjectsModel.py | 19 ++- plugins/3MFReader/ThreeMFReader.py | 3 + plugins/3MFWriter/ThreeMFWriter.py | 4 + resources/definitions/fdmprinter.def.json | 10 ++ resources/i18n/cs_CZ/cura.po | 8 + resources/i18n/cs_CZ/fdmprinter.def.json.po | 8 + resources/i18n/cura.pot | 8 + resources/i18n/de_DE/cura.po | 8 + resources/i18n/de_DE/fdmprinter.def.json.po | 8 + resources/i18n/es_ES/cura.po | 8 + resources/i18n/es_ES/fdmprinter.def.json.po | 8 + resources/i18n/fdmprinter.def.json.pot | 8 + resources/i18n/fi_FI/cura.po | 8 + resources/i18n/fi_FI/fdmprinter.def.json.po | 8 + resources/i18n/fr_FR/cura.po | 8 + resources/i18n/fr_FR/fdmprinter.def.json.po | 8 + resources/i18n/hu_HU/cura.po | 8 + resources/i18n/hu_HU/fdmprinter.def.json.po | 8 + resources/i18n/it_IT/cura.po | 8 + resources/i18n/it_IT/fdmprinter.def.json.po | 8 + resources/i18n/ja_JP/cura.po | 8 + resources/i18n/ja_JP/fdmprinter.def.json.po | 8 + resources/i18n/ko_KR/cura.po | 8 + resources/i18n/ko_KR/fdmprinter.def.json.po | 8 + resources/i18n/nl_NL/cura.po | 8 + resources/i18n/nl_NL/fdmprinter.def.json.po | 8 + resources/i18n/pl_PL/cura.po | 8 + resources/i18n/pl_PL/fdmprinter.def.json.po | 8 + resources/i18n/pt_BR/cura.po | 8 + resources/i18n/pt_BR/fdmprinter.def.json.po | 8 + resources/i18n/pt_PT/cura.po | 8 + resources/i18n/pt_PT/fdmprinter.def.json.po | 8 + resources/i18n/ru_RU/cura.po | 8 + resources/i18n/ru_RU/fdmprinter.def.json.po | 8 + resources/i18n/tr_TR/cura.po | 8 + resources/i18n/tr_TR/fdmprinter.def.json.po | 8 + resources/i18n/zh_CN/cura.po | 8 + resources/i18n/zh_CN/fdmprinter.def.json.po | 8 + resources/i18n/zh_TW/cura.po | 8 + resources/i18n/zh_TW/fdmprinter.def.json.po | 8 + resources/qml/Actions.qml | 23 +++ resources/qml/Menus/ContextMenu.qml | 13 ++ resources/qml/Menus/EditMenu.qml | 13 ++ resources/setting_visibility/advanced.cfg | 1 + resources/setting_visibility/expert.cfg | 1 + tests/TestHitChecker.py | 141 ++++++++++++++++ tests/TestPrintOrderManager.py | 175 ++++++++++++++++++++ 53 files changed, 1021 insertions(+), 88 deletions(-) create mode 100644 cura/HitChecker.py create mode 100644 cura/PrintOrderManager.py create mode 100644 tests/TestHitChecker.py create mode 100644 tests/TestPrintOrderManager.py diff --git a/conandata.yml b/conandata.yml index a0a5a204ca..c1dad5057d 100644 --- a/conandata.yml +++ b/conandata.yml @@ -161,6 +161,10 @@ pycharm_targets: module_name: Cura name: pytest in TestGCodeListDecorator.py script_name: tests/TestGCodeListDecorator.py + - jinja_path: .run_templates/pycharm_cura_test.run.xml.jinja + module_name: Cura + name: pytest in TestHitChecker.py + script_name: tests/TestHitChecker.py - jinja_path: .run_templates/pycharm_cura_test.run.xml.jinja module_name: Cura name: pytest in TestIntentManager.py @@ -189,6 +193,10 @@ pycharm_targets: module_name: Cura name: pytest in TestPrintInformation.py script_name: tests/TestPrintInformation.py + - jinja_path: .run_templates/pycharm_cura_test.run.xml.jinja + module_name: Cura + name: pytest in TestPrintOrderManager.py + script_name: tests/TestPrintOrderManager.py - jinja_path: .run_templates/pycharm_cura_test.run.xml.jinja module_name: Cura name: pytest in TestProfileRequirements.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1ef2f63a9e..387adda5cb 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -125,6 +125,7 @@ from .Machines.Models.CompatibleMachineModel import CompatibleMachineModel from .Machines.Models.MachineListModel import MachineListModel from .Machines.Models.ActiveIntentQualitiesModel import ActiveIntentQualitiesModel from .Machines.Models.IntentSelectionModel import IntentSelectionModel +from .PrintOrderManager import PrintOrderManager from .SingleInstance import SingleInstance if TYPE_CHECKING: @@ -202,6 +203,7 @@ class CuraApplication(QtApplication): self._container_manager = None self._object_manager = None + self._print_order_manager = None self._extruders_model = None self._extruders_model_with_optional = None self._build_plate_model = None @@ -899,6 +901,7 @@ class CuraApplication(QtApplication): # initialize info objects self._print_information = PrintInformation.PrintInformation(self) self._cura_actions = CuraActions.CuraActions(self) + self._print_order_manager = PrintOrderManager(self.getObjectsModel().getNodes) self.processEvents() # Initialize setting visibility presets model. self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self.getPreferences(), parent = self) @@ -979,6 +982,7 @@ class CuraApplication(QtApplication): t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.YAxis, ToolHandle.ZAxis]) Selection.selectionChanged.connect(self.onSelectionChanged) + self._print_order_manager.printOrderChanged.connect(self._onPrintOrderChanged) # Set default background color for scene self.getRenderer().setBackgroundColor(QColor(245, 245, 245)) @@ -1218,6 +1222,7 @@ class CuraApplication(QtApplication): self.processEvents() engine.rootContext().setContextProperty("Printer", self) engine.rootContext().setContextProperty("CuraApplication", self) + engine.rootContext().setContextProperty("PrintOrderManager", self._print_order_manager) engine.rootContext().setContextProperty("PrintInformation", self._print_information) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) engine.rootContext().setContextProperty("CuraSDKVersion", ApplicationMetadata.CuraSDKVersion) @@ -1715,8 +1720,12 @@ class CuraApplication(QtApplication): Selection.remove(node) Selection.add(group_node) + all_nodes = self.getObjectsModel().getNodes() + PrintOrderManager.updatePrintOrdersAfterGroupOperation(all_nodes, group_node, selected_nodes) + @pyqtSlot() def ungroupSelected(self) -> None: + all_nodes = self.getObjectsModel().getNodes() selected_objects = Selection.getAllSelectedObjects().copy() for node in selected_objects: if node.callDecoration("isGroup"): @@ -1724,21 +1733,30 @@ 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 + # Ungroup only 1 level deep + children_to_ungroup = list(filter(lambda child: child.getParent() == node, children)) + for child in children_to_ungroup: # Set the parent of the children to the parent of the group-node op.addOperation(SetParentOperation(child, group_parent)) # Add all individual nodes to the selection Selection.add(child) + PrintOrderManager.updatePrintOrdersAfterUngroupOperation(all_nodes, node, children_to_ungroup) op.push() # Note: The group removes itself from the scene once all its children have left it, # see GroupDecorator._onChildrenChanged + def _onPrintOrderChanged(self) -> None: + # update object list + scene = self.getController().getScene() + scene.sceneChanged.emit(scene.getRoot()) + + # reset if already was sliced + Application.getInstance().getBackend().needsSlicing() + Application.getInstance().getBackend().tickle() + def _createSplashScreen(self) -> Optional[CuraSplashScreen.CuraSplashScreen]: if self._is_headless: return None diff --git a/cura/HitChecker.py b/cura/HitChecker.py new file mode 100644 index 0000000000..4b229e6b9b --- /dev/null +++ b/cura/HitChecker.py @@ -0,0 +1,88 @@ +from typing import List, Dict +from cura.Scene.CuraSceneNode import CuraSceneNode + + +class HitChecker: + """Checks if nodes can be printed without causing any collisions and interference""" + + def __init__(self, nodes: List[CuraSceneNode]) -> None: + self._hit_map = self._buildHitMap(nodes) + + def anyTwoNodesBlockEachOther(self, nodes: List[CuraSceneNode]) -> bool: + """Returns True if any 2 nodes block each other""" + for a in nodes: + for b in nodes: + if self._hit_map[a][b] and self._hit_map[b][a]: + return True + return False + + def canPrintBefore(self, node: CuraSceneNode, other_nodes: List[CuraSceneNode]) -> bool: + """Returns True if node doesn't block other_nodes and can be printed before them""" + no_hits = all(not self._hit_map[node][other_node] for other_node in other_nodes) + return no_hits + + def canPrintAfter(self, node: CuraSceneNode, other_nodes: List[CuraSceneNode]) -> bool: + """Returns True if node doesn't hit other nodes and can be printed after them""" + no_hits = all(not self._hit_map[other_node][node] for other_node in other_nodes) + return no_hits + + def calculateScore(self, a: CuraSceneNode, b: CuraSceneNode) -> int: + """Calculate score simply sums the number of other objects it 'blocks' + + :param a: node + :param b: node + :return: sum of the number of other objects + """ + + score_a = sum(self._hit_map[a].values()) + score_b = sum(self._hit_map[b].values()) + return score_a - score_b + + def canPrintNodesInProvidedOrder(self, ordered_nodes: List[CuraSceneNode]) -> bool: + """Returns True If nodes don't have any hits in provided order""" + for node_index, node in enumerate(ordered_nodes): + nodes_before = ordered_nodes[:node_index - 1] if node_index - 1 >= 0 else [] + nodes_after = ordered_nodes[node_index + 1:] if node_index + 1 < len(ordered_nodes) else [] + if not self.canPrintBefore(node, nodes_after) or not self.canPrintAfter(node, nodes_before): + return False + return True + + @staticmethod + def _buildHitMap(nodes: List[CuraSceneNode]) -> Dict[CuraSceneNode, CuraSceneNode]: + """Pre-computes all hits between all objects + + :nodes: nodes that need to be checked for collisions + :return: dictionary where hit_map[node1][node2] is False if there node1 can be printed before node2 + """ + hit_map = {j: {i: HitChecker._checkHit(j, i) for i in nodes} for j in nodes} + return hit_map + + @staticmethod + def _checkHit(a: CuraSceneNode, b: CuraSceneNode) -> bool: + """Checks if a can be printed before b + + :param a: node + :param b: node + :return: False if a can be printed before b + """ + + if a == b: + return False + + a_hit_hull = a.callDecoration("getConvexHullBoundary") + b_hit_hull = b.callDecoration("getConvexHullHeadFull") + overlap = a_hit_hull.intersectsPolygon(b_hit_hull) + + if overlap: + return True + + # Adhesion areas must never overlap, regardless of printing order + # This would cause over-extrusion + a_hit_hull = a.callDecoration("getAdhesionArea") + b_hit_hull = b.callDecoration("getAdhesionArea") + overlap = a_hit_hull.intersectsPolygon(b_hit_hull) + + if overlap: + return True + else: + return False diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 8bdddba554..f92da3ec14 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -7,6 +7,11 @@ from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode from functools import cmp_to_key +from cura.HitChecker import HitChecker +from cura.PrintOrderManager import PrintOrderManager +from cura.Scene.CuraSceneNode import CuraSceneNode + + class OneAtATimeIterator(Iterator.Iterator): """Iterator that returns a list of nodes in the order that they need to be printed @@ -16,8 +21,6 @@ class OneAtATimeIterator(Iterator.Iterator): def __init__(self, scene_node) -> None: super().__init__(scene_node) # Call super to make multiple inheritance work. - self._hit_map = [[]] # type: List[List[bool]] # For each node, which other nodes this hits. A grid of booleans on which nodes hit which. - self._original_node_list = [] # type: List[SceneNode] # The nodes that need to be checked for collisions. def _fillStack(self) -> None: """Fills the ``_node_stack`` with a list of scene nodes that need to be printed in order. """ @@ -38,104 +41,50 @@ class OneAtATimeIterator(Iterator.Iterator): self._node_stack = node_list[:] return - # Copy the list - self._original_node_list = node_list[:] + hit_checker = HitChecker(node_list) - # Initialise the hit map (pre-compute all hits between all objects) - self._hit_map = [[self._checkHit(i, j) for i in node_list] for j in node_list] + if PrintOrderManager.isUserDefinedPrintOrderEnabled(): + self._node_stack = self._getNodesOrderedByUser(hit_checker, node_list) + else: + self._node_stack = self._getNodesOrderedAutomatically(hit_checker, node_list) - # Check if we have to files that block each other. If this is the case, there is no solution! - for a in range(0, len(node_list)): - for b in range(0, len(node_list)): - if a != b and self._hit_map[a][b] and self._hit_map[b][a]: - return + # update print orders so that user can try to arrange the nodes automatically first + # and if result is not satisfactory he/she can switch to manual mode and change it + for index, node in enumerate(self._node_stack): + node.printOrder = index + 1 + + @staticmethod + def _getNodesOrderedByUser(hit_checker: HitChecker, node_list: List[CuraSceneNode]) -> List[CuraSceneNode]: + nodes_ordered_by_user = sorted(node_list, key=lambda n: n.printOrder) + if hit_checker.canPrintNodesInProvidedOrder(nodes_ordered_by_user): + return nodes_ordered_by_user + return [] # No solution + + @staticmethod + def _getNodesOrderedAutomatically(hit_checker: HitChecker, node_list: List[CuraSceneNode]) -> List[CuraSceneNode]: + # Check if we have two files that block each other. If this is the case, there is no solution! + if hit_checker.anyTwoNodesBlockEachOther(node_list): + return [] # No solution # Sort the original list so that items that block the most other objects are at the beginning. # This does not decrease the worst case running time, but should improve it in most cases. - sorted(node_list, key = cmp_to_key(self._calculateScore)) + sorted(node_list, key = cmp_to_key(hit_checker.calculateScore)) todo_node_list = [_ObjectOrder([], node_list)] while len(todo_node_list) > 0: current = todo_node_list.pop() for node in current.todo: # Check if the object can be placed with what we have and still allows for a solution in the future - if not self._checkHitMultiple(node, current.order) and not self._checkBlockMultiple(node, current.todo): + if hit_checker.canPrintAfter(node, current.order) and hit_checker.canPrintBefore(node, current.todo): # We found a possible result. Create new todo & order list. new_todo_list = current.todo[:] new_todo_list.remove(node) new_order = current.order[:] + [node] if len(new_todo_list) == 0: # We have no more nodes to check, so quit looking. - self._node_stack = new_order - return + return new_order # Solution found! todo_node_list.append(_ObjectOrder(new_order, new_todo_list)) - self._node_stack = [] #No result found! - - - # Check if first object can be printed before the provided list (using the hit map) - def _checkHitMultiple(self, node: SceneNode, other_nodes: List[SceneNode]) -> bool: - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[node_index][other_node_index]: - return True - return False - - def _checkBlockMultiple(self, node: SceneNode, other_nodes: List[SceneNode]) -> bool: - """Check for a node whether it hits any of the other nodes. - - :param node: The node to check whether it collides with the other nodes. - :param other_nodes: The nodes to check for collisions. - :return: returns collision between nodes - """ - - node_index = self._original_node_list.index(node) - for other_node in other_nodes: - other_node_index = self._original_node_list.index(other_node) - if self._hit_map[other_node_index][node_index] and node_index != other_node_index: - return True - return False - - def _calculateScore(self, a: SceneNode, b: SceneNode) -> int: - """Calculate score simply sums the number of other objects it 'blocks' - - :param a: node - :param b: node - :return: sum of the number of other objects - """ - - score_a = sum(self._hit_map[self._original_node_list.index(a)]) - score_b = sum(self._hit_map[self._original_node_list.index(b)]) - return score_a - score_b - - def _checkHit(self, a: SceneNode, b: SceneNode) -> bool: - """Checks if a can be printed before b - - :param a: node - :param b: node - :return: true if a can be printed before b - """ - - if a == b: - return False - - a_hit_hull = a.callDecoration("getConvexHullBoundary") - b_hit_hull = b.callDecoration("getConvexHullHeadFull") - overlap = a_hit_hull.intersectsPolygon(b_hit_hull) - - if overlap: - return True - - # Adhesion areas must never overlap, regardless of printing order - # This would cause over-extrusion - a_hit_hull = a.callDecoration("getAdhesionArea") - b_hit_hull = b.callDecoration("getAdhesionArea") - overlap = a_hit_hull.intersectsPolygon(b_hit_hull) - - if overlap: - return True - else: - return False + return [] # No result found! class _ObjectOrder: diff --git a/cura/PrintOrderManager.py b/cura/PrintOrderManager.py new file mode 100644 index 0000000000..abfa5442a2 --- /dev/null +++ b/cura/PrintOrderManager.py @@ -0,0 +1,171 @@ +from typing import List, Callable, Optional, Any + +from PyQt6.QtCore import pyqtProperty, pyqtSignal, QObject, pyqtSlot +from UM.Application import Application +from UM.Scene.Selection import Selection + +from cura.Scene.CuraSceneNode import CuraSceneNode + + +class PrintOrderManager(QObject): + """Allows to order the object list to set the print sequence manually""" + + def __init__(self, get_nodes: Callable[[], List[CuraSceneNode]]) -> None: + super().__init__() + self._get_nodes = get_nodes + self._configureEvents() + + _settingsChanged = pyqtSignal() + _uiActionsOutdated = pyqtSignal() + printOrderChanged = pyqtSignal() + + @pyqtSlot() + def swapSelectedAndPreviousNodes(self) -> None: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + self._swapPrintOrders(selected_node, previous_node) + + @pyqtSlot() + def swapSelectedAndNextNodes(self) -> None: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + self._swapPrintOrders(selected_node, next_node) + + @pyqtProperty(str, notify=_uiActionsOutdated) + def previousNodeName(self) -> str: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + return self._getNodeName(previous_node) + + @pyqtProperty(str, notify=_uiActionsOutdated) + def nextNodeName(self) -> str: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + return self._getNodeName(next_node) + + @pyqtProperty(bool, notify=_uiActionsOutdated) + def shouldEnablePrintBeforeAction(self) -> bool: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + can_swap_with_previous_node = selected_node is not None and previous_node is not None + return can_swap_with_previous_node + + @pyqtProperty(bool, notify=_uiActionsOutdated) + def shouldEnablePrintAfterAction(self) -> bool: + selected_node, previous_node, next_node = self._getSelectedAndNeighborNodes() + can_swap_with_next_node = selected_node is not None and next_node is not None + return can_swap_with_next_node + + @pyqtProperty(bool, notify=_settingsChanged) + def shouldShowEditPrintOrderActions(self) -> bool: + return PrintOrderManager.isUserDefinedPrintOrderEnabled() + + @staticmethod + def isUserDefinedPrintOrderEnabled() -> bool: + stack = Application.getInstance().getGlobalContainerStack() + is_enabled = stack and \ + stack.getProperty("print_sequence", "value") == "one_at_a_time" and \ + stack.getProperty("user_defined_print_order_enabled", "value") + return is_enabled + + @staticmethod + def initializePrintOrders(nodes: List[CuraSceneNode]) -> None: + """Just created (loaded from file) nodes have print order 0. + + This method initializes print orders with max value to put nodes at the end of object list""" + max_print_order = max(map(lambda n: n.printOrder, nodes), default=0) + for node in nodes: + if node.printOrder == 0: + max_print_order += 1 + node.printOrder = max_print_order + + @staticmethod + def updatePrintOrdersAfterGroupOperation( + all_nodes: List[CuraSceneNode], + group_node: CuraSceneNode, + grouped_nodes: List[CuraSceneNode] + ) -> None: + group_node.printOrder = min(map(lambda n: n.printOrder, grouped_nodes)) + + all_nodes.append(group_node) + for node in grouped_nodes: + all_nodes.remove(node) + + # reassign print orders so there won't be gaps like 1 2 5 6 7 + sorted_nodes = sorted(all_nodes, key=lambda n: n.printOrder) + for i, node in enumerate(sorted_nodes): + node.printOrder = i + 1 + + @staticmethod + def updatePrintOrdersAfterUngroupOperation( + all_nodes: List[CuraSceneNode], + group_node: CuraSceneNode, + ungrouped_nodes: List[CuraSceneNode] + ) -> None: + all_nodes.remove(group_node) + nodes_to_update_print_order = filter(lambda n: n.printOrder > group_node.printOrder, all_nodes) + for node in nodes_to_update_print_order: + node.printOrder += len(ungrouped_nodes) - 1 + + for i, child in enumerate(ungrouped_nodes): + child.printOrder = group_node.printOrder + i + all_nodes.append(child) + + def _swapPrintOrders(self, node1: CuraSceneNode, node2: CuraSceneNode) -> None: + if node1 and node2: + node1.printOrder, node2.printOrder = node2.printOrder, node1.printOrder # swap print orders + self.printOrderChanged.emit() # update object list first + self._uiActionsOutdated.emit() # then update UI actions + + def _getSelectedAndNeighborNodes(self + ) -> (Optional[CuraSceneNode], Optional[CuraSceneNode], Optional[CuraSceneNode]): + nodes = self._get_nodes() + ordered_nodes = sorted(nodes, key=lambda n: n.printOrder) + selected_node = PrintOrderManager._getSingleSelectedNode() + if selected_node and selected_node in ordered_nodes: + selected_node_index = ordered_nodes.index(selected_node) + else: + selected_node_index = None + + if selected_node_index is not None and selected_node_index - 1 >= 0: + previous_node = ordered_nodes[selected_node_index - 1] + else: + previous_node = None + + if selected_node_index is not None and selected_node_index + 1 < len(ordered_nodes): + next_node = ordered_nodes[selected_node_index + 1] + else: + next_node = None + + return selected_node, previous_node, next_node + + @staticmethod + def _getNodeName(node: CuraSceneNode, max_length: int = 30) -> str: + node_name = node.getName() if node else "" + truncated_node_name = node_name[:max_length] + return truncated_node_name + + @staticmethod + def _getSingleSelectedNode() -> Optional[CuraSceneNode]: + if len(Selection.getAllSelectedObjects()) == 1: + selected_node = Selection.getSelectedObject(0) + return selected_node + return None + + def _configureEvents(self) -> None: + Selection.selectionChanged.connect(self._onSelectionChanged) + self._global_stack = None + Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) + self._onGlobalStackChanged() + + def _onGlobalStackChanged(self) -> None: + if self._global_stack: + self._global_stack.propertyChanged.disconnect(self._onSettingsChanged) + self._global_stack.containersChanged.disconnect(self._onSettingsChanged) + + self._global_stack = Application.getInstance().getGlobalContainerStack() + + if self._global_stack: + self._global_stack.propertyChanged.connect(self._onSettingsChanged) + self._global_stack.containersChanged.connect(self._onSettingsChanged) + + def _onSettingsChanged(self, *args: Any) -> None: + self._settingsChanged.emit() + + def _onSelectionChanged(self) -> None: + self._uiActionsOutdated.emit() diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py index 5fbaded650..9b412c7d4f 100644 --- a/cura/Scene/CuraSceneNode.py +++ b/cura/Scene/CuraSceneNode.py @@ -25,10 +25,19 @@ class CuraSceneNode(SceneNode): if not no_setting_override: self.addDecorator(SettingOverrideDecorator()) # Now we always have a getActiveExtruderPosition, unless explicitly disabled self._outside_buildarea = False + self._print_order = 0 def setOutsideBuildArea(self, new_value: bool) -> None: self._outside_buildarea = new_value + @property + def printOrder(self): + return self._print_order + + @printOrder.setter + def printOrder(self, new_value): + self._print_order = new_value + def isOutsideBuildArea(self) -> bool: return self._outside_buildarea or self.callDecoration("getBuildPlateNumber") < 0 @@ -157,3 +166,6 @@ class CuraSceneNode(SceneNode): def transformChanged(self) -> None: self._transformChanged() + + def __repr__(self) -> str: + return "{print_order}. {name}".format(print_order = self._print_order, name = self.getName()) diff --git a/cura/UI/ObjectsModel.py b/cura/UI/ObjectsModel.py index 4f64270247..4d5a4dfc81 100644 --- a/cura/UI/ObjectsModel.py +++ b/cura/UI/ObjectsModel.py @@ -14,6 +14,9 @@ from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.i18n import i18nCatalog +from cura.PrintOrderManager import PrintOrderManager +from cura.Scene.CuraSceneNode import CuraSceneNode + catalog = i18nCatalog("cura") @@ -76,6 +79,9 @@ class ObjectsModel(ListModel): self._build_plate_number = nr self._update() + def getNodes(self) -> List[CuraSceneNode]: + return list(map(lambda n: n["node"], self.items)) + def _updateSceneDelayed(self, source) -> None: if not isinstance(source, Camera): self._update_timer.start() @@ -175,6 +181,10 @@ class ObjectsModel(ListModel): all_nodes = self._renameNodes(name_to_node_info_dict) + user_defined_print_order_enabled = PrintOrderManager.isUserDefinedPrintOrderEnabled() + if user_defined_print_order_enabled: + PrintOrderManager.initializePrintOrders(all_nodes) + for node in all_nodes: if hasattr(node, "isOutsideBuildArea"): is_outside_build_area = node.isOutsideBuildArea() # type: ignore @@ -223,8 +233,13 @@ class ObjectsModel(ListModel): # for anti overhang meshes and groups the extruder nr is irrelevant extruder_number = -1 + if not user_defined_print_order_enabled: + name = node.getName() + else: + name = "{print_order}. {name}".format(print_order = node.printOrder, name = node.getName()) + nodes.append({ - "name": node.getName(), + "name": name, "selected": Selection.isSelected(node), "outside_build_area": is_outside_build_area, "buildplate_number": node_build_plate_number, @@ -234,5 +249,5 @@ class ObjectsModel(ListModel): "node": node }) - nodes = sorted(nodes, key=lambda n: n["name"]) + nodes = sorted(nodes, key=lambda n: n["name"] if not user_defined_print_order_enabled else n["node"].printOrder) self.setItems(nodes) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 13a97d5a89..85bdbfa551 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -177,6 +177,9 @@ class ThreeMFReader(MeshReader): else: Logger.log("w", "Unable to find extruder in position %s", setting_value) continue + if key == "print_order": + um_node.printOrder = int(setting_value) + continue if key in known_setting_keys: setting_container.setProperty(key, "value", setting_value) else: diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index ad4b0d8dad..5ffd99a1c4 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -20,6 +20,7 @@ from cura.CuraApplication import CuraApplication from cura.CuraPackageManager import CuraPackageManager from cura.Settings import CuraContainerStack from cura.Utils.Threading import call_on_qt_thread +from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Snapshot import Snapshot from PyQt6.QtCore import QBuffer @@ -137,6 +138,9 @@ class ThreeMFWriter(MeshWriter): for key in changed_setting_keys: savitar_node.setSetting("cura:" + key, str(stack.getProperty(key, "value"))) + if isinstance(um_node, CuraSceneNode): + savitar_node.setSetting("cura:print_order", str(um_node.printOrder)) + # Store the metadata. for key, value in um_node.metadata.items(): savitar_node.setSetting(key, value) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 62143cf8f8..160c1d905d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -7060,6 +7060,16 @@ "settable_per_extruder": false, "settable_per_meshgroup": false }, + "user_defined_print_order_enabled": + { + "label": "Set Print Sequence Manually", + "description": "Allows to order the object list to set the print sequence manually. First object from the list will be printed first.", + "type": "bool", + "default_value": false, + "settable_per_mesh": false, + "settable_per_extruder": false, + "enabled": "print_sequence == 'one_at_a_time'" + }, "infill_mesh": { "label": "Infill Mesh", diff --git a/resources/i18n/cs_CZ/cura.po b/resources/i18n/cs_CZ/cura.po index 715af3ea84..3267139490 100644 --- a/resources/i18n/cs_CZ/cura.po +++ b/resources/i18n/cs_CZ/cura.po @@ -4946,6 +4946,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Rozdělit modely" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Tisknout před" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Tisknout po" + msgctxt "@button" msgid "Uninstall" msgstr "Odinstalovat" diff --git a/resources/i18n/cs_CZ/fdmprinter.def.json.po b/resources/i18n/cs_CZ/fdmprinter.def.json.po index 7588e81c52..4b697c9cea 100644 --- a/resources/i18n/cs_CZ/fdmprinter.def.json.po +++ b/resources/i18n/cs_CZ/fdmprinter.def.json.po @@ -2583,6 +2583,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Tisková sekvence" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Nastavit tiskovou sekvenci ručně" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Umožňuje řadit seznam objektů pro ruční nastavení tiskové sekvence. První objekt ze seznamu bude vytisknut jako první." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Rychlost tisku" diff --git a/resources/i18n/cura.pot b/resources/i18n/cura.pot index 7d5b5f94d6..2fabd97f7e 100644 --- a/resources/i18n/cura.pot +++ b/resources/i18n/cura.pot @@ -4565,6 +4565,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "" + msgctxt "@button" msgid "Uninstall" msgstr "" diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po index f006c75fb6..8ca4de67b4 100644 --- a/resources/i18n/de_DE/cura.po +++ b/resources/i18n/de_DE/cura.po @@ -4930,6 +4930,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Gruppierung für Modelle aufheben" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Vor dem Drucken" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Nach dem Drucken" + msgctxt "@button" msgid "Uninstall" msgstr "Deinstallieren" diff --git a/resources/i18n/de_DE/fdmprinter.def.json.po b/resources/i18n/de_DE/fdmprinter.def.json.po index ca893ad149..ff44a4837d 100644 --- a/resources/i18n/de_DE/fdmprinter.def.json.po +++ b/resources/i18n/de_DE/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Druckreihenfolge" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Druckreihenfolge manuell einstellen" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Ermöglicht das Ordnen der Objektliste, um die Druckreihenfolge manuell festzulegen. Das erste Objekt aus der Liste wird zuerst gedruckt." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Druckgeschwindigkeit" diff --git a/resources/i18n/es_ES/cura.po b/resources/i18n/es_ES/cura.po index 07d4ad2d79..aa4c727441 100644 --- a/resources/i18n/es_ES/cura.po +++ b/resources/i18n/es_ES/cura.po @@ -4931,6 +4931,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Desagrupar modelos" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Imprimir antes" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Imprimir después" + msgctxt "@button" msgid "Uninstall" msgstr "Desinstalar" diff --git a/resources/i18n/es_ES/fdmprinter.def.json.po b/resources/i18n/es_ES/fdmprinter.def.json.po index 4b797652ed..6811ca05a8 100644 --- a/resources/i18n/es_ES/fdmprinter.def.json.po +++ b/resources/i18n/es_ES/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Secuencia de impresión" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Establecer secuencia de impresión manualmente" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Permite ordenar la lista de objetos para establecer la secuencia de impresión manualmente. El primer objeto de la lista se imprimirá primero." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Velocidad de impresión" diff --git a/resources/i18n/fdmprinter.def.json.pot b/resources/i18n/fdmprinter.def.json.pot index 6b61ec3173..ab5a717643 100644 --- a/resources/i18n/fdmprinter.def.json.pot +++ b/resources/i18n/fdmprinter.def.json.pot @@ -4596,6 +4596,14 @@ msgctxt "print_sequence option one_at_a_time" msgid "One at a Time" msgstr "" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "" + msgctxt "infill_mesh label" msgid "Infill Mesh" msgstr "" diff --git a/resources/i18n/fi_FI/cura.po b/resources/i18n/fi_FI/cura.po index c3f331c1ef..55a60d50ae 100644 --- a/resources/i18n/fi_FI/cura.po +++ b/resources/i18n/fi_FI/cura.po @@ -4899,6 +4899,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Poista mallien ryhmitys" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Tulosta ennen" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Tulosta jälkeen" + msgctxt "@button" msgid "Uninstall" msgstr "" diff --git a/resources/i18n/fi_FI/fdmprinter.def.json.po b/resources/i18n/fi_FI/fdmprinter.def.json.po index 19a83d2f6a..a1e4ab420e 100644 --- a/resources/i18n/fi_FI/fdmprinter.def.json.po +++ b/resources/i18n/fi_FI/fdmprinter.def.json.po @@ -2578,6 +2578,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Tulostusjärjestys" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Aseta tulostusjärjestys manuaalisesti" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Mahdollistaa kohteiden järjestämisen tulostusjärjestyksen manuaaliseen asettamiseen. Listan ensimmäinen kohde tulostetaan ensin." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Tulostusnopeus" diff --git a/resources/i18n/fr_FR/cura.po b/resources/i18n/fr_FR/cura.po index b597b2d540..af46346d63 100644 --- a/resources/i18n/fr_FR/cura.po +++ b/resources/i18n/fr_FR/cura.po @@ -4928,6 +4928,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Dégrouper les modèles" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Imprimer avant" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Imprimer après" + msgctxt "@button" msgid "Uninstall" msgstr "Désinstaller" diff --git a/resources/i18n/fr_FR/fdmprinter.def.json.po b/resources/i18n/fr_FR/fdmprinter.def.json.po index e4018d33e5..2376820b7c 100644 --- a/resources/i18n/fr_FR/fdmprinter.def.json.po +++ b/resources/i18n/fr_FR/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Séquence d'impression" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Définir la séquence d'impression manuellement" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Permet de classer la liste des objets pour définir manuellement la séquence d'impression. Le premier objet de la liste sera imprimé en premier." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Vitesse d’impression" diff --git a/resources/i18n/hu_HU/cura.po b/resources/i18n/hu_HU/cura.po index 9a502fbdf6..d5f06599a1 100644 --- a/resources/i18n/hu_HU/cura.po +++ b/resources/i18n/hu_HU/cura.po @@ -4913,6 +4913,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Csoport bontása" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Nyomtatás előtt" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Nyomtatás után" + msgctxt "@button" msgid "Uninstall" msgstr "" diff --git a/resources/i18n/hu_HU/fdmprinter.def.json.po b/resources/i18n/hu_HU/fdmprinter.def.json.po index 789454be37..27eabd4bbc 100644 --- a/resources/i18n/hu_HU/fdmprinter.def.json.po +++ b/resources/i18n/hu_HU/fdmprinter.def.json.po @@ -2585,6 +2585,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Nyomtatási sorrend" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Nyomtatási sorrend kézi beállítása" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Lehetővé teszi az objektumlista rendezését a nyomtatási sorrend kézi beállításához. A lista első objektuma lesz először nyomtatva." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Nyomtatási sebesség" diff --git a/resources/i18n/it_IT/cura.po b/resources/i18n/it_IT/cura.po index 1a131973bf..48918d3883 100644 --- a/resources/i18n/it_IT/cura.po +++ b/resources/i18n/it_IT/cura.po @@ -4931,6 +4931,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Separa modelli" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Stampa prima" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Stampa dopo" + msgctxt "@button" msgid "Uninstall" msgstr "Disinstalla" diff --git a/resources/i18n/it_IT/fdmprinter.def.json.po b/resources/i18n/it_IT/fdmprinter.def.json.po index 4565e30aa9..e9fc77ca3c 100644 --- a/resources/i18n/it_IT/fdmprinter.def.json.po +++ b/resources/i18n/it_IT/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Sequenza di stampa" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Imposta manualmente la sequenza di stampa" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Consente di ordinare l'elenco degli oggetti per impostare manualmente la sequenza di stampa. Il primo oggetto dell'elenco sarà stampato per primo." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Velocità di stampa" diff --git a/resources/i18n/ja_JP/cura.po b/resources/i18n/ja_JP/cura.po index 7826e4df9e..bc2f27e825 100644 --- a/resources/i18n/ja_JP/cura.po +++ b/resources/i18n/ja_JP/cura.po @@ -4914,6 +4914,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "モデルを非グループ化" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "印刷前" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "印刷後" + msgctxt "@button" msgid "Uninstall" msgstr "アンインストール" diff --git a/resources/i18n/ja_JP/fdmprinter.def.json.po b/resources/i18n/ja_JP/fdmprinter.def.json.po index 8e473e72ae..a4311a63bd 100644 --- a/resources/i18n/ja_JP/fdmprinter.def.json.po +++ b/resources/i18n/ja_JP/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "印刷頻度" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "手動で印刷順序を設定する" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "オブジェクトリストを並べ替えて、手動で印刷順序を設定することができます。リストの最初のオブジェクトが最初に印刷されます。" + msgctxt "speed_print label" msgid "Print Speed" msgstr "印刷速度" diff --git a/resources/i18n/ko_KR/cura.po b/resources/i18n/ko_KR/cura.po index 5926b7c442..6bfbd1bae7 100644 --- a/resources/i18n/ko_KR/cura.po +++ b/resources/i18n/ko_KR/cura.po @@ -4917,6 +4917,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "모델 그룹 해제" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "인쇄 전" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "인쇄 후" + msgctxt "@button" msgid "Uninstall" msgstr "설치 제거" diff --git a/resources/i18n/ko_KR/fdmprinter.def.json.po b/resources/i18n/ko_KR/fdmprinter.def.json.po index 7e2974dd37..0cf075c854 100644 --- a/resources/i18n/ko_KR/fdmprinter.def.json.po +++ b/resources/i18n/ko_KR/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "프린팅 순서" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "수동으로 인쇄 순서 설정" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "객체 목록을 정렬하여 수동으로 인쇄 순서를 설정할 수 있습니다. 목록의 첫 번째 객체가 먼저 인쇄됩니다." + msgctxt "speed_print label" msgid "Print Speed" msgstr "프린팅 속도" diff --git a/resources/i18n/nl_NL/cura.po b/resources/i18n/nl_NL/cura.po index f831c7989f..43ca87b01e 100644 --- a/resources/i18n/nl_NL/cura.po +++ b/resources/i18n/nl_NL/cura.po @@ -4925,6 +4925,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Groeperen van Modellen Opheffen" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Afdrukken voor" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Afdrukken na" + msgctxt "@button" msgid "Uninstall" msgstr "De-installeren" diff --git a/resources/i18n/nl_NL/fdmprinter.def.json.po b/resources/i18n/nl_NL/fdmprinter.def.json.po index 7d6b32e0ac..8c4ef463a8 100644 --- a/resources/i18n/nl_NL/fdmprinter.def.json.po +++ b/resources/i18n/nl_NL/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Printvolgorde" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Handmatig afdrukvolgorde instellen" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Maakt het mogelijk de objectlijst te ordenen om de afdrukvolgorde handmatig in te stellen. Het eerste object van de lijst wordt als eerste afgedrukt." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Printsnelheid" diff --git a/resources/i18n/pl_PL/cura.po b/resources/i18n/pl_PL/cura.po index ed823e183c..fe9f606141 100644 --- a/resources/i18n/pl_PL/cura.po +++ b/resources/i18n/pl_PL/cura.po @@ -4916,6 +4916,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Rozgrupuj modele" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Drukuj przed" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Drukuj po" + msgctxt "@button" msgid "Uninstall" msgstr "" diff --git a/resources/i18n/pl_PL/fdmprinter.def.json.po b/resources/i18n/pl_PL/fdmprinter.def.json.po index b772775d09..7f093c859c 100644 --- a/resources/i18n/pl_PL/fdmprinter.def.json.po +++ b/resources/i18n/pl_PL/fdmprinter.def.json.po @@ -2584,6 +2584,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Sekwencja Wydruku" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Ręczne ustawienie kolejności drukowania" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Umożliwia ręczne ustawienie kolejności drukowania na liście obiektów. Pierwszy obiekt z listy zostanie wydrukowany jako pierwszy." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Prędkość Druku" diff --git a/resources/i18n/pt_BR/cura.po b/resources/i18n/pt_BR/cura.po index 1c4590a016..0ae0a56cfd 100644 --- a/resources/i18n/pt_BR/cura.po +++ b/resources/i18n/pt_BR/cura.po @@ -4942,6 +4942,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Desagrupar Modelos" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Imprimir antes" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Imprimir depois" + msgctxt "@button" msgid "Uninstall" msgstr "Desinstalar" diff --git a/resources/i18n/pt_BR/fdmprinter.def.json.po b/resources/i18n/pt_BR/fdmprinter.def.json.po index 651837f458..412a020a7e 100644 --- a/resources/i18n/pt_BR/fdmprinter.def.json.po +++ b/resources/i18n/pt_BR/fdmprinter.def.json.po @@ -2585,6 +2585,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Sequência de Impressão" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Definir sequência de impressão manualmente" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Permite ordenar a lista de objetos para definir a sequência de impressão manualmente. O primeiro objeto da lista será impresso primeiro." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Velocidade de Impressão" diff --git a/resources/i18n/pt_PT/cura.po b/resources/i18n/pt_PT/cura.po index 48ea1e7c2c..d6e19b222d 100644 --- a/resources/i18n/pt_PT/cura.po +++ b/resources/i18n/pt_PT/cura.po @@ -4932,6 +4932,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Desagrupar Modelos" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Imprimir antes" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Imprimir depois" + msgctxt "@button" msgid "Uninstall" msgstr "Desinstalar" diff --git a/resources/i18n/pt_PT/fdmprinter.def.json.po b/resources/i18n/pt_PT/fdmprinter.def.json.po index dea593ffe4..36283bc9de 100644 --- a/resources/i18n/pt_PT/fdmprinter.def.json.po +++ b/resources/i18n/pt_PT/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Sequência de impressão" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Definir sequência de impressão manualmente" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Permite ordenar a lista de objetos para definir a sequência de impressão manualmente. O primeiro objeto da lista será impresso primeiro." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Velocidade de Impressão" diff --git a/resources/i18n/ru_RU/cura.po b/resources/i18n/ru_RU/cura.po index 6494d6b5d2..2960193d7e 100644 --- a/resources/i18n/ru_RU/cura.po +++ b/resources/i18n/ru_RU/cura.po @@ -4955,6 +4955,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Разгруппировать модели" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Печатать до" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Печатать после" + msgctxt "@button" msgid "Uninstall" msgstr "Удалить" diff --git a/resources/i18n/ru_RU/fdmprinter.def.json.po b/resources/i18n/ru_RU/fdmprinter.def.json.po index 99036d4865..bba90e21ef 100644 --- a/resources/i18n/ru_RU/fdmprinter.def.json.po +++ b/resources/i18n/ru_RU/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Последовательная печать" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Установить последовательность печати вручную" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Позволяет упорядочить список объектов для ручной настройки последовательности печати. Первый объект из списка будет напечатан первым." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Скорость печати" diff --git a/resources/i18n/tr_TR/cura.po b/resources/i18n/tr_TR/cura.po index d98ff91e72..c3afd0c7c1 100644 --- a/resources/i18n/tr_TR/cura.po +++ b/resources/i18n/tr_TR/cura.po @@ -4931,6 +4931,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "Model Grubunu Çöz" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "Önce Yazdır" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "Sonra Yazdır" + msgctxt "@button" msgid "Uninstall" msgstr "Kaldır" diff --git a/resources/i18n/tr_TR/fdmprinter.def.json.po b/resources/i18n/tr_TR/fdmprinter.def.json.po index b57a0cd0bb..0e11895512 100644 --- a/resources/i18n/tr_TR/fdmprinter.def.json.po +++ b/resources/i18n/tr_TR/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "Yazdırma Dizisi" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "Baskı Sırasını Manuel Olarak Ayarla" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "Nesne listesini sıralayarak baskı sırasını manuel olarak ayarlamayı sağlar. Listeden ilk nesne ilk olarak basılacak." + msgctxt "speed_print label" msgid "Print Speed" msgstr "Yazdırma Hızı" diff --git a/resources/i18n/zh_CN/cura.po b/resources/i18n/zh_CN/cura.po index 34b4f1d4dc..cf2ed81f9b 100644 --- a/resources/i18n/zh_CN/cura.po +++ b/resources/i18n/zh_CN/cura.po @@ -4919,6 +4919,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "拆分模型" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "打印前" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "打印后" + msgctxt "@button" msgid "Uninstall" msgstr "卸载" diff --git a/resources/i18n/zh_CN/fdmprinter.def.json.po b/resources/i18n/zh_CN/fdmprinter.def.json.po index 1042199d5b..4696832051 100644 --- a/resources/i18n/zh_CN/fdmprinter.def.json.po +++ b/resources/i18n/zh_CN/fdmprinter.def.json.po @@ -2580,6 +2580,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "打印序列" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "手动设置打印顺序" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "允许对对象列表进行排序,以手动设置打印顺序。列表中的第一个对象将首先被打印。" + msgctxt "speed_print label" msgid "Print Speed" msgstr "打印速度" diff --git a/resources/i18n/zh_TW/cura.po b/resources/i18n/zh_TW/cura.po index a461fd1fa3..741bde1d14 100644 --- a/resources/i18n/zh_TW/cura.po +++ b/resources/i18n/zh_TW/cura.po @@ -4911,6 +4911,14 @@ msgctxt "@action:inmenu menubar:edit" msgid "Ungroup Models" msgstr "取消模型群組" +msgctxt "@action:inmenu menubar:edit" +msgid "Print Before" +msgstr "列印前" + +msgctxt "@action:inmenu menubar:edit" +msgid "Print After" +msgstr "列印後" + msgctxt "@button" msgid "Uninstall" msgstr "" diff --git a/resources/i18n/zh_TW/fdmprinter.def.json.po b/resources/i18n/zh_TW/fdmprinter.def.json.po index c92a7f861a..aa02299fc1 100644 --- a/resources/i18n/zh_TW/fdmprinter.def.json.po +++ b/resources/i18n/zh_TW/fdmprinter.def.json.po @@ -2585,6 +2585,14 @@ msgctxt "print_sequence label" msgid "Print Sequence" msgstr "列印順序" +msgctxt "user_defined_print_order_enabled label" +msgid "Set Print Sequence Manually" +msgstr "手動設置列印順序" + +msgctxt "user_defined_print_order_enabled description" +msgid "Allows to order the object list to set the print sequence manually. First object from the list will be printed first." +msgstr "允許手動設置物件列表以設定列印順序。列表中的第一個物件將首先被列印。" + msgctxt "speed_print label" msgid "Print Speed" msgstr "列印速度" diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 458d7fcaae..4cc504166b 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -35,6 +35,9 @@ Item property alias mergeObjects: mergeObjectsAction //property alias unMergeObjects: unMergeObjectsAction + property alias printObjectBeforePrevious: printObjectBeforePreviousAction + property alias printObjectAfterNext: printObjectAfterNextAction + property alias multiplyObject: multiplyObjectAction property alias selectAll: selectAllAction @@ -406,6 +409,26 @@ Item onTriggered: CuraApplication.ungroupSelected() } + Action + { + id: printObjectBeforePreviousAction + text: catalog.i18nc("@action:inmenu menubar:edit","Print Before") + " " + PrintOrderManager.previousNodeName + enabled: PrintOrderManager.shouldEnablePrintBeforeAction + icon.name: "print-before" + shortcut: "PgUp" + onTriggered: PrintOrderManager.swapSelectedAndPreviousNodes() + } + + Action + { + id: printObjectAfterNextAction + text: catalog.i18nc("@action:inmenu menubar:edit","Print After") + " " + PrintOrderManager.nextNodeName + enabled: PrintOrderManager.shouldEnablePrintAfterAction + icon.name: "print-after" + shortcut: "PgDown" + onTriggered: PrintOrderManager.swapSelectedAndNextNodes() + } + Action { id: mergeObjectsAction diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index 2de2795a74..1b32c24254 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -78,6 +78,19 @@ Cura.Menu Cura.MenuItem { action: Cura.Actions.mergeObjects } Cura.MenuItem { action: Cura.Actions.unGroupObjects } + // Edit print sequence actions + Cura.MenuSeparator { visible: PrintOrderManager.shouldShowEditPrintOrderActions } + Cura.MenuItem + { + action: Cura.Actions.printObjectBeforePrevious + visible: PrintOrderManager.shouldShowEditPrintOrderActions + } + Cura.MenuItem + { + action: Cura.Actions.printObjectAfterNext + visible: PrintOrderManager.shouldShowEditPrintOrderActions + } + Connections { target: UM.Controller diff --git a/resources/qml/Menus/EditMenu.qml b/resources/qml/Menus/EditMenu.qml index 522c6b27d1..728b3b212b 100644 --- a/resources/qml/Menus/EditMenu.qml +++ b/resources/qml/Menus/EditMenu.qml @@ -25,4 +25,17 @@ Cura.Menu Cura.MenuItem { action: Cura.Actions.groupObjects } Cura.MenuItem { action: Cura.Actions.mergeObjects } Cura.MenuItem { action: Cura.Actions.unGroupObjects } + + // Edit print sequence actions + Cura.MenuSeparator { visible: PrintOrderManager.shouldShowEditPrintOrderActions } + Cura.MenuItem + { + action: Cura.Actions.printObjectBeforePrevious + visible: PrintOrderManager.shouldShowEditPrintOrderActions + } + Cura.MenuItem + { + action: Cura.Actions.printObjectAfterNext + visible: PrintOrderManager.shouldShowEditPrintOrderActions + } } \ No newline at end of file diff --git a/resources/setting_visibility/advanced.cfg b/resources/setting_visibility/advanced.cfg index c3451d2c98..cd501267d0 100644 --- a/resources/setting_visibility/advanced.cfg +++ b/resources/setting_visibility/advanced.cfg @@ -136,6 +136,7 @@ prime_tower_brim_enable [blackmagic] print_sequence +user_defined_print_order_enabled magic_mesh_surface_mode magic_spiralize smooth_spiralized_contours diff --git a/resources/setting_visibility/expert.cfg b/resources/setting_visibility/expert.cfg index 2f2dd7671d..06ffead8a5 100644 --- a/resources/setting_visibility/expert.cfg +++ b/resources/setting_visibility/expert.cfg @@ -386,6 +386,7 @@ meshfix_fluid_motion_angle [blackmagic] print_sequence +user_defined_print_order_enabled infill_mesh infill_mesh_order cutting_mesh diff --git a/tests/TestHitChecker.py b/tests/TestHitChecker.py new file mode 100644 index 0000000000..59ee1d8162 --- /dev/null +++ b/tests/TestHitChecker.py @@ -0,0 +1,141 @@ +from unittest.mock import patch + +from cura.HitChecker import HitChecker +from cura.OneAtATimeIterator import OneAtATimeIterator +from cura.Scene.CuraSceneNode import CuraSceneNode + + +def test_anyTwoNodesBlockEachOther_True(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + # node1 and node2 block each other + hit_map = { + node1: {node1: 0, node2: 1}, + node2: {node1: 1, node2: 0} + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2]) + assert hit_checker.anyTwoNodesBlockEachOther([node1, node2]) + assert hit_checker.anyTwoNodesBlockEachOther([node2, node1]) + + +def test_anyTwoNodesBlockEachOther_False(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + # node1 blocks node2, but node2 doesn't block node1 + hit_map = { + node1: {node1: 0, node2: 1}, + node2: {node1: 0, node2: 0} + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2]) + assert not hit_checker.anyTwoNodesBlockEachOther([node1, node2]) + assert not hit_checker.anyTwoNodesBlockEachOther([node2, node1]) + + +def test_canPrintBefore(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + # nodes can be printed only in order node1 -> node2 -> node3 + hit_map = { + node1: {node1: 0, node2: 0, node3: 0}, + node2: {node1: 1, node2: 0, node3: 0}, + node3: {node1: 1, node2: 1, node3: 0}, + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2, node3]) + + assert hit_checker.canPrintBefore(node1, [node2]) + assert hit_checker.canPrintBefore(node1, [node3]) + assert hit_checker.canPrintBefore(node1, [node2, node3]) + assert hit_checker.canPrintBefore(node1, [node3, node2]) + + assert hit_checker.canPrintBefore(node2, [node3]) + assert not hit_checker.canPrintBefore(node2, [node1]) + assert not hit_checker.canPrintBefore(node2, [node1, node3]) + assert not hit_checker.canPrintBefore(node2, [node3, node1]) + + assert not hit_checker.canPrintBefore(node3, [node1]) + assert not hit_checker.canPrintBefore(node3, [node2]) + assert not hit_checker.canPrintBefore(node3, [node1, node2]) + assert not hit_checker.canPrintBefore(node3, [node2, node1]) + + +def test_canPrintAfter(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + + # nodes can be printed only in order node1 -> node2 -> node3 + hit_map = { + node1: {node1: 0, node2: 0, node3: 0}, + node2: {node1: 1, node2: 0, node3: 0}, + node3: {node1: 1, node2: 1, node3: 0}, + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2, node3]) + + assert not hit_checker.canPrintAfter(node1, [node2]) + assert not hit_checker.canPrintAfter(node1, [node3]) + assert not hit_checker.canPrintAfter(node1, [node2, node3]) + assert not hit_checker.canPrintAfter(node1, [node3, node2]) + + assert hit_checker.canPrintAfter(node2, [node1]) + assert not hit_checker.canPrintAfter(node2, [node3]) + assert not hit_checker.canPrintAfter(node2, [node1, node3]) + assert not hit_checker.canPrintAfter(node2, [node3, node1]) + + assert hit_checker.canPrintAfter(node3, [node1]) + assert hit_checker.canPrintAfter(node3, [node2]) + assert hit_checker.canPrintAfter(node3, [node1, node2]) + assert hit_checker.canPrintAfter(node3, [node2, node1]) + + +def test_calculateScore(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + + hit_map = { + node1: {node1: 0, node2: 0, node3: 0}, # sum is 0 + node2: {node1: 1, node2: 0, node3: 0}, # sum is 1 + node3: {node1: 1, node2: 1, node3: 0}, # sum is 2 + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2, node3]) + + # score is a diff between sums + assert hit_checker.calculateScore(node1, node2) == -1 + assert hit_checker.calculateScore(node2, node1) == 1 + assert hit_checker.calculateScore(node1, node3) == -2 + assert hit_checker.calculateScore(node3, node1) == 2 + assert hit_checker.calculateScore(node2, node3) == -1 + assert hit_checker.calculateScore(node3, node2) == 1 + + +def test_canPrintNodesInProvidedOrder(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + + # nodes can be printed only in order node1 -> node2 -> node3 + hit_map = { + node1: {node1: 0, node2: 0, node3: 0}, # 0 + node2: {node1: 1, node2: 0, node3: 0}, # 1 + node3: {node1: 1, node2: 1, node3: 0}, # 2 + } + + with patch.object(HitChecker, "_buildHitMap", return_value=hit_map): + hit_checker = HitChecker([node1, node2, node3]) + assert hit_checker.canPrintNodesInProvidedOrder([node1, node2, node3]) + assert not hit_checker.canPrintNodesInProvidedOrder([node1, node3, node2]) + assert not hit_checker.canPrintNodesInProvidedOrder([node2, node1, node3]) + assert not hit_checker.canPrintNodesInProvidedOrder([node2, node3, node1]) + assert not hit_checker.canPrintNodesInProvidedOrder([node3, node1, node2]) + assert not hit_checker.canPrintNodesInProvidedOrder([node3, node2, node1]) \ No newline at end of file diff --git a/tests/TestPrintOrderManager.py b/tests/TestPrintOrderManager.py new file mode 100644 index 0000000000..8b2c0475b2 --- /dev/null +++ b/tests/TestPrintOrderManager.py @@ -0,0 +1,175 @@ +from unittest.mock import patch, MagicMock + +from cura.PrintOrderManager import PrintOrderManager +from cura.Scene.CuraSceneNode import CuraSceneNode + + +def test_getNodeName(): + node1 = CuraSceneNode(name="cat", no_setting_override=True) + node2 = CuraSceneNode(name="dog", no_setting_override=True) + assert PrintOrderManager._getNodeName(node1) == "cat" + assert PrintOrderManager._getNodeName(node2) == "dog" + assert PrintOrderManager._getNodeName(None) == "" + + +def test_getNodeName_truncatesLongName(): + node = CuraSceneNode(name="some_name_longer_than_30_characters", no_setting_override=True) + assert PrintOrderManager._getNodeName(node) == "some_name_longer_than_30_chara" + assert PrintOrderManager._getNodeName(node, max_length=10) == "some_name_" + + +def test_getSingleSelectedNode(): + node1 = CuraSceneNode(no_setting_override=True) + with patch("UM.Scene.Selection.Selection.getAllSelectedObjects", MagicMock(return_value=[node1])): + with patch("UM.Scene.Selection.Selection.getSelectedObject", MagicMock(return_value=node1)): + assert PrintOrderManager._getSingleSelectedNode() == node1 + + +def test_getSingleSelectedNode_returnsNoneIfNothingSelected(): + with patch("UM.Scene.Selection.Selection.getAllSelectedObjects", MagicMock(return_value=[])): + assert PrintOrderManager._getSingleSelectedNode() is None + + +def test_getSingleSelectedNode_returnsNoneIfMultipleObjectsSelected(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + with patch("UM.Scene.Selection.Selection.getAllSelectedObjects", MagicMock(return_value=[node1, node2])): + assert PrintOrderManager._getSingleSelectedNode() is None + + +def test_neighborNodeNamesCorrect_WhenSomeNodeSelected(): + node1 = CuraSceneNode(no_setting_override=True, name="node1") + node2 = CuraSceneNode(no_setting_override=True, name="node2") + node3 = CuraSceneNode(no_setting_override=True, name="node3") + node1.printOrder = 1 + node2.printOrder = 2 + node3.printOrder = 3 + with patch.object(PrintOrderManager, "_configureEvents", return_value=None): + with patch.object(PrintOrderManager, "_getSingleSelectedNode", return_value=node1): + print_order_manager = PrintOrderManager(get_nodes=lambda: [node1, node2, node3]) + + assert print_order_manager.previousNodeName == "" + assert print_order_manager.nextNodeName == "node2" + assert not print_order_manager.shouldEnablePrintBeforeAction + assert print_order_manager.shouldEnablePrintAfterAction + + print_order_manager.swapSelectedAndNextNodes() # swaps node1 with node2, result: [node2, node1, node3] + assert print_order_manager.previousNodeName == "node2" + assert print_order_manager.nextNodeName == "node3" + assert print_order_manager.shouldEnablePrintBeforeAction + assert print_order_manager.shouldEnablePrintAfterAction + + print_order_manager.swapSelectedAndNextNodes() # swaps node1 with node3, result: [node2, node3, node1] + assert print_order_manager.previousNodeName == "node3" + assert print_order_manager.nextNodeName == "" + assert print_order_manager.shouldEnablePrintBeforeAction + assert not print_order_manager.shouldEnablePrintAfterAction + + print_order_manager.swapSelectedAndPreviousNodes() # swaps node1 with node3, result: [node2, node1, node3] + assert print_order_manager.previousNodeName == "node2" + assert print_order_manager.nextNodeName == "node3" + assert print_order_manager.shouldEnablePrintBeforeAction + assert print_order_manager.shouldEnablePrintAfterAction + + print_order_manager.swapSelectedAndPreviousNodes() # swaps node1 with node2, result: [node1, node2, node3] + assert print_order_manager.previousNodeName == "" + assert print_order_manager.nextNodeName == "node2" + assert not print_order_manager.shouldEnablePrintBeforeAction + assert print_order_manager.shouldEnablePrintAfterAction + + +def test_neighborNodeNamesEmpty_WhenNothingSelected(): + node1 = CuraSceneNode(no_setting_override=True, name="node1") + node2 = CuraSceneNode(no_setting_override=True, name="node2") + node3 = CuraSceneNode(no_setting_override=True, name="node3") + node1.printOrder = 1 + node2.printOrder = 2 + node3.printOrder = 3 + with patch.object(PrintOrderManager, "_configureEvents", return_value=None): + with patch.object(PrintOrderManager, "_getSingleSelectedNode", return_value=None): + print_order_manager = PrintOrderManager(get_nodes=lambda: [node1, node2, node3]) + assert print_order_manager.previousNodeName == "" + assert print_order_manager.nextNodeName == "" + assert not print_order_manager.shouldEnablePrintBeforeAction + assert not print_order_manager.shouldEnablePrintAfterAction + + +def test_initializePrintOrders(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + + # assume print orders are 0 + assert node1.printOrder == 0 + assert node2.printOrder == 0 + + PrintOrderManager.initializePrintOrders([node1, node2]) + + # assert print orders initialized + assert node1.printOrder == 1 + assert node2.printOrder == 2 + + node3 = CuraSceneNode(no_setting_override=True) + node4 = CuraSceneNode(no_setting_override=True) + # assume print orders are 0 + assert node3.printOrder == 0 + assert node4.printOrder == 0 + + PrintOrderManager.initializePrintOrders([node2, node1, node3, node4]) + + # assert print orders not changed for node1 and node2 and initialized for node3 and node4 + assert node1.printOrder == 1 + assert node2.printOrder == 2 + assert node3.printOrder == 3 + assert node4.printOrder == 4 + + +def test_updatePrintOrdersAfterGroupOperation(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + node4 = CuraSceneNode(no_setting_override=True) + node5 = CuraSceneNode(no_setting_override=True) + node1.printOrder = 1 + node2.printOrder = 2 + node3.printOrder = 3 + node4.printOrder = 4 + node5.printOrder = 5 + + all_nodes = [node1, node2, node3, node4, node5] + grouped_nodes = [node2, node4] + group_node = CuraSceneNode(no_setting_override=True) + + PrintOrderManager.updatePrintOrdersAfterGroupOperation(all_nodes, group_node, grouped_nodes) + + assert node1.printOrder == 1 + assert group_node.printOrder == 2 + assert node3.printOrder == 3 + assert node5.printOrder == 4 + + +def test_updatePrintOrdersAfterUngroupOperation(): + node1 = CuraSceneNode(no_setting_override=True) + node2 = CuraSceneNode(no_setting_override=True) + node3 = CuraSceneNode(no_setting_override=True) + node1.printOrder = 1 + node2.printOrder = 2 + node3.printOrder = 3 + + all_nodes = [node1, node2, node3] + node4 = CuraSceneNode(no_setting_override=True) + node5 = CuraSceneNode(no_setting_override=True) + + group_node = node2 + ungrouped_nodes = [node4, node5] + PrintOrderManager.updatePrintOrdersAfterUngroupOperation(all_nodes, group_node, ungrouped_nodes) + + assert node1.printOrder == 1 + assert node4.printOrder == 2 + assert node5.printOrder == 3 + assert node3.printOrder == 4 + + assert node1 in all_nodes + assert node2 not in all_nodes + assert node3 in all_nodes + assert node4 in all_nodes + assert node5 in all_nodes From 330dfd8be0dc4ea312273df3e73654ca51618242 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 10 Jan 2024 15:13:42 +0100 Subject: [PATCH 02/46] Add retry to OAuth token refresh failure CURA-11406 --- cura/OAuth2/AuthorizationHelpers.py | 11 ++++++++--- cura/OAuth2/AuthorizationService.py | 26 +++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index a654ee4bdb..1bc0d545f4 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -16,6 +16,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To downlo catalog = i18nCatalog("cura") TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S" +REQUEST_TIMEOUT = 5 # Seconds class AuthorizationHelpers: @@ -52,7 +53,8 @@ class AuthorizationHelpers: data = urllib.parse.urlencode(data).encode("UTF-8"), headers_dict = headers, callback = lambda response: self.parseTokenResponse(response, callback), - error_callback = lambda response, _: self.parseTokenResponse(response, callback) + error_callback = lambda response, _: self.parseTokenResponse(response, callback), + timeout = REQUEST_TIMEOUT ) def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None: @@ -75,7 +77,9 @@ class AuthorizationHelpers: data = urllib.parse.urlencode(data).encode("UTF-8"), headers_dict = headers, callback = lambda response: self.parseTokenResponse(response, callback), - error_callback = lambda response, _: self.parseTokenResponse(response, callback) + error_callback = lambda response, _: self.parseTokenResponse(response, callback), + urgent = True, + timeout = REQUEST_TIMEOUT ) def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None: @@ -120,7 +124,8 @@ class AuthorizationHelpers: check_token_url, headers_dict = headers, callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback), - error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None + error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None, + timeout = REQUEST_TIMEOUT ) def _parseUserProfile(self, reply: QNetworkReply, success_callback: Optional[Callable[[UserProfile], None]], failed_callback: Optional[Callable[[], None]] = None) -> None: diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 62bf31982a..7a1bfb75f7 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -6,13 +6,14 @@ from datetime import datetime, timedelta from typing import Callable, Dict, Optional, TYPE_CHECKING, Union from urllib.parse import urlencode, quote_plus -from PyQt6.QtCore import QUrl +from PyQt6.QtCore import QUrl, QTimer from PyQt6.QtGui import QDesktopServices from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal from UM.i18n import i18nCatalog +from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To download log-in tokens. from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer from cura.OAuth2.Models import AuthenticationResponse, BaseModel @@ -53,6 +54,12 @@ class AuthorizationService: self.onAuthStateChanged.connect(self._authChanged) + self._refresh_token_retries = 0 + self._refresh_token_retry_timer = QTimer() + self._refresh_token_retry_timer.setInterval(1000) + self._refresh_token_retry_timer.setSingleShot(True) + self._refresh_token_retry_timer.timeout.connect(self.refreshAccessToken) + def _authChanged(self, logged_in): if logged_in and self._unable_to_get_data_message is not None: self._unable_to_get_data_message.hide() @@ -163,16 +170,29 @@ class AuthorizationService: return def process_auth_data(response: AuthenticationResponse) -> None: + self._currently_refreshing_token = False + if response.success: + self._refresh_token_retries = 0 self._storeAuthData(response) + HttpRequestManager.getInstance().setDelayRequests(False) self.onAuthStateChanged.emit(logged_in = True) else: - Logger.warning("Failed to get a new access token from the server.") - self.onAuthStateChanged.emit(logged_in = False) + if self._refresh_token_retries >= 15: + self._refresh_token_retries = 0 + Logger.warning("Failed to get a new access token from the server, giving up.") + HttpRequestManager.getInstance().setDelayRequests(False) + self.onAuthStateChanged.emit(logged_in = False) + else: + # Retry a bit later, network may be offline right now and will hopefully be back soon + Logger.warning("Failed to get a new access token from the server, retrying later.") + self._refresh_token_retries += 1 + self._refresh_token_retry_timer.start() if self._currently_refreshing_token: Logger.debug("Was already busy refreshing token. Do not start a new request.") return + HttpRequestManager.getInstance().setDelayRequests(True) self._currently_refreshing_token = True self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data) From 1bf789f6f495a7986182854e85d3e3810b92879f Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 26 Jan 2024 10:36:13 +0100 Subject: [PATCH 03/46] Update pyinstaller for mac --- UltiMaker-Cura.spec.jinja | 186 +------------------------------------- conandata.yml | 1 - conanfile.py | 4 +- cura/CuraApplication.py | 3 + requirements-dev.txt | 2 +- 5 files changed, 10 insertions(+), 186 deletions(-) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index cd939cf736..2c930e6ed6 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -70,188 +70,7 @@ coll = COLLECT( ) {% if macos == true %} -# PyInstaller seems to copy everything in the resource folder for the MacOS, this causes issues with codesigning and notarizing -# The folder structure should adhere to the one specified in Table 2-5 -# https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1 -# The class below is basically ducktyping the BUNDLE class of PyInstaller and using our own `assemble` method for more fine-grain and specific -# control. Some code of the method below is copied from: -# https://github.com/pyinstaller/pyinstaller/blob/22d1d2a5378228744cc95f14904dae1664df32c4/PyInstaller/building/osx.py#L115 -#----------------------------------------------------------------------------- -# Copyright (c) 2005-2022, PyInstaller Development Team. -# -# Distributed under the terms of the GNU General Public License (version 2 -# or later) with exception for distributing the bootloader. -# -# The full license is in the file COPYING.txt, distributed with this software. -# -# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) -#----------------------------------------------------------------------------- - -import plistlib -import shutil -import PyInstaller.utils.osx as osxutils -from pathlib import Path -from PyInstaller.building.osx import BUNDLE -from PyInstaller.building.utils import (_check_path_overlap, _rmtree, add_suffix_to_extension, checkCache) -from PyInstaller.building.datastruct import logger -from PyInstaller.building.icon import normalize_icon_type - - -class UMBUNDLE(BUNDLE): - def assemble(self): - from PyInstaller.config import CONF - - if _check_path_overlap(self.name) and os.path.isdir(self.name): - _rmtree(self.name) - logger.info("Building BUNDLE %s", self.tocbasename) - - # Create a minimal Mac bundle structure. - macos_path = Path(self.name, "Contents", "MacOS") - resources_path = Path(self.name, "Contents", "Resources") - frameworks_path = Path(self.name, "Contents", "Frameworks") - os.makedirs(macos_path) - os.makedirs(resources_path) - os.makedirs(frameworks_path) - - # Makes sure the icon exists and attempts to convert to the proper format if applicable - self.icon = normalize_icon_type(self.icon, ("icns",), "icns", CONF["workpath"]) - - # Ensure icon path is absolute - self.icon = os.path.abspath(self.icon) - - # Copy icns icon to Resources directory. - shutil.copy(self.icon, os.path.join(self.name, 'Contents', 'Resources')) - - # Key/values for a minimal Info.plist file - info_plist_dict = { - "CFBundleDisplayName": self.appname, - "CFBundleName": self.appname, - - # Required by 'codesign' utility. - # The value for CFBundleIdentifier is used as the default unique name of your program for Code Signing - # purposes. It even identifies the APP for access to restricted OS X areas like Keychain. - # - # The identifier used for signing must be globally unique. The usual form for this identifier is a - # hierarchical name in reverse DNS notation, starting with the toplevel domain, followed by the company - # name, followed by the department within the company, and ending with the product name. Usually in the - # form: com.mycompany.department.appname - # CLI option --osx-bundle-identifier sets this value. - "CFBundleIdentifier": self.bundle_identifier, - "CFBundleExecutable": os.path.basename(self.exename), - "CFBundleIconFile": os.path.basename(self.icon), - "CFBundleInfoDictionaryVersion": "6.0", - "CFBundlePackageType": "APPL", - "CFBundleVersionString": self.version, - "CFBundleShortVersionString": self.version, - } - - # Set some default values. But they still can be overwritten by the user. - if self.console: - # Setting EXE console=True implies LSBackgroundOnly=True. - info_plist_dict['LSBackgroundOnly'] = True - else: - # Let's use high resolution by default. - info_plist_dict['NSHighResolutionCapable'] = True - - # Merge info_plist settings from spec file - if isinstance(self.info_plist, dict) and self.info_plist: - info_plist_dict.update(self.info_plist) - - plist_filename = os.path.join(self.name, "Contents", "Info.plist") - with open(plist_filename, "wb") as plist_fh: - plistlib.dump(info_plist_dict, plist_fh) - - links = [] - _QT_BASE_PATH = {'PySide2', 'PySide6', 'PyQt5', 'PyQt6', 'PySide6'} - for inm, fnm, typ in self.toc: - # Adjust name for extensions, if applicable - inm, fnm, typ = add_suffix_to_extension(inm, fnm, typ) - inm = Path(inm) - fnm = Path(fnm) - # Copy files from cache. This ensures that are used files with relative paths to dynamic library - # dependencies (@executable_path) - if typ in ('EXTENSION', 'BINARY') or (typ == 'DATA' and inm.suffix == '.so'): - if any(['.' in p for p in inm.parent.parts]): - inm = Path(inm.name) - fnm = Path(checkCache( - str(fnm), - strip = self.strip, - upx = self.upx, - upx_exclude = self.upx_exclude, - dist_nm = str(inm), - target_arch = self.target_arch, - codesign_identity = self.codesign_identity, - entitlements_file = self.entitlements_file, - strict_arch_validation = (typ == 'EXTENSION'), - )) - frame_dst = frameworks_path.joinpath(inm) - if not frame_dst.exists(): - if frame_dst.is_dir(): - os.makedirs(frame_dst, exist_ok = True) - else: - os.makedirs(frame_dst.parent, exist_ok = True) - shutil.copy(fnm, frame_dst, follow_symlinks = True) - macos_dst = macos_path.joinpath(inm) - if not macos_dst.exists(): - if macos_dst.is_dir(): - os.makedirs(macos_dst, exist_ok = True) - else: - os.makedirs(macos_dst.parent, exist_ok = True) - - # Create relative symlink to the framework - symlink_to = Path(*[".." for p in macos_dst.relative_to(macos_path).parts], "Frameworks").joinpath( - frame_dst.relative_to(frameworks_path)) - try: - macos_dst.symlink_to(symlink_to) - except FileExistsError: - pass - else: - if typ == 'DATA': - if any(['.' in p for p in inm.parent.parts]) or inm.suffix == '.so': - # Skip info dist egg and some not needed folders in tcl and tk, since they all contain dots in their files - logger.warning(f"Skipping DATA file {inm}") - continue - res_dst = resources_path.joinpath(inm) - if not res_dst.exists(): - if res_dst.is_dir(): - os.makedirs(res_dst, exist_ok = True) - else: - os.makedirs(res_dst.parent, exist_ok = True) - shutil.copy(fnm, res_dst, follow_symlinks = True) - macos_dst = macos_path.joinpath(inm) - if not macos_dst.exists(): - if macos_dst.is_dir(): - os.makedirs(macos_dst, exist_ok = True) - else: - os.makedirs(macos_dst.parent, exist_ok = True) - - # Create relative symlink to the resource - symlink_to = Path(*[".." for p in macos_dst.relative_to(macos_path).parts], "Resources").joinpath( - res_dst.relative_to(resources_path)) - try: - macos_dst.symlink_to(symlink_to) - except FileExistsError: - pass - else: - macos_dst = macos_path.joinpath(inm) - if not macos_dst.exists(): - if macos_dst.is_dir(): - os.makedirs(macos_dst, exist_ok = True) - else: - os.makedirs(macos_dst.parent, exist_ok = True) - shutil.copy(fnm, macos_dst, follow_symlinks = True) - - # Sign the bundle - logger.info('Signing the BUNDLE...') - try: - osxutils.sign_binary(self.name, self.codesign_identity, self.entitlements_file, deep = True) - except Exception as e: - logger.warning(f"Error while signing the bundle: {e}") - logger.warning("You will need to sign the bundle manually!") - - logger.info(f"Building BUNDLE {self.tocbasename} completed successfully.") - -app = UMBUNDLE( +app = BUNDLE( coll, name='{{ display_name }}.app', icon={{ icon }}, @@ -276,4 +95,5 @@ app = UMBUNDLE( 'CFBundleTypeName': 'Model Files', }] }, -){% endif %} +) +{% endif %} diff --git a/conandata.yml b/conandata.yml index 486a64c26e..2485dd8bd0 100644 --- a/conandata.yml +++ b/conandata.yml @@ -118,7 +118,6 @@ pyinstaller: - "sqlite3" - "trimesh" - "win32ctypes" - - "PyQt6" - "PyQt6.QtNetwork" - "PyQt6.sip" - "stl" diff --git a/conanfile.py b/conanfile.py index 87e3377687..6f0c598b22 100644 --- a/conanfile.py +++ b/conanfile.py @@ -163,8 +163,10 @@ class CuraConan(ConanFile): def _python_installs(self): python_installs = {} + python_executable = "python3" if self.settings.os == "Macos" else "python" + # list of python installs - python_ins_cmd = f"python -c \"import pkg_resources; print(';'.join([(s.key+','+ s.version) for s in pkg_resources.working_set]))\"" + python_ins_cmd = f"{python_executable} -c \"import pkg_resources; print(';'.join([(s.key+','+ s.version) for s in pkg_resources.working_set]))\"" from six import StringIO buffer = StringIO() self.run(python_ins_cmd, run_environment= True, env = "conanrun", output=buffer) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 67c420028b..ddc080d748 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -374,8 +374,10 @@ class CuraApplication(QtApplication): app_root = os.path.abspath(os.path.join(os.path.dirname(sys.executable))) Resources.addSecureSearchPath(os.path.join(app_root, "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "Resources", "share", "cura", "resources")) if not hasattr(sys, "frozen"): cura_data_root = os.environ.get('CURA_DATA_ROOT', None) if cura_data_root: @@ -389,6 +391,7 @@ class CuraApplication(QtApplication): # venv site-packages Resources.addSearchPath(os.path.join(app_root, "..", "share", "cura", "resources")) + Resources.addSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) @classmethod def _initializeSettingDefinitions(cls): diff --git a/requirements-dev.txt b/requirements-dev.txt index a1b191009a..162b33bf15 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,5 @@ pytest -pyinstaller==5.8.0 +pyinstaller==6.3.0 pyinstaller-hooks-contrib pyyaml sip==6.5.1 From 18fabe468be1b3b215de67fd68473e0c210d5c19 Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:38:09 +0100 Subject: [PATCH 04/46] Increase part strength of high speed modes by compensating for the slip at high flow rates. PP-386 --- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg | 4 ++++ .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg | 4 ++++ .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg | 4 ++++ .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg | 4 ++++ .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg | 4 ++++ .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg | 4 ++++ .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg | 4 ++++ .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg index 57413c4b30..435af40ae9 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 4 +infill_material_flow = =1.05 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -49,6 +50,7 @@ raft_airgap = 0.15 retraction_amount = 6.5 retraction_prime_speed = 15 retraction_speed = 45 +skin_material_flow = =material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -70,6 +72,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.05 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg index e7e50350c0..29138b1fa1 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 4 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -48,6 +49,7 @@ prime_tower_enable = False retraction_amount = 8 retraction_prime_speed = 15 retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -69,6 +71,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg index dcbb580edb..859289d447 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 6 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -49,6 +50,7 @@ raft_airgap = 0.25 retraction_amount = 6.5 retraction_prime_speed = =retraction_speed retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -70,6 +72,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg index 151af3ed50..8b6af78965 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 6 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -48,6 +49,7 @@ raft_airgap = 0.25 retraction_amount = 6.5 retraction_prime_speed = =retraction_speed retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -69,6 +71,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg index f430e6bc16..c700c42674 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 4 +infill_material_flow = =1.05 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -49,6 +50,7 @@ raft_airgap = 0.15 retraction_amount = 6.5 retraction_prime_speed = 15 retraction_speed = 45 +skin_material_flow = =material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -70,6 +72,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.05 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg index 55696eccb4..cb3419dadc 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 4 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -48,6 +49,7 @@ prime_tower_enable = False retraction_amount = 8 retraction_prime_speed = 15 retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -69,6 +71,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg index 02d22b06b8..ba379b1b05 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 6 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -49,6 +50,7 @@ raft_airgap = 0.25 retraction_amount = 6.5 retraction_prime_speed = =retraction_speed retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -70,6 +72,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg index ee0ee279e6..6f4efb905b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg @@ -28,6 +28,7 @@ bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 cool_min_layer_time = 6 +infill_material_flow = =1.1 * material_flow infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 jerk_infill = =jerk_print @@ -48,6 +49,7 @@ raft_airgap = 0.25 retraction_amount = 6.5 retraction_prime_speed = =retraction_speed retraction_speed = 45 +skin_material_flow = =1.05 * material_flow small_skin_on_surface = False small_skin_width = 4 speed_infill = =speed_print @@ -69,6 +71,8 @@ support_top_distance = =support_z_distance support_z_distance = =math.ceil(0.3/layer_height)*layer_height top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 +wall_x_material_flow = =1.1 * wall_material_flow +wall_x_material_flow_roofing = =wall_material_flow z_seam_relative = True z_seam_type = back zig_zaggify_infill = True From 3fc859c76bb17e7792692fb75c16dba0d288a548 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Thu, 1 Feb 2024 11:34:19 +0100 Subject: [PATCH 05/46] crash while opening printer setting It happened because of creating MachineActionManager as a singleton. Code is refractored to make it work. CURA-11558 --- cura/CuraApplication.py | 17 ++++++++--------- resources/qml/Preferences/MachinesPage.qml | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 67c420028b..08fec4479e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -104,7 +104,8 @@ from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager -from cura.UI import CuraSplashScreen, MachineActionManager, PrintInformation +from cura.UI import CuraSplashScreen, PrintInformation +from cura.UI.MachineActionManager import MachineActionManager from cura.UI.AddPrinterPagesModel import AddPrinterPagesModel from cura.UI.MachineSettingsManager import MachineSettingsManager from cura.UI.ObjectsModel import ObjectsModel @@ -186,7 +187,7 @@ class CuraApplication(QtApplication): self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions] - self._machine_action_manager = None # type: Optional[MachineActionManager.MachineActionManager] + self._machine_action_manager = None # type: Optional[MachineActionManager] self.empty_container = None # type: EmptyInstanceContainer self.empty_definition_changes_container = None # type: EmptyInstanceContainer @@ -352,7 +353,7 @@ class CuraApplication(QtApplication): self.__addAllEmptyContainers() self.__setLatestResouceVersionsForVersionUpgrade() - self._machine_action_manager = MachineActionManager.MachineActionManager(self) + self._machine_action_manager = MachineActionManager(self) self._machine_action_manager.initialize() def __sendCommandToSingleInstance(self): @@ -1129,18 +1130,16 @@ class CuraApplication(QtApplication): self._setting_inheritance_manager = SettingInheritanceManager.createSettingInheritanceManager() return self._setting_inheritance_manager - def getMachineActionManager(self, *args: Any) -> MachineActionManager.MachineActionManager: + @pyqtSlot(result = QObject) + def getMachineActionManager(self, *args: Any) -> MachineActionManager: """Get the machine action manager We ignore any *args given to this, as we also register the machine manager as qml singleton. It wants to give this function an engine and script engine, but we don't care about that. """ - return cast(MachineActionManager.MachineActionManager, self._machine_action_manager) + return self._machine_action_manager - @pyqtSlot(result = QObject) - def getMachineActionManagerQml(self)-> MachineActionManager.MachineActionManager: - return cast(QObject, self._machine_action_manager) @pyqtSlot(result = QObject) def getMaterialManagementModel(self) -> MaterialManagementModel: @@ -1264,7 +1263,7 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(IntentManager, "Cura", 1, 6, self.getIntentManager, "IntentManager") qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, self.getSettingInheritanceManager, "SettingInheritanceManager") qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, self.getSimpleModeSettingsManagerWrapper, "SimpleModeSettingsManager") - qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, self.getMachineActionManagerWrapper, "MachineActionManager") + qmlRegisterSingletonType(MachineActionManager, "Cura", 1, 0, self.getMachineActionManagerWrapper, "MachineActionManager") self.processEvents() qmlRegisterType(NetworkingUtil, "Cura", 1, 5, "NetworkingUtil") diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 971de03696..845c6cf492 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -12,7 +12,7 @@ import Cura 1.0 as Cura UM.ManagementPage { id: base - property var machineActionManager: CuraApplication.getMachineActionManagerQml() + property var machineActionManager: CuraApplication.getMachineActionManager() Item { enabled: false; UM.I18nCatalog { id: catalog; name: "cura"} } title: catalog.i18nc("@title:tab", "Printers") @@ -63,7 +63,7 @@ UM.ManagementPage Repeater { id: machineActionRepeater - model: base.currentItem ? machineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null + model: base.currentItem.id ? machineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null Item { From 8a0914c981ad6d3df1a8bcd963b75521f1bcede9 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Fri, 2 Feb 2024 16:38:02 +0100 Subject: [PATCH 06/46] Adding more paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🥲 CURA-11483 --- cura/CuraApplication.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index ddc080d748..827f0d8598 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -373,11 +373,16 @@ class CuraApplication(QtApplication): Resources.addExpectedDirNameInData(dir_name) app_root = os.path.abspath(os.path.join(os.path.dirname(sys.executable))) + Resources.addSecureSearchPath(os.path.join(app_root, "share", "cura", "resources")) Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "Resources", "share", "cura", "resources")) + Resources.addSecureSearchPath( + os.path.join(self._app_install_dir, "..", "Resources", "share", "cura", "resources")) + if not hasattr(sys, "frozen"): cura_data_root = os.environ.get('CURA_DATA_ROOT', None) if cura_data_root: From c29eb49113a18fa1eb29cdcb56f2d173b2d0d327 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Sun, 4 Feb 2024 22:44:21 +0100 Subject: [PATCH 07/46] Add more `paths` --- plugins/CuraEngineBackend/CuraEngineBackend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 0c4003fadc..66949eeaf5 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -76,6 +76,7 @@ class CuraEngineBackend(QObject, Backend): self._default_engine_location = executable_name search_path = [ + os.path.abspath(os.path.join(os.path.dirname(sys.executable), "..", "Resources")), os.path.abspath(os.path.dirname(sys.executable)), os.path.abspath(os.path.join(os.path.dirname(sys.executable), "bin")), os.path.abspath(os.path.join(os.path.dirname(sys.executable), "..")), From fc081b20e30bc4e978a5103a8a6c6a77e4cf6aed Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Sun, 4 Feb 2024 22:48:55 +0100 Subject: [PATCH 08/46] Remove unused variable --- conanfile.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index 18fe339528..3b48442fa0 100644 --- a/conanfile.py +++ b/conanfile.py @@ -166,8 +166,6 @@ class CuraConan(ConanFile): self.output.info("Collecting python installs") python_installs = {} - python_executable = "python3" if self.settings.os == "Macos" else "python" - # list of python installs run_env = VirtualRunEnv(self) env = run_env.environment() From 7d9a699eb145ee68ada6b793da7584241c564a65 Mon Sep 17 00:00:00 2001 From: Saumya Jain <70144862+saumyaj3@users.noreply.github.com> Date: Mon, 5 Feb 2024 09:07:22 +0100 Subject: [PATCH 09/46] Update cura/CuraApplication.py using modern typing Co-authored-by: Casper Lamboo --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 08fec4479e..508c36bf7c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -187,7 +187,7 @@ class CuraApplication(QtApplication): self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions] - self._machine_action_manager = None # type: Optional[MachineActionManager] + self._machine_action_manager: Optional[MachineActionManager] = None self.empty_container = None # type: EmptyInstanceContainer self.empty_definition_changes_container = None # type: EmptyInstanceContainer From 9d6f80fb86a0d1585bf6d6e86e2053c2a65c4a6b Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Mon, 5 Feb 2024 09:27:01 +0100 Subject: [PATCH 10/46] Also make app bundle for linux/windows --- UltiMaker-Cura.spec.jinja | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index 2c930e6ed6..795de41424 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -69,9 +69,9 @@ coll = COLLECT( name=r'{{ name }}' ) -{% if macos == true %} app = BUNDLE( coll, + {% if macos == true %} name='{{ display_name }}.app', icon={{ icon }}, bundle_identifier={{ osx_bundle_identifier }} + "_" + '{{ display_name }}'.replace(" ", "_") + "_" {{ short_version }}, @@ -90,10 +90,10 @@ app = BUNDLE( 'CFBundleURLSchemes': ['cura', 'slicer'], }], 'CFBundleDocumentTypes': [{ - 'CFBundleTypeRole': 'Viewer', - 'CFBundleTypeExtensions': ['*'], - 'CFBundleTypeName': 'Model Files', - }] - }, + 'CFBundleTypeRole': 'Viewer', + 'CFBundleTypeExtensions': ['*'], + 'CFBundleTypeName': 'Model Files', + }] + }, + {% endif %} ) -{% endif %} From ebea2b46db71f472a7f8080de17ae8c27eb43c87 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Mon, 5 Feb 2024 10:46:34 +0100 Subject: [PATCH 11/46] Only bundle for mac CURA-11483 --- UltiMaker-Cura.spec.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index 795de41424..ec9820fd57 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -69,9 +69,9 @@ coll = COLLECT( name=r'{{ name }}' ) +{% if macos == true %} app = BUNDLE( coll, - {% if macos == true %} name='{{ display_name }}.app', icon={{ icon }}, bundle_identifier={{ osx_bundle_identifier }} + "_" + '{{ display_name }}'.replace(" ", "_") + "_" {{ short_version }}, @@ -95,5 +95,5 @@ app = BUNDLE( 'CFBundleTypeName': 'Model Files', }] }, - {% endif %} ) +{% endif %} From 54d6315f28f1ff0240aea1b9e63cf6f115542838 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Mon, 5 Feb 2024 10:58:19 +0100 Subject: [PATCH 12/46] Fix broken windows/linux builds Due to some breaking changes in pyinstaller upgrade, add option to use old packaging https://github.com/pyinstaller/pyinstaller/pull/7713 CURA-11483 --- UltiMaker-Cura.spec.jinja | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index ec9820fd57..99bfa80078 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -55,7 +55,8 @@ exe = EXE( target_arch={{ target_arch }}, codesign_identity=os.getenv('CODESIGN_IDENTITY', None), entitlements_file={{ entitlements_file }}, - icon={{ icon }} + icon={{ icon }}, + contents_directory='.' ) coll = COLLECT( From 0f6f18e7ddb2db7f9b9851938467070ce5c9ae6b Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Mon, 5 Feb 2024 11:30:15 +0100 Subject: [PATCH 13/46] Clean up some paths CURA-11483 --- cura/CuraApplication.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 827f0d8598..241113ece7 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -374,14 +374,15 @@ class CuraApplication(QtApplication): app_root = os.path.abspath(os.path.join(os.path.dirname(sys.executable))) - Resources.addSecureSearchPath(os.path.join(app_root, "share", "cura", "resources")) - Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) - Resources.addSecureSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) - - Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) - Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "Resources", "share", "cura", "resources")) - Resources.addSecureSearchPath( - os.path.join(self._app_install_dir, "..", "Resources", "share", "cura", "resources")) + if platform.system() == "Darwin": + Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) + Resources.addSecureSearchPath( + os.path.join(self._app_install_dir, "..", "Resources", "share", "cura", "resources")) + else: + Resources.addSecureSearchPath(os.path.join(app_root, "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) + Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) if not hasattr(sys, "frozen"): cura_data_root = os.environ.get('CURA_DATA_ROOT', None) @@ -396,7 +397,6 @@ class CuraApplication(QtApplication): # venv site-packages Resources.addSearchPath(os.path.join(app_root, "..", "share", "cura", "resources")) - Resources.addSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) @classmethod def _initializeSettingDefinitions(cls): From 03abc91bda185549642666f50f833dd14f95df0d Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:35:44 +0100 Subject: [PATCH 14/46] Improved self support z distance settings for Ultimaker PLA, T-PLA, PETG and ABS PP-424 --- .../quality/ultimaker_s3/um_s3_aa0.25_um-abs_0.1mm.inst.cfg | 3 +-- .../quality/ultimaker_s3/um_s3_aa0.25_um-petg_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.25_um-pla_0.1mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.25_um-tough-pla_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.3mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.3mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.3mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.06mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.15mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.1mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.3mm.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 + .../quality/ultimaker_s5/um_s5_aa0.25_um-abs_0.1mm.inst.cfg | 3 +-- .../quality/ultimaker_s5/um_s5_aa0.25_um-petg_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.25_um-pla_0.1mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.25_um-tough-pla_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.3mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.3mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.06mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.15mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.1mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg | 2 +- .../quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.3mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.06mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.15mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.1mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.3mm.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 + 50 files changed, 50 insertions(+), 50 deletions(-) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-abs_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-abs_0.1mm.inst.cfg index 8557b08b1b..24c5a1d9e6 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-abs_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-abs_0.1mm.inst.cfg @@ -27,7 +27,6 @@ acceleration_wall_x = =acceleration_wall bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 -cool_fan_speed_0 = 0 cool_min_layer_time = 4 infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 @@ -65,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-petg_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-petg_0.1mm.inst.cfg index 1aa26ebcfc..e3965d9c5c 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-petg_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-petg_0.1mm.inst.cfg @@ -63,7 +63,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-pla_0.1mm.inst.cfg index 3343f7627a..9589f2f915 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-pla_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-tough-pla_0.1mm.inst.cfg index d0d532f410..b8aec4972f 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_um-tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_um-tough-pla_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.06mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.06mm.inst.cfg index 85dc32801e..de5e0faf2e 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.15mm.inst.cfg index ee0525c13e..c39c6d42c8 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.1mm.inst.cfg index ca1d9d7afc..08bb2befdf 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg index 57413c4b30..9d67113da0 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.2mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.3mm.inst.cfg index 0052ce90cd..cc0da1a253 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-abs_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.06mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.06mm.inst.cfg index 0e9ceaf9e3..7eb5de8b64 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.06mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.15mm.inst.cfg index 8732c3ad63..d4431382dd 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.15mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.1mm.inst.cfg index 6f8db11141..bb7de56356 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg index e7e50350c0..6b333e2f13 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.2mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.3mm.inst.cfg index 5ecaa739db..854b868259 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-petg_0.3mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.06mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.06mm.inst.cfg index 25887f19d7..9678ba9523 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.15mm.inst.cfg index 136a3bed42..c53596bc9f 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.1mm.inst.cfg index e8820673ea..58a8a1ebb0 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg index dcbb580edb..c3139970db 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.2mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.3mm.inst.cfg index fc2a185be4..6f450463b9 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-pla_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.06mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.06mm.inst.cfg index 73f25eae0f..e193aa51c3 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.15mm.inst.cfg index 2aa24f805d..622f2030e4 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.1mm.inst.cfg index e51d440c31..09f02aa375 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg index 151af3ed50..91b522349d 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.2mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.3mm.inst.cfg index 56c097d890..2fd9e5ef2c 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_um-tough-pla_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg index a76864a1a3..2310f2503f 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,6 +69,7 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-abs_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-abs_0.1mm.inst.cfg index d725b5aa15..7b14730a66 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-abs_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-abs_0.1mm.inst.cfg @@ -27,7 +27,6 @@ acceleration_wall_x = =acceleration_wall bridge_skin_speed = =bridge_wall_speed bridge_sparse_infill_max_density = 50 bridge_wall_speed = 30 -cool_fan_speed_0 = 0 cool_min_layer_time = 4 infill_pattern = ='zigzag' if infill_sparse_density > 80 else 'grid' infill_sparse_density = 15 @@ -65,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-petg_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-petg_0.1mm.inst.cfg index 82e07b6fdf..a2233703d4 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-petg_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-petg_0.1mm.inst.cfg @@ -63,7 +63,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-pla_0.1mm.inst.cfg index 789d186f77..44f6670085 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-pla_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-tough-pla_0.1mm.inst.cfg index 307869d494..997f823e51 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_um-tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_um-tough-pla_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.06mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.06mm.inst.cfg index fbe230fb2e..c0b4799ca9 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.15mm.inst.cfg index 9c7ceca13b..d430f867d8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.1mm.inst.cfg index 8ef78a6fb5..b2c25e26c7 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg index f430e6bc16..8a02dfe38c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.2mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.3mm.inst.cfg index 98ca8927b6..9a10024813 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-abs_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.06mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.06mm.inst.cfg index aea8906877..ef58c14663 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.06mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.15mm.inst.cfg index 201c663d5c..5d14f014b9 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.15mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.1mm.inst.cfg index a9d239bf3a..d23a7b8cea 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.1mm.inst.cfg @@ -64,7 +64,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg index 55696eccb4..8bfe117380 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.2mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.3mm.inst.cfg index fe3eeb67ad..ab66eed0ab 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-petg_0.3mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1.2 , layer_height * 6) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.06mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.06mm.inst.cfg index a9043c7372..2b192e8c1c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.15mm.inst.cfg index 713f94219f..11301a2990 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.1mm.inst.cfg index 4e451d4165..1d07e0f63c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg index 02d22b06b8..990271dd9e 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.2mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.3mm.inst.cfg index b0d5d41d0f..a01b433eb2 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-pla_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.06mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.06mm.inst.cfg index 641c1279e4..f368ac13d8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.06mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.15mm.inst.cfg index 55e724da9d..b699ebc9f3 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.15mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.1mm.inst.cfg index 35e8c0903c..d0ee391c65 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.1mm.inst.cfg @@ -65,7 +65,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.3 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg index ee0ee279e6..d9bbd7cc00 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.2mm.inst.cfg @@ -66,7 +66,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.3mm.inst.cfg index 875bd5a669..fc8507c42b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_um-tough-pla_0.3mm.inst.cfg @@ -67,7 +67,7 @@ support_bottom_distance = =support_z_distance support_interface_enable = True support_structure = tree support_top_distance = =support_z_distance -support_z_distance = =math.ceil(0.3/layer_height)*layer_height +support_z_distance = 0.4 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 wall_line_width_0 = =line_width * (1 + magic_spiralize * 0.25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg index 4973ec35bb..b3711c1cbd 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,6 +69,7 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree +support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True From 21517c502589000777d42e0b1c3dcd487e9260bc Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Mon, 5 Feb 2024 13:22:26 +0100 Subject: [PATCH 15/46] Adding openURL in singleinstance --- cura/SingleInstance.py | 6 +++++- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 2 +- packaging/msi/UltiMaker-Cura.wxs.jinja | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index 61ab1204fe..2c3e816767 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -92,7 +92,11 @@ class SingleInstance: # Command: Load a model or project file elif command == "open": - self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) + if payload["filePath"].file(): + self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) + if payload["filePath"].url(): + self._application.callLater(lambda f= payload["filepath"]: self._application._openUrl(f)) + # Command: Activate the window and bring it to the top. elif command == "focus": diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index 0a2ce0f517..2106c47312 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -156,7 +156,7 @@ WriteRegStr HKCR "slicer" "" "URL:slicer" WriteRegStr HKCR "slicer" "URL Protocol" "" WriteRegStr HKCR "slicer\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE},1" WriteRegStr HKCR "slicer\shell" "" "open" -WriteRegStr HKCR "slicer\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" "%1"' +WriteRegStr HKCR "slicer\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" --single-instance "%1"' SectionEnd ###################################################################### diff --git a/packaging/msi/UltiMaker-Cura.wxs.jinja b/packaging/msi/UltiMaker-Cura.wxs.jinja index 21f017c813..13c5d2842e 100644 --- a/packaging/msi/UltiMaker-Cura.wxs.jinja +++ b/packaging/msi/UltiMaker-Cura.wxs.jinja @@ -165,7 +165,7 @@ - + From e554eb264e4e3f44752addcd9079c0257fdb24c3 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Mon, 5 Feb 2024 15:44:46 +0100 Subject: [PATCH 16/46] adding logging for debugging CURA-11596 --- cura/SingleInstance.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index 2c3e816767..ef04ef5ddc 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -52,6 +52,7 @@ class SingleInstance: single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) for filename in self._files_to_open: + Logger.log("i",f"Filename isxxx {os.path(filename)}") payload = {"command": "open", "filePath": os.path.abspath(filename)} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) @@ -73,14 +74,18 @@ class SingleInstance: def _onClientConnected(self) -> None: Logger.log("i", "New connection received on our single-instance server") connection = None #type: Optional[QLocalSocket] + Logger.log("i","getting connection") if self._single_instance_server: connection = self._single_instance_server.nextPendingConnection() + Logger.log("i", f"here: {connection}") if connection is not None: + Logger.log("i","here2") connection.readyRead.connect(lambda c = connection: self.__readCommands(c)) def __readCommands(self, connection: QLocalSocket) -> None: line = connection.readLine() + Logger.log("i", f"line read is {line}") while len(line) != 0: # There is also a .canReadLine() try: payload = json.loads(str(line, encoding = "ascii").strip()) From a5d6ae1c97290a24a6598b0c1d9432028f0b61ee Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:55:33 +0100 Subject: [PATCH 17/46] Bug fix: Do not sett the z distance for the AA0.8 cores of T-PLA. PP-424 --- resources/definitions/fdmprinter.def.json | 12 ------------ .../um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 - .../um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 - 3 files changed, 14 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 03850a7344..31a67d0122 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -6453,18 +6453,6 @@ "settable_per_extruder": true, "limit_to_extruder": "raft_surface_extruder_nr" }, - "raft_surface_monotonic": - { - "label": "Monotonic Raft Top Surface Order", - "description": "Print raft top surface lines in an ordering that causes them to always overlap with adjacent lines in a single direction. This takes slightly more time to print, but makes the surface look more consistent, which is also visible on the model bottom surface.", - "type": "bool", - "default_value": false, - "value": "skin_monotonic", - "enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0", - "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "raft_surface_extruder_nr" - }, "raft_wall_count": { "label": "Raft Wall Count", diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg index 2310f2503f..a76864a1a3 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,7 +69,6 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree -support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg index b3711c1cbd..4973ec35bb 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,7 +69,6 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree -support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True From 4bb5eed97e13f3f178d32f9112a79959d6ef9e25 Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:57:25 +0100 Subject: [PATCH 18/46] Bug fix: Do not sett the z distance for the AA0.8 cores of T-PLA. PP-424 --- .../quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 - .../quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg | 1 - 2 files changed, 2 deletions(-) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg index 2310f2503f..a76864a1a3 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,7 +69,6 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree -support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg index b3711c1cbd..4973ec35bb 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_um-tough-pla_0.2mm.inst.cfg @@ -69,7 +69,6 @@ speed_wall_x_roofing = =speed_roofing support_angle = 70 support_interface_enable = False support_structure = tree -support_z_distance = 0.35 top_bottom_thickness = =max(1 , layer_height * 5) wall_0_wipe_dist = 0.8 z_seam_relative = True From 87cd7a47f5380c7292c4a79eabec6a1a348da6aa Mon Sep 17 00:00:00 2001 From: Frederic Meeuwissen <13856291+Frederic98@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:05:11 +0100 Subject: [PATCH 19/46] Revert "Merge remote-tracking branch 'origin/PP-424-Improve-self-support' into PP-424-Improve-self-support" This reverts commit 0e18407286f9ec1e83548a2bf11386f6667f20fd, reversing changes made to 4bb5eed97e13f3f178d32f9112a79959d6ef9e25. --- resources/definitions/fdmprinter.def.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 31a67d0122..03850a7344 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -6453,6 +6453,18 @@ "settable_per_extruder": true, "limit_to_extruder": "raft_surface_extruder_nr" }, + "raft_surface_monotonic": + { + "label": "Monotonic Raft Top Surface Order", + "description": "Print raft top surface lines in an ordering that causes them to always overlap with adjacent lines in a single direction. This takes slightly more time to print, but makes the surface look more consistent, which is also visible on the model bottom surface.", + "type": "bool", + "default_value": false, + "value": "skin_monotonic", + "enabled": "resolveOrValue('adhesion_type') == 'raft' and raft_surface_layers > 0", + "settable_per_mesh": false, + "settable_per_extruder": true, + "limit_to_extruder": "raft_surface_extruder_nr" + }, "raft_wall_count": { "label": "Raft Wall Count", From 9c57627a8828d45b2336396b29a572eebc9d5a44 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Tue, 6 Feb 2024 12:17:38 +0100 Subject: [PATCH 20/46] Adding command for opening url CURA-11596 --- cura/SingleInstance.py | 3 --- packaging/msi/UltiMaker-Cura.wxs.jinja | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index ef04ef5ddc..fb85e258db 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -74,13 +74,10 @@ class SingleInstance: def _onClientConnected(self) -> None: Logger.log("i", "New connection received on our single-instance server") connection = None #type: Optional[QLocalSocket] - Logger.log("i","getting connection") if self._single_instance_server: connection = self._single_instance_server.nextPendingConnection() - Logger.log("i", f"here: {connection}") if connection is not None: - Logger.log("i","here2") connection.readyRead.connect(lambda c = connection: self.__readCommands(c)) def __readCommands(self, connection: QLocalSocket) -> None: diff --git a/packaging/msi/UltiMaker-Cura.wxs.jinja b/packaging/msi/UltiMaker-Cura.wxs.jinja index 13c5d2842e..1f22dcc8bc 100644 --- a/packaging/msi/UltiMaker-Cura.wxs.jinja +++ b/packaging/msi/UltiMaker-Cura.wxs.jinja @@ -166,6 +166,8 @@ + + From d8cc99bf0deb951d32059e47b7690a0c76babfcb Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Tue, 6 Feb 2024 13:00:31 +0100 Subject: [PATCH 21/46] Remove duplicate paths CURA-11483 --- cura/CuraApplication.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 241113ece7..0cc3d20d58 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -376,13 +376,11 @@ class CuraApplication(QtApplication): if platform.system() == "Darwin": Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) - Resources.addSecureSearchPath(os.path.join(app_root, "..", "Resources", "share", "cura", "resources")) Resources.addSecureSearchPath( - os.path.join(self._app_install_dir, "..", "Resources", "share", "cura", "resources")) + os.path.join(self._app_install_dir, "Resources", "share", "cura", "resources")) else: Resources.addSecureSearchPath(os.path.join(app_root, "share", "cura", "resources")) Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) - Resources.addSecureSearchPath(os.path.join(app_root, "Resources", "share", "cura", "resources")) if not hasattr(sys, "frozen"): cura_data_root = os.environ.get('CURA_DATA_ROOT', None) From 8073bc0e50473ada7828d707674c9d3822f59b70 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Tue, 6 Feb 2024 16:04:08 +0100 Subject: [PATCH 22/46] adding this preference in mac-os doesn't work. It always opens it up in singlenstance CURA-11596 --- resources/qml/Preferences/GeneralPage.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 8871944523..0a430eda5d 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -627,6 +627,7 @@ UM.PreferencesPage UM.TooltipArea { width: childrenRect.width + visible: Qt.platform.os !== "osx" height: childrenRect.height text: catalog.i18nc("@info:tooltip","Should opening files from the desktop or external applications open in the same instance of Cura?") From eff45842038373ab436ca67e9fc2173458a09eb5 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Tue, 6 Feb 2024 16:05:34 +0100 Subject: [PATCH 23/46] adding files in single instance in case of url CURA-11596 --- cura/CuraApplication.py | 2 +- cura/SingleInstance.py | 33 ++++++++++++++----------- packaging/NSIS/Ultimaker-Cura.nsi.jinja | 2 +- packaging/msi/UltiMaker-Cura.wxs.jinja | 4 +-- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 67c420028b..bae609c07b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -356,7 +356,7 @@ class CuraApplication(QtApplication): self._machine_action_manager.initialize() def __sendCommandToSingleInstance(self): - self._single_instance = SingleInstance(self, self._files_to_open) + self._single_instance = SingleInstance(self, self._files_to_open, self._open_url_queue) # If we use single instance, try to connect to the single instance server, send commands, and then exit. # If we cannot find an existing single instance server, this is the only instance, so just keep going. diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index fb85e258db..02fa6622aa 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -7,14 +7,15 @@ from typing import List, Optional from PyQt6.QtNetwork import QLocalServer, QLocalSocket -from UM.Qt.QtApplication import QtApplication #For typing. +from UM.Qt.QtApplication import QtApplication # For typing. from UM.Logger import Logger class SingleInstance: - def __init__(self, application: QtApplication, files_to_open: Optional[List[str]]) -> None: + def __init__(self, application: QtApplication, files_to_open: Optional[List[str]], url_to_open: Optional[List[str]]) -> None: self._application = application self._files_to_open = files_to_open + self._url_to_open = url_to_open self._single_instance_server = None @@ -33,7 +34,7 @@ class SingleInstance: return False # We only send the files that need to be opened. - if not self._files_to_open: + if not self._files_to_open or not self._url_to_open: Logger.log("i", "No file need to be opened, do nothing.") return True @@ -46,18 +47,21 @@ class SingleInstance: if self._application.getPreferences().getValue("cura/single_instance_clear_before_load"): payload = {"command": "clear-all"} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) payload = {"command": "focus"} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) for filename in self._files_to_open: - Logger.log("i",f"Filename isxxx {os.path(filename)}") payload = {"command": "open", "filePath": os.path.abspath(filename)} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) + + for filename in self._url_to_open: + payload = {"command": "open", "urlPath": os.path.abspath(filename)} + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) payload = {"command": "close-connection"} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) single_instance_socket.flush() single_instance_socket.waitForDisconnected() @@ -73,7 +77,7 @@ class SingleInstance: def _onClientConnected(self) -> None: Logger.log("i", "New connection received on our single-instance server") - connection = None #type: Optional[QLocalSocket] + connection = None # type: Optional[QLocalSocket] if self._single_instance_server: connection = self._single_instance_server.nextPendingConnection() @@ -82,10 +86,9 @@ class SingleInstance: def __readCommands(self, connection: QLocalSocket) -> None: line = connection.readLine() - Logger.log("i", f"line read is {line}") - while len(line) != 0: # There is also a .canReadLine() + while len(line) != 0: # There is also a .canReadLine() try: - payload = json.loads(str(line, encoding = "ascii").strip()) + payload = json.loads(str(line, encoding="ascii").strip()) command = payload["command"] # Command: Remove all models from the build plate. @@ -96,8 +99,8 @@ class SingleInstance: elif command == "open": if payload["filePath"].file(): self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) - if payload["filePath"].url(): - self._application.callLater(lambda f= payload["filepath"]: self._application._openUrl(f)) + if payload["urlPath"].url(): + self._application.callLater(lambda f = payload["urlPath"]: self._application._openUrl(f)) # Command: Activate the window and bring it to the top. @@ -106,7 +109,7 @@ class SingleInstance: # 'alert' or flashing the icon in the taskbar is the best thing we do now. main_window = self._application.getMainWindow() if main_window is not None: - self._application.callLater(lambda: main_window.alert(0)) # type: ignore # I don't know why MyPy complains here + self._application.callLater(lambda: main_window.alert(0)) # type: ignore # I don't know why MyPy complains here # Command: Close the socket connection. We're done. elif command == "close-connection": diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index 2106c47312..0a2ce0f517 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -156,7 +156,7 @@ WriteRegStr HKCR "slicer" "" "URL:slicer" WriteRegStr HKCR "slicer" "URL Protocol" "" WriteRegStr HKCR "slicer\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE},1" WriteRegStr HKCR "slicer\shell" "" "open" -WriteRegStr HKCR "slicer\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" --single-instance "%1"' +WriteRegStr HKCR "slicer\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" "%1"' SectionEnd ###################################################################### diff --git a/packaging/msi/UltiMaker-Cura.wxs.jinja b/packaging/msi/UltiMaker-Cura.wxs.jinja index 1f22dcc8bc..21f017c813 100644 --- a/packaging/msi/UltiMaker-Cura.wxs.jinja +++ b/packaging/msi/UltiMaker-Cura.wxs.jinja @@ -165,9 +165,7 @@ - - - + From 664fa4f48d215d9cf52e5f2437bd0ac21a1f9ba5 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Tue, 6 Feb 2024 16:19:01 +0100 Subject: [PATCH 24/46] assigning different command for opening url CURA-11596 --- cura/SingleInstance.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index 02fa6622aa..3357d22d30 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -56,8 +56,8 @@ class SingleInstance: payload = {"command": "open", "filePath": os.path.abspath(filename)} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) - for filename in self._url_to_open: - payload = {"command": "open", "urlPath": os.path.abspath(filename)} + for url in self._url_to_open: + payload = {"command": "open-url", "urlPath": url} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) payload = {"command": "close-connection"} @@ -88,7 +88,7 @@ class SingleInstance: line = connection.readLine() while len(line) != 0: # There is also a .canReadLine() try: - payload = json.loads(str(line, encoding="ascii").strip()) + payload = json.loads(str(line, encoding = "ascii").strip()) command = payload["command"] # Command: Remove all models from the build plate. @@ -97,10 +97,11 @@ class SingleInstance: # Command: Load a model or project file elif command == "open": - if payload["filePath"].file(): - self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) - if payload["urlPath"].url(): - self._application.callLater(lambda f = payload["urlPath"]: self._application._openUrl(f)) + self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) + + #command: Load a url link in Cura + elif command == "open-url": + self._application.callLater(lambda f = payload["urlPath"]: self._application._openUrl(f)) # Command: Activate the window and bring it to the top. From bb28a7c5063666b138be862acd607e0fa47a8d42 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 7 Feb 2024 11:00:54 +0100 Subject: [PATCH 25/46] fixing the if condition CURA-11596 --- cura/SingleInstance.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index 3357d22d30..c4590fc275 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -5,6 +5,7 @@ import json import os from typing import List, Optional +from PyQt6.QtCore import QUrl from PyQt6.QtNetwork import QLocalServer, QLocalSocket from UM.Qt.QtApplication import QtApplication # For typing. @@ -34,7 +35,7 @@ class SingleInstance: return False # We only send the files that need to be opened. - if not self._files_to_open or not self._url_to_open: + if not self._files_to_open and not self._url_to_open: Logger.log("i", "No file need to be opened, do nothing.") return True @@ -47,17 +48,17 @@ class SingleInstance: if self._application.getPreferences().getValue("cura/single_instance_clear_before_load"): payload = {"command": "clear-all"} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) payload = {"command": "focus"} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) for filename in self._files_to_open: payload = {"command": "open", "filePath": os.path.abspath(filename)} - single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) + single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) for url in self._url_to_open: - payload = {"command": "open-url", "urlPath": url} + payload = {"command": "open-url", "urlPath": url.toString()} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ascii")) payload = {"command": "close-connection"} @@ -82,10 +83,12 @@ class SingleInstance: connection = self._single_instance_server.nextPendingConnection() if connection is not None: + x = self.__readCommands(connection) connection.readyRead.connect(lambda c = connection: self.__readCommands(c)) def __readCommands(self, connection: QLocalSocket) -> None: line = connection.readLine() + print(f"line is {line}") while len(line) != 0: # There is also a .canReadLine() try: payload = json.loads(str(line, encoding = "ascii").strip()) @@ -101,7 +104,8 @@ class SingleInstance: #command: Load a url link in Cura elif command == "open-url": - self._application.callLater(lambda f = payload["urlPath"]: self._application._openUrl(f)) + url = QUrl(payload["urlPath"]) + self._application.callLater(lambda f = url: self._application._openUrl(f)) # Command: Activate the window and bring it to the top. From 206b53072465273db18be15ca398ae116157dbb1 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 7 Feb 2024 11:05:48 +0100 Subject: [PATCH 26/46] Removing debug statement CURA-11596 --- cura/SingleInstance.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index c4590fc275..c081044201 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -88,7 +88,6 @@ class SingleInstance: def __readCommands(self, connection: QLocalSocket) -> None: line = connection.readLine() - print(f"line is {line}") while len(line) != 0: # There is also a .canReadLine() try: payload = json.loads(str(line, encoding = "ascii").strip()) From 313a7f7068ef494e4e1b6f4fd84669434340302a Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 7 Feb 2024 12:16:01 +0100 Subject: [PATCH 27/46] remove debug statement CURA-11596 --- cura/SingleInstance.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index c081044201..8c4018a4f7 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -83,7 +83,6 @@ class SingleInstance: connection = self._single_instance_server.nextPendingConnection() if connection is not None: - x = self.__readCommands(connection) connection.readyRead.connect(lambda c = connection: self.__readCommands(c)) def __readCommands(self, connection: QLocalSocket) -> None: From d2e8999e453eacc6bfcc633592c2249d1d730b2a Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 7 Feb 2024 15:20:52 +0100 Subject: [PATCH 28/46] creating pyqtslot for desired functionality CURA-11596 --- cura/CuraApplication.py | 4 ++++ resources/qml/Preferences/MachinesPage.qml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index edf4353ae8..f8b3894ed9 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1101,6 +1101,10 @@ class CuraApplication(QtApplication): self._object_manager = ObjectsModel(self) return self._object_manager + @pyqtSlot(str, result = "QVariantList") + def getSupportedActionMachineList(self, definition_id: str) -> List["MachineAction"]: + return self._machine_action_manager.getSupportedActions(self._machine_manager.getDefinitionByMachineId(definition_id)) + @pyqtSlot(result = QObject) def getExtrudersModel(self, *args) -> "ExtrudersModel": if self._extruders_model is None: diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 845c6cf492..1e287e74a0 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -12,7 +12,6 @@ import Cura 1.0 as Cura UM.ManagementPage { id: base - property var machineActionManager: CuraApplication.getMachineActionManager() Item { enabled: false; UM.I18nCatalog { id: catalog; name: "cura"} } title: catalog.i18nc("@title:tab", "Printers") @@ -63,7 +62,7 @@ UM.ManagementPage Repeater { id: machineActionRepeater - model: base.currentItem.id ? machineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null + model: base.currentItem ? CuraApplication.getSupportedActionMachineList(base.currentItem.id) : null Item { From cf1a7889c237a25e92f6307572e750d4dc3ae822 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 7 Feb 2024 17:01:56 +0100 Subject: [PATCH 29/46] mimicing behavior as files to open CURA-11596 --- cura/CuraApplication.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8a87ba448c..51ceecd7dd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -180,6 +180,7 @@ class CuraApplication(QtApplication): # Variables set from CLI self._files_to_open = [] + self._urls_to_open = [] self._use_single_instance = False self._single_instance = None @@ -334,7 +335,7 @@ class CuraApplication(QtApplication): for filename in self._cli_args.file: url = QUrl(filename) if url.scheme() in self._supported_url_schemes: - self._open_url_queue.append(url) + self._urls_to_open.append(url) else: self._files_to_open.append(os.path.abspath(filename)) @@ -357,7 +358,7 @@ class CuraApplication(QtApplication): self._machine_action_manager.initialize() def __sendCommandToSingleInstance(self): - self._single_instance = SingleInstance(self, self._files_to_open, self._open_url_queue) + self._single_instance = SingleInstance(self, self._files_to_open, self._urls_to_open) # If we use single instance, try to connect to the single instance server, send commands, and then exit. # If we cannot find an existing single instance server, this is the only instance, so just keep going. @@ -963,6 +964,8 @@ class CuraApplication(QtApplication): self.callLater(self._openFile, file_name) for file_name in self._open_file_queue: # Open all the files that were queued up while plug-ins were loading. self.callLater(self._openFile, file_name) + for url in self._urls_to_open: + self.callLater(self._openUrl, url) for url in self._open_url_queue: self.callLater(self._openUrl, url) From 495be39d1f7b4c62419edd5742a497f123c2f741 Mon Sep 17 00:00:00 2001 From: Saumya Jain <70144862+saumyaj3@users.noreply.github.com> Date: Thu, 8 Feb 2024 10:51:49 +0100 Subject: [PATCH 30/46] Update cura/SingleInstance.py Co-authored-by: Casper Lamboo --- cura/SingleInstance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index 8c4018a4f7..0448ddc647 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -103,7 +103,7 @@ class SingleInstance: #command: Load a url link in Cura elif command == "open-url": url = QUrl(payload["urlPath"]) - self._application.callLater(lambda f = url: self._application._openUrl(f)) + self._application.callLater(lambda: self._application._openUrl(url)) # Command: Activate the window and bring it to the top. From a251a5d2ca1cdba0a1d8971968b49f5076720c95 Mon Sep 17 00:00:00 2001 From: Saumya Jain <70144862+saumyaj3@users.noreply.github.com> Date: Thu, 8 Feb 2024 10:51:56 +0100 Subject: [PATCH 31/46] Update resources/qml/Preferences/GeneralPage.qml Co-authored-by: Casper Lamboo --- resources/qml/Preferences/GeneralPage.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 0a430eda5d..c313ffbd94 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -627,6 +627,7 @@ UM.PreferencesPage UM.TooltipArea { width: childrenRect.width + // Mac only allows applications to run as a single instance, so providing the option for this os doesn't make much sense visible: Qt.platform.os !== "osx" height: childrenRect.height text: catalog.i18nc("@info:tooltip","Should opening files from the desktop or external applications open in the same instance of Cura?") From 2d82bb94abc92d5ff2e4e0a60e307d44d5cbd8b2 Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:20:02 +0100 Subject: [PATCH 32/46] Set retraction_min_travel to 5mm for all S-line and Method machines. This improves the infill pattern wall overlaps (for TPU top surfaces and raft base layers) and reduces the amount of retracts in tree supports islands. It also cleans up the settings. PP-389 --- resources/definitions/ultimaker.def.json | 1 + resources/definitions/ultimaker3.def.json | 1 - resources/definitions/ultimaker_method_base.def.json | 1 - resources/definitions/ultimaker_s3.def.json | 1 - resources/definitions/ultimaker_s5.def.json | 1 - resources/quality/ultimaker_s3/um_s3_aa0.25_nylon_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.25_pc_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.25_pp_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.06mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.3mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.4mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.3mm.inst.cfg | 1 - resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.4mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.25_nylon_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.25_pc_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.25_pp_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.06mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.15mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.1mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.3mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.4mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.2mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.3mm.inst.cfg | 1 - resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.4mm.inst.cfg | 1 - resources/variants/ultimaker_s3_aa0.25.inst.cfg | 1 - resources/variants/ultimaker_s3_aa0.8.inst.cfg | 1 - resources/variants/ultimaker_s3_aa04.inst.cfg | 1 - resources/variants/ultimaker_s3_bb0.8.inst.cfg | 1 - resources/variants/ultimaker_s3_bb04.inst.cfg | 1 - resources/variants/ultimaker_s3_cc04.inst.cfg | 1 - resources/variants/ultimaker_s3_cc06.inst.cfg | 1 - resources/variants/ultimaker_s5_aa0.25.inst.cfg | 1 - resources/variants/ultimaker_s5_aa0.8.inst.cfg | 1 - resources/variants/ultimaker_s5_aa04.inst.cfg | 1 - resources/variants/ultimaker_s5_bb0.8.inst.cfg | 1 - resources/variants/ultimaker_s5_bb04.inst.cfg | 1 - resources/variants/ultimaker_s5_cc04.inst.cfg | 1 - resources/variants/ultimaker_s5_cc06.inst.cfg | 1 - resources/variants/ultimaker_s7_aa0.25.inst.cfg | 1 - resources/variants/ultimaker_s7_aa0.8.inst.cfg | 1 - resources/variants/ultimaker_s7_aa04.inst.cfg | 1 - resources/variants/ultimaker_s7_bb0.8.inst.cfg | 1 - resources/variants/ultimaker_s7_bb04.inst.cfg | 1 - resources/variants/ultimaker_s7_cc04.inst.cfg | 1 - resources/variants/ultimaker_s7_cc06.inst.cfg | 1 - 64 files changed, 1 insertion(+), 63 deletions(-) diff --git a/resources/definitions/ultimaker.def.json b/resources/definitions/ultimaker.def.json index 1669dd5e00..dae64cea6b 100644 --- a/resources/definitions/ultimaker.def.json +++ b/resources/definitions/ultimaker.def.json @@ -106,6 +106,7 @@ "retraction_combing_max_distance": { "value": 15 }, "retraction_count_max": { "value": 25 }, "retraction_extrusion_window": { "value": 1 }, + "retraction_min_travel": { "value": 5 }, "roofing_layer_count": { "value": "1" }, "roofing_material_flow": { "value": "material_flow" }, "skin_angles": { "value": "[] if infill_pattern not in ['cross', 'cross_3d'] else [20, 110]" }, diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 19df92c08d..17a4b6045e 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -156,7 +156,6 @@ "retraction_hop": { "value": "2" }, "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" }, "retraction_hop_only_when_collides": { "value": "True" }, - "retraction_min_travel": { "value": "5" }, "retraction_prime_speed": { "value": "15" }, "skin_overlap": { "value": "10" }, "speed_prime_tower": { "value": "speed_topbottom" }, diff --git a/resources/definitions/ultimaker_method_base.def.json b/resources/definitions/ultimaker_method_base.def.json index f0808c529e..6e40f0bbf1 100644 --- a/resources/definitions/ultimaker_method_base.def.json +++ b/resources/definitions/ultimaker_method_base.def.json @@ -373,7 +373,6 @@ "retraction_hop": { "value": 0.4 }, "retraction_hop_enabled": { "value": true }, "retraction_hop_only_when_collides": { "value": false }, - "retraction_min_travel": { "value": "line_width * 4" }, "retraction_prime_speed": { "value": "retraction_speed" }, "retraction_speed": { "value": 5 }, "roofing_layer_count": { "value": 2 }, diff --git a/resources/definitions/ultimaker_s3.def.json b/resources/definitions/ultimaker_s3.def.json index add1782368..483825df5a 100644 --- a/resources/definitions/ultimaker_s3.def.json +++ b/resources/definitions/ultimaker_s3.def.json @@ -108,7 +108,6 @@ "retraction_hop": { "value": "2" }, "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" }, "retraction_hop_only_when_collides": { "value": "True" }, - "retraction_min_travel": { "value": "5" }, "retraction_prime_speed": { "value": "15" }, "retraction_speed": { "value": "45" }, "speed_prime_tower": { "value": "speed_topbottom" }, diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json index ec82e6b630..cd48c4fd38 100644 --- a/resources/definitions/ultimaker_s5.def.json +++ b/resources/definitions/ultimaker_s5.def.json @@ -110,7 +110,6 @@ "retraction_hop": { "value": "2" }, "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" }, "retraction_hop_only_when_collides": { "value": "True" }, - "retraction_min_travel": { "value": "5" }, "retraction_prime_speed": { "value": "15" }, "retraction_speed": { "value": "45" }, "speed_prime_tower": { "value": "speed_topbottom" }, diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_nylon_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_nylon_0.1mm.inst.cfg index c6d99b63b5..e0d3aa4d50 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_nylon_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_nylon_0.1mm.inst.cfg @@ -17,7 +17,6 @@ machine_nozzle_heat_up_speed = 1.4 material_print_temperature = =default_material_print_temperature - 20 ooze_shield_angle = 40 raft_airgap = 0.4 -retraction_min_travel = 5 speed_print = 70 speed_topbottom = =math.ceil(speed_print * 30 / 70) speed_wall = =math.ceil(speed_print * 30 / 70) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_pc_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_pc_0.1mm.inst.cfg index ec86494397..369cbcd563 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_pc_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_pc_0.1mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.25_pp_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.25_pp_0.1mm.inst.cfg index 77082932a5..6485844da8 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.25_pp_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.25_pp_0.1mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.2 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 retraction_prime_speed = 15 speed_print = 25 speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.06mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.06mm.inst.cfg index f46f816cfb..c9eebee8a0 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.06mm.inst.cfg @@ -26,7 +26,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.15mm.inst.cfg index 2c23449373..bcd04f4b24 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.15mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.1mm.inst.cfg index e0899c8dc2..278e502231 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.1mm.inst.cfg @@ -26,7 +26,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.2mm.inst.cfg index 329bd095d5..1baf43933c 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pc_0.2mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.15mm.inst.cfg index eee8fc31b6..3b106196f2 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.15mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.1mm.inst.cfg index fa87825718..455338a901 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.1mm.inst.cfg @@ -29,7 +29,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.2mm.inst.cfg index 6c90ec685f..b1f5e1f19a 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_pp_0.2mm.inst.cfg @@ -29,7 +29,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.15mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.15mm.inst.cfg index 15018203e9..601886a065 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.15mm.inst.cfg @@ -28,7 +28,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.1mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.1mm.inst.cfg index 1b9912c1d6..bb303eeb33 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.1mm.inst.cfg @@ -29,7 +29,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.2mm.inst.cfg index 971cee7b3a..85c37d439d 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.4_tpu_0.2mm.inst.cfg @@ -28,7 +28,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.2mm.inst.cfg index 163f32a36d..7619fcf43d 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.2mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 10 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_wall_x = =math.ceil(speed_wall * 30 / 30) switch_extruder_prime_speed = 15 diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.3mm.inst.cfg index 3f75c3366e..b157ed198c 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.3mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 15 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_wall_x = =math.ceil(speed_wall * 30 / 30) switch_extruder_prime_speed = 15 diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.4mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.4mm.inst.cfg index b2c5dab3c4..550a26c7f8 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.4mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_pp_0.4mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 20 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_infill = =math.ceil(speed_wall * 30 / 30) speed_wall_x = =math.ceil(speed_wall * 30 / 30) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.2mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.2mm.inst.cfg index 75949f45aa..5d6ce58f7c 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.2mm.inst.cfg @@ -27,7 +27,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 speed_print = 30 speed_topbottom = =math.ceil(speed_print * 25 / 30) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.3mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.3mm.inst.cfg index 034bda5d09..1b69ada75d 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.3mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 speed_print = 30 speed_topbottom = =math.ceil(speed_print * 23 / 30) diff --git a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.4mm.inst.cfg b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.4mm.inst.cfg index e7189d5467..d678d7e178 100644 --- a/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.4mm.inst.cfg +++ b/resources/quality/ultimaker_s3/um_s3_aa0.8_tpu_0.4mm.inst.cfg @@ -27,7 +27,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 speed_infill = =speed_print speed_print = 30 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_nylon_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_nylon_0.1mm.inst.cfg index 38267fcf24..ea86a9a9a6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_nylon_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_nylon_0.1mm.inst.cfg @@ -17,7 +17,6 @@ machine_nozzle_heat_up_speed = 1.4 material_print_temperature = =default_material_print_temperature - 20 ooze_shield_angle = 40 raft_airgap = 0.4 -retraction_min_travel = 5 speed_print = 70 speed_topbottom = =math.ceil(speed_print * 30 / 70) speed_wall = =math.ceil(speed_print * 30 / 70) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_pc_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_pc_0.1mm.inst.cfg index 5779142162..eef6e66a5e 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_pc_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_pc_0.1mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_pp_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_pp_0.1mm.inst.cfg index 64b1be79aa..56689c4bfa 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_pp_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_pp_0.1mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.2 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 retraction_prime_speed = 15 speed_print = 25 speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.06mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.06mm.inst.cfg index 0b471a8c75..c58107dcf9 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.06mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.06mm.inst.cfg @@ -26,7 +26,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.15mm.inst.cfg index 6c9710e436..b210b894e5 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.15mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.1mm.inst.cfg index 945b77e699..aa17d35a97 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.1mm.inst.cfg @@ -26,7 +26,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.2mm.inst.cfg index b523e3c646..616443b129 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pc_0.2mm.inst.cfg @@ -25,7 +25,6 @@ prime_tower_wipe_enabled = True raft_airgap = 0.25 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 50 speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.15mm.inst.cfg index 85e892628d..8eb0d257d6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.15mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.1mm.inst.cfg index 531f946ba8..bd4dd317bb 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.1mm.inst.cfg @@ -29,7 +29,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.2mm.inst.cfg index a7f63a76b1..1e5ea9efb6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_pp_0.2mm.inst.cfg @@ -29,7 +29,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 speed_print = 25 speed_topbottom = =math.ceil(speed_print * 25 / 25) speed_wall = =math.ceil(speed_print * 25 / 25) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.15mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.15mm.inst.cfg index 0b69ae0c43..db01865cf8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.15mm.inst.cfg @@ -28,7 +28,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.1mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.1mm.inst.cfg index 29aa42a436..27a8bb863b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.1mm.inst.cfg @@ -29,7 +29,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.2mm.inst.cfg index 48e6ffb81b..cf3069ee0f 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_tpu_0.2mm.inst.cfg @@ -28,7 +28,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 15 retraction_extra_prime_amount = 0.8 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 skin_line_width = =round(line_width / 0.8, 2) speed_print = 25 speed_topbottom = =math.ceil(speed_print * 0.8) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.2mm.inst.cfg index 149104700e..c338c4b7ff 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.2mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 10 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_wall_x = =math.ceil(speed_wall * 30 / 30) switch_extruder_prime_speed = 15 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.3mm.inst.cfg index 670ec78d51..62d9eb235d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.3mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 15 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_wall_x = =math.ceil(speed_wall * 30 / 30) switch_extruder_prime_speed = 15 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.4mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.4mm.inst.cfg index c9b5c26d64..b2792b6fee 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.4mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_pp_0.4mm.inst.cfg @@ -24,7 +24,6 @@ prime_tower_min_volume = 20 retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 0.5 -retraction_min_travel = 1.5 retraction_prime_speed = 15 speed_infill = =math.ceil(speed_wall * 30 / 30) speed_wall_x = =math.ceil(speed_wall * 30 / 30) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.2mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.2mm.inst.cfg index 43436cd4c7..2491d0ed88 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.2mm.inst.cfg @@ -27,7 +27,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 speed_print = 30 speed_topbottom = =math.ceil(speed_print * 25 / 30) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.3mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.3mm.inst.cfg index 58b524dd2a..e975175ce0 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.3mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.3mm.inst.cfg @@ -28,7 +28,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 speed_print = 30 speed_topbottom = =math.ceil(speed_print * 23 / 30) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.4mm.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.4mm.inst.cfg index d17ec5486a..5334fac1f0 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.4mm.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_tpu_0.4mm.inst.cfg @@ -27,7 +27,6 @@ retraction_count_max = 15 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = =line_width * 2 speed_infill = =speed_print speed_print = 30 speed_topbottom = =math.ceil(speed_print * 20 / 30) diff --git a/resources/variants/ultimaker_s3_aa0.25.inst.cfg b/resources/variants/ultimaker_s3_aa0.25.inst.cfg index 1f3baa432f..97b303035c 100644 --- a/resources/variants/ultimaker_s3_aa0.25.inst.cfg +++ b/resources/variants/ultimaker_s3_aa0.25.inst.cfg @@ -16,7 +16,6 @@ machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = AA 0.25 machine_nozzle_size = 0.25 machine_nozzle_tip_outer_diameter = 0.65 -retraction_min_travel = 0.7 retraction_prime_speed = =retraction_speed speed_print = 55 speed_topbottom = 20 diff --git a/resources/variants/ultimaker_s3_aa0.8.inst.cfg b/resources/variants/ultimaker_s3_aa0.8.inst.cfg index c30365897b..e7d3487503 100644 --- a/resources/variants/ultimaker_s3_aa0.8.inst.cfg +++ b/resources/variants/ultimaker_s3_aa0.8.inst.cfg @@ -29,7 +29,6 @@ raft_surface_layers = 1 retraction_amount = 6.5 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 retraction_speed = 25 speed_print = 35 speed_topbottom = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s3_aa04.inst.cfg b/resources/variants/ultimaker_s3_aa04.inst.cfg index b3f76758f4..76992b5805 100644 --- a/resources/variants/ultimaker_s3_aa04.inst.cfg +++ b/resources/variants/ultimaker_s3_aa04.inst.cfg @@ -14,7 +14,6 @@ machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 -retraction_min_travel = =line_width * 2 speed_print = 70 speed_topbottom = =math.ceil(speed_print * 30 / 70) speed_wall = =math.ceil(speed_print * 30 / 70) diff --git a/resources/variants/ultimaker_s3_bb0.8.inst.cfg b/resources/variants/ultimaker_s3_bb0.8.inst.cfg index 34e1b6d308..d0f78ac3bd 100644 --- a/resources/variants/ultimaker_s3_bb0.8.inst.cfg +++ b/resources/variants/ultimaker_s3_bb0.8.inst.cfg @@ -30,7 +30,6 @@ prime_tower_wipe_enabled = True raft_surface_layers = 1 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 3 speed_prime_tower = =math.ceil(speed_print * 7 / 35) speed_print = 35 speed_support = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s3_bb04.inst.cfg b/resources/variants/ultimaker_s3_bb04.inst.cfg index e50241aa3a..4e232cbb5e 100644 --- a/resources/variants/ultimaker_s3_bb04.inst.cfg +++ b/resources/variants/ultimaker_s3_bb04.inst.cfg @@ -16,7 +16,6 @@ acceleration_support_interface = =math.ceil(acceleration_support * 1500 / 2000) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 -retraction_min_travel = =3 * line_width speed_prime_tower = =math.ceil(speed_print * 10 / 35) speed_support = =math.ceil(speed_print * 25 / 35) speed_support_interface = =math.ceil(speed_support * 20 / 25) diff --git a/resources/variants/ultimaker_s3_cc04.inst.cfg b/resources/variants/ultimaker_s3_cc04.inst.cfg index 19192bfba6..38f04547aa 100644 --- a/resources/variants/ultimaker_s3_cc04.inst.cfg +++ b/resources/variants/ultimaker_s3_cc04.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.4 machine_nozzle_size = 0.4 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 diff --git a/resources/variants/ultimaker_s3_cc06.inst.cfg b/resources/variants/ultimaker_s3_cc06.inst.cfg index 925a9f68d6..e42817e8f8 100644 --- a/resources/variants/ultimaker_s3_cc06.inst.cfg +++ b/resources/variants/ultimaker_s3_cc06.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.6 machine_nozzle_size = 0.6 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 diff --git a/resources/variants/ultimaker_s5_aa0.25.inst.cfg b/resources/variants/ultimaker_s5_aa0.25.inst.cfg index 519b21c920..08ed6132f5 100644 --- a/resources/variants/ultimaker_s5_aa0.25.inst.cfg +++ b/resources/variants/ultimaker_s5_aa0.25.inst.cfg @@ -16,7 +16,6 @@ machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = AA 0.25 machine_nozzle_size = 0.25 machine_nozzle_tip_outer_diameter = 0.65 -retraction_min_travel = 0.7 retraction_prime_speed = =retraction_speed speed_print = 55 speed_topbottom = 20 diff --git a/resources/variants/ultimaker_s5_aa0.8.inst.cfg b/resources/variants/ultimaker_s5_aa0.8.inst.cfg index b482c418f0..04a3a97d11 100644 --- a/resources/variants/ultimaker_s5_aa0.8.inst.cfg +++ b/resources/variants/ultimaker_s5_aa0.8.inst.cfg @@ -29,7 +29,6 @@ raft_surface_layers = 1 retraction_amount = 6.5 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 retraction_speed = 25 speed_print = 35 speed_topbottom = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s5_aa04.inst.cfg b/resources/variants/ultimaker_s5_aa04.inst.cfg index 09f528162d..fd4f1ff778 100644 --- a/resources/variants/ultimaker_s5_aa04.inst.cfg +++ b/resources/variants/ultimaker_s5_aa04.inst.cfg @@ -14,7 +14,6 @@ machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 -retraction_min_travel = =line_width * 2 speed_print = 70 speed_topbottom = =math.ceil(speed_print * 30 / 70) speed_wall = =math.ceil(speed_print * 30 / 70) diff --git a/resources/variants/ultimaker_s5_bb0.8.inst.cfg b/resources/variants/ultimaker_s5_bb0.8.inst.cfg index 660a6b10f4..07b556d206 100644 --- a/resources/variants/ultimaker_s5_bb0.8.inst.cfg +++ b/resources/variants/ultimaker_s5_bb0.8.inst.cfg @@ -30,7 +30,6 @@ prime_tower_wipe_enabled = True raft_surface_layers = 1 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 3 speed_prime_tower = =math.ceil(speed_print * 7 / 35) speed_print = 35 speed_support = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s5_bb04.inst.cfg b/resources/variants/ultimaker_s5_bb04.inst.cfg index 2058185bb8..7959fc75c2 100644 --- a/resources/variants/ultimaker_s5_bb04.inst.cfg +++ b/resources/variants/ultimaker_s5_bb04.inst.cfg @@ -16,7 +16,6 @@ acceleration_support_interface = =math.ceil(acceleration_support * 1500 / 2000) machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 -retraction_min_travel = =3 * line_width speed_prime_tower = =math.ceil(speed_print * 10 / 35) speed_support = =math.ceil(speed_print * 25 / 35) speed_support_interface = =math.ceil(speed_support * 20 / 25) diff --git a/resources/variants/ultimaker_s5_cc04.inst.cfg b/resources/variants/ultimaker_s5_cc04.inst.cfg index ef64dc0ae4..5510d0126f 100644 --- a/resources/variants/ultimaker_s5_cc04.inst.cfg +++ b/resources/variants/ultimaker_s5_cc04.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.4 machine_nozzle_size = 0.4 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 diff --git a/resources/variants/ultimaker_s5_cc06.inst.cfg b/resources/variants/ultimaker_s5_cc06.inst.cfg index ba33bab17b..a49c790e4f 100644 --- a/resources/variants/ultimaker_s5_cc06.inst.cfg +++ b/resources/variants/ultimaker_s5_cc06.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.6 machine_nozzle_size = 0.6 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 diff --git a/resources/variants/ultimaker_s7_aa0.25.inst.cfg b/resources/variants/ultimaker_s7_aa0.25.inst.cfg index 1495af6c48..fc1bdcfef2 100644 --- a/resources/variants/ultimaker_s7_aa0.25.inst.cfg +++ b/resources/variants/ultimaker_s7_aa0.25.inst.cfg @@ -16,7 +16,6 @@ machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = AA 0.25 machine_nozzle_size = 0.25 machine_nozzle_tip_outer_diameter = 0.65 -retraction_min_travel = 0.7 retraction_prime_speed = =retraction_speed speed_print = 55 speed_topbottom = 20 diff --git a/resources/variants/ultimaker_s7_aa0.8.inst.cfg b/resources/variants/ultimaker_s7_aa0.8.inst.cfg index a5b6a66516..b3253f7d25 100644 --- a/resources/variants/ultimaker_s7_aa0.8.inst.cfg +++ b/resources/variants/ultimaker_s7_aa0.8.inst.cfg @@ -29,7 +29,6 @@ raft_surface_layers = 1 retraction_amount = 6.5 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 2 retraction_speed = 25 speed_print = 35 speed_topbottom = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s7_aa04.inst.cfg b/resources/variants/ultimaker_s7_aa04.inst.cfg index a9079c975e..6aee6597e0 100644 --- a/resources/variants/ultimaker_s7_aa04.inst.cfg +++ b/resources/variants/ultimaker_s7_aa04.inst.cfg @@ -14,7 +14,6 @@ machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = AA 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 6.5 -retraction_min_travel = =line_width * 2 speed_print = 70 speed_topbottom = =math.ceil(speed_print * 30 / 70) speed_wall = =math.ceil(speed_print * 30 / 70) diff --git a/resources/variants/ultimaker_s7_bb0.8.inst.cfg b/resources/variants/ultimaker_s7_bb0.8.inst.cfg index 6823fe18a4..010d5c7cf1 100644 --- a/resources/variants/ultimaker_s7_bb0.8.inst.cfg +++ b/resources/variants/ultimaker_s7_bb0.8.inst.cfg @@ -31,7 +31,6 @@ raft_surface_layers = 1 retraction_amount = 4.5 retraction_hop = 2 retraction_hop_only_when_collides = True -retraction_min_travel = =line_width * 3 speed_prime_tower = =math.ceil(speed_print * 7 / 35) speed_print = 35 speed_support = =math.ceil(speed_print * 25 / 35) diff --git a/resources/variants/ultimaker_s7_bb04.inst.cfg b/resources/variants/ultimaker_s7_bb04.inst.cfg index bead299de3..1ec0dfab98 100644 --- a/resources/variants/ultimaker_s7_bb04.inst.cfg +++ b/resources/variants/ultimaker_s7_bb04.inst.cfg @@ -17,7 +17,6 @@ machine_nozzle_heat_up_speed = 1.5 machine_nozzle_id = BB 0.4 machine_nozzle_tip_outer_diameter = 1.0 retraction_amount = 4.5 -retraction_min_travel = =3 * line_width speed_prime_tower = =math.ceil(speed_print * 10 / 35) speed_support = =math.ceil(speed_print * 25 / 35) speed_support_interface = =math.ceil(speed_support * 20 / 25) diff --git a/resources/variants/ultimaker_s7_cc04.inst.cfg b/resources/variants/ultimaker_s7_cc04.inst.cfg index d46d387330..6949c5be74 100644 --- a/resources/variants/ultimaker_s7_cc04.inst.cfg +++ b/resources/variants/ultimaker_s7_cc04.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.4 machine_nozzle_size = 0.4 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 diff --git a/resources/variants/ultimaker_s7_cc06.inst.cfg b/resources/variants/ultimaker_s7_cc06.inst.cfg index d0c0d3670f..576701fc2b 100644 --- a/resources/variants/ultimaker_s7_cc06.inst.cfg +++ b/resources/variants/ultimaker_s7_cc06.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.6 machine_nozzle_size = 0.6 -retraction_min_travel = =line_width * 2 retraction_prime_speed = =retraction_speed speed_infill = =speed_print speed_print = 45 From 578057f16a3985df356532d87f1dd9a1b3b1b269 Mon Sep 17 00:00:00 2001 From: "c.lamboo" Date: Thu, 8 Feb 2024 16:35:28 +0100 Subject: [PATCH 33/46] add file association for mac --- UltiMaker-Cura.spec.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index 99bfa80078..2dce96282e 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -92,7 +92,7 @@ app = BUNDLE( }], 'CFBundleDocumentTypes': [{ 'CFBundleTypeRole': 'Viewer', - 'CFBundleTypeExtensions': ['*'], + 'CFBundleTypeExtensions': ['stl', 'obj', '3mf', 'gcode', 'ufp'], 'CFBundleTypeName': 'Model Files', }] }, From e8bdca3dd95a9ba3b1efacc224732b73e5d2d0e4 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 9 Feb 2024 10:32:39 +0100 Subject: [PATCH 34/46] introducing drop to buildplate per model CURA-10542 --- cura/PlatformPhysics.py | 15 ++++-- resources/qml/Preferences/GeneralPage.qml | 66 +++++++++++++++++++++++ resources/qml/Toolbar.qml | 2 +- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 1ef39de80d..98e9e823c6 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -38,7 +38,7 @@ class PlatformPhysics: self._minimum_gap = 2 # It is a minimum distance (in mm) between two models, applicable for small models Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False) - Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", True) + Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down_per_model", "never") def _onSceneChanged(self, source): if not source.callDecoration("isSliceable"): @@ -71,6 +71,15 @@ class PlatformPhysics: # We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A. # By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve. random.shuffle(nodes) + default_value = False + if app_automatic_drop_down == "always": + default_value = True + if app_automatic_drop_down == "never": + default_value = False + if app_automatic_drop_down == "always_ask": + # ask_during_loading_model + pass + for node in nodes: if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None: continue @@ -80,10 +89,10 @@ class PlatformPhysics: # Move it downwards if bottom is above platform move_vector = Vector() - if node.getSetting(SceneNodeSettings.AutoDropDown, app_automatic_drop_down) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down + + if node.getSetting(SceneNodeSettings.AutoDropDown, default_value) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0 move_vector = move_vector.set(y = -bbox.bottom + z_offset) - # If there is no convex hull for the node, start calculating it and continue. if not node.getDecorator(ConvexHullDecorator) and not node.callDecoration("isNonPrintingMesh") and node.callDecoration("getLayerData") is None: node.addDecorator(ConvexHullDecorator()) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index c313ffbd94..963f95da4b 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -63,6 +63,18 @@ UM.PreferencesPage } } + function setDefaultDropDown(code) + { + for (var i = 0; i < choiceOnDropDown.model.count; ++i) + { + if (choiceOnDropDown.model.get(i).code == code) + { + choiceOnDropDown.currentIndex = i + break; + } + } + } + function reset() { UM.Preferences.resetPreference("general/language") @@ -513,6 +525,60 @@ UM.PreferencesPage } } + UM.TooltipArea + { + width: childrenRect.width + height: childrenRect.height + text: catalog.i18nc("@info:tooltip", "This setting will set a default (or not) for the Per Model Drop to buildplate feature (Either Always, Never, decide every time") + + Column + { + spacing: UM.Theme.getSize("narrow_margin").height + + UM.Label + { + text: catalog.i18nc("@window:text", " Default per model setting for drop to build plate when importing a model: ") + } + + Cura.ComboBox + { + id: choiceOnDropDown + width: UM.Theme.getSize("combobox").width + height: UM.Theme.getSize("combobox").height + + model: ListModel + { + id: dropDownOptions + + Component.onCompleted: + { + append({ text: catalog.i18nc("@option:openProject", "Always"), code: "always" }) + append({ text: catalog.i18nc("@option:openProject", "Never"), code: "never" }) + append({ text: catalog.i18nc("@option:openProject", "Always ask me this"), code: "always_ask" }) + } + } + textRole: "text" + + currentIndex: + { + var index = 0; + var currentChoice = UM.Preferences.getValue("physics/automatic_drop_down_per_model"); + for (var i = 0; i < model.count; ++i) + { + if (model.get(i).code == currentChoice) + { + index = i; + break; + } + } + return index; + } + + onActivated: UM.Preferences.setValue("physics/automatic_drop_down_per_model", model.get(index).code) + } + } + } + UM.TooltipArea { diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index 1af4e958f4..81f6c5d682 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -222,7 +222,7 @@ Item UM.Label { id: toolHint - text: UM.Controller.properties.getValue("ToolHint") != undefined ? UM.ActiveTool.properties.getValue("ToolHint") : "" + text: UM.Controller.properties.getValue("ToolHint") != undefined ? UM.Controller.properties.getValue("ToolHint") : "" color: UM.Theme.getColor("tooltip_text") anchors.horizontalCenter: parent.horizontalCenter } From a7292c7baf49539737136bdf6bc89b4617167c5c Mon Sep 17 00:00:00 2001 From: Saumya Jain <70144862+saumyaj3@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:20:04 +0100 Subject: [PATCH 35/46] Update OneAtATimeIterator.py saving node_list after sorting --- cura/OneAtATimeIterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index f92da3ec14..1017cfc79e 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -68,7 +68,7 @@ class OneAtATimeIterator(Iterator.Iterator): # Sort the original list so that items that block the most other objects are at the beginning. # This does not decrease the worst case running time, but should improve it in most cases. - sorted(node_list, key = cmp_to_key(hit_checker.calculateScore)) + node_list = sorted(node_list, key = cmp_to_key(hit_checker.calculateScore)) todo_node_list = [_ObjectOrder([], node_list)] while len(todo_node_list) > 0: From 91a84674f022b0baf0b1915fadef1d171c9cbddd Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 9 Feb 2024 15:11:56 +0100 Subject: [PATCH 36/46] Adding the preference drop to buildplate while opening Cura project CURA-10542 --- cura/PlatformPhysics.py | 14 +---- plugins/3MFReader/WorkspaceDialog.qml | 14 +++++ resources/qml/Preferences/GeneralPage.qml | 67 ----------------------- 3 files changed, 16 insertions(+), 79 deletions(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 98e9e823c6..7add1e24e7 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -38,7 +38,7 @@ class PlatformPhysics: self._minimum_gap = 2 # It is a minimum distance (in mm) between two models, applicable for small models Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False) - Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down_per_model", "never") + Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", False) def _onSceneChanged(self, source): if not source.callDecoration("isSliceable"): @@ -71,14 +71,6 @@ class PlatformPhysics: # We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A. # By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve. random.shuffle(nodes) - default_value = False - if app_automatic_drop_down == "always": - default_value = True - if app_automatic_drop_down == "never": - default_value = False - if app_automatic_drop_down == "always_ask": - # ask_during_loading_model - pass for node in nodes: if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None: @@ -88,9 +80,7 @@ class PlatformPhysics: # Move it downwards if bottom is above platform move_vector = Vector() - - - if node.getSetting(SceneNodeSettings.AutoDropDown, default_value) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down + if node.getSetting(SceneNodeSettings.AutoDropDown, app_automatic_drop_down) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0 move_vector = move_vector.set(y = -bbox.bottom + z_offset) # If there is no convex hull for the node, start calculating it and continue. diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index d5f9b1817d..874ca0aab8 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -299,6 +299,20 @@ UM.Dialog } } } + Row + { + id: dropToBuildPlate + width: parent.width + height: childrenRect.height + spacing: UM.Theme.getSize("default_margin").width + UM.CheckBox + { + id: rememberChoiceCheckBox + text: catalog.i18nc("@text:window", "Drop models to buildplate") + checked: UM.Preferences.getValue("physics/automatic_drop_down") == True + onCheckedChanged: UM.Preferences.setValue("physics/automatic_drop_down", checked) + } + } Row { diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 963f95da4b..af63743931 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -63,18 +63,6 @@ UM.PreferencesPage } } - function setDefaultDropDown(code) - { - for (var i = 0; i < choiceOnDropDown.model.count; ++i) - { - if (choiceOnDropDown.model.get(i).code == code) - { - choiceOnDropDown.currentIndex = i - break; - } - } - } - function reset() { UM.Preferences.resetPreference("general/language") @@ -525,61 +513,6 @@ UM.PreferencesPage } } - UM.TooltipArea - { - width: childrenRect.width - height: childrenRect.height - text: catalog.i18nc("@info:tooltip", "This setting will set a default (or not) for the Per Model Drop to buildplate feature (Either Always, Never, decide every time") - - Column - { - spacing: UM.Theme.getSize("narrow_margin").height - - UM.Label - { - text: catalog.i18nc("@window:text", " Default per model setting for drop to build plate when importing a model: ") - } - - Cura.ComboBox - { - id: choiceOnDropDown - width: UM.Theme.getSize("combobox").width - height: UM.Theme.getSize("combobox").height - - model: ListModel - { - id: dropDownOptions - - Component.onCompleted: - { - append({ text: catalog.i18nc("@option:openProject", "Always"), code: "always" }) - append({ text: catalog.i18nc("@option:openProject", "Never"), code: "never" }) - append({ text: catalog.i18nc("@option:openProject", "Always ask me this"), code: "always_ask" }) - } - } - textRole: "text" - - currentIndex: - { - var index = 0; - var currentChoice = UM.Preferences.getValue("physics/automatic_drop_down_per_model"); - for (var i = 0; i < model.count; ++i) - { - if (model.get(i).code == currentChoice) - { - index = i; - break; - } - } - return index; - } - - onActivated: UM.Preferences.setValue("physics/automatic_drop_down_per_model", model.get(index).code) - } - } - } - - UM.TooltipArea { width: childrenRect.width; From aa2abfbd2e1a86a5e10f6a3e3c56e0092d8cb589 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Fri, 9 Feb 2024 15:15:44 +0100 Subject: [PATCH 37/46] removing id of checkbox CURA-10542 --- cura/PlatformPhysics.py | 2 ++ plugins/3MFReader/WorkspaceDialog.qml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 7add1e24e7..d204bee185 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -80,9 +80,11 @@ class PlatformPhysics: # Move it downwards if bottom is above platform move_vector = Vector() + if node.getSetting(SceneNodeSettings.AutoDropDown, app_automatic_drop_down) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0 move_vector = move_vector.set(y = -bbox.bottom + z_offset) + # If there is no convex hull for the node, start calculating it and continue. if not node.getDecorator(ConvexHullDecorator) and not node.callDecoration("isNonPrintingMesh") and node.callDecoration("getLayerData") is None: node.addDecorator(ConvexHullDecorator()) diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index 874ca0aab8..8b4b2341d9 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -299,6 +299,7 @@ UM.Dialog } } } + Row { id: dropToBuildPlate @@ -307,7 +308,6 @@ UM.Dialog spacing: UM.Theme.getSize("default_margin").width UM.CheckBox { - id: rememberChoiceCheckBox text: catalog.i18nc("@text:window", "Drop models to buildplate") checked: UM.Preferences.getValue("physics/automatic_drop_down") == True onCheckedChanged: UM.Preferences.setValue("physics/automatic_drop_down", checked) From 7a72708217c79275cb97d9ed468976d82e6e77e9 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 13 Feb 2024 16:04:20 +0100 Subject: [PATCH 38/46] Fix random crash on windows OS on boot up --- cura/PrintOrderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrintOrderManager.py b/cura/PrintOrderManager.py index abfa5442a2..80fc1e99dc 100644 --- a/cura/PrintOrderManager.py +++ b/cura/PrintOrderManager.py @@ -61,7 +61,7 @@ class PrintOrderManager(QObject): is_enabled = stack and \ stack.getProperty("print_sequence", "value") == "one_at_a_time" and \ stack.getProperty("user_defined_print_order_enabled", "value") - return is_enabled + return bool(is_enabled) @staticmethod def initializePrintOrders(nodes: List[CuraSceneNode]) -> None: From 32d9e6b45c56f65beea413248849b8599e62c30a Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Wed, 14 Feb 2024 12:59:41 +0100 Subject: [PATCH 39/46] preference does not change after user changes drop to buildplate for a model CURA-10542 --- cura/PlatformPhysics.py | 12 +++++++++++- plugins/3MFReader/WorkspaceDialog.qml | 10 ++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index d204bee185..b7fe549601 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -39,6 +39,7 @@ class PlatformPhysics: Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False) Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", False) + Application.getInstance().getPreferences().addPreference("physics/per_model_drop", False) def _onSceneChanged(self, source): if not source.callDecoration("isSliceable"): @@ -54,6 +55,9 @@ class PlatformPhysics: app_preferences = app_instance.getPreferences() app_automatic_drop_down = app_preferences.getValue("physics/automatic_drop_down") app_automatic_push_free = app_preferences.getValue("physics/automatic_push_free") + # silent preference setting to mimic preference automatic_drop_down only different when user changes it explicitely while opening model + app_per_model_drop = app_preferences.getValue("physics/per_model_drop") + root = self._controller.getScene().getRoot() build_volume = app_instance.getBuildVolume() @@ -81,7 +85,11 @@ class PlatformPhysics: # Move it downwards if bottom is above platform move_vector = Vector() - if node.getSetting(SceneNodeSettings.AutoDropDown, app_automatic_drop_down) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down + # if per model drop is different then app_automatic_drop + # in case of 3mf loading when user changes this setting for that model + if (app_per_model_drop != app_automatic_drop_down): + node.setSetting(SceneNodeSettings.AutoDropDown, app_per_model_drop) + if node.getSetting(SceneNodeSettings.AutoDropDown, app_per_model_drop) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0 move_vector = move_vector.set(y = -bbox.bottom + z_offset) @@ -169,6 +177,8 @@ class PlatformPhysics: op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector) op.push() + # setting this silent preference same as app_automatic_drop_down + app_preferences.setValue("physics/per_model_drop", app_automatic_drop_down) # After moving, we have to evaluate the boundary checks for nodes build_volume.updateNodeBoundaryCheck() diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index 8b4b2341d9..eefa0f713a 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -308,9 +308,14 @@ UM.Dialog spacing: UM.Theme.getSize("default_margin").width UM.CheckBox { + id: checkDropModels text: catalog.i18nc("@text:window", "Drop models to buildplate") - checked: UM.Preferences.getValue("physics/automatic_drop_down") == True - onCheckedChanged: UM.Preferences.setValue("physics/automatic_drop_down", checked) + checked: UM.Preferences.getValue("physics/automatic_drop_down") + onCheckedChanged: UM.Preferences.setValue("physics/per_model_drop", checked) + } + function reloadValue() + { + checkDropModels.checked = UM.Preferences.getValue("physics/automatic_drop_down") } } @@ -436,6 +441,7 @@ UM.Dialog materialSection.reloadValues() profileSection.reloadValues() printerSection.reloadValues() + dropToBuildPlate.reloadValue() } } } From 844f9b3ae81faf76387d6b757d475af4a9058b9a Mon Sep 17 00:00:00 2001 From: Paul Kuiper <46715907+pkuiper-ultimaker@users.noreply.github.com> Date: Wed, 14 Feb 2024 14:44:54 +0100 Subject: [PATCH 40/46] Changed max. value warning level z support distance to prevent warnings for AA0.25 nozzle using default profiles. PP-424 --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 20a8a698a2..2f63bf5798 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5135,7 +5135,7 @@ "unit": "mm", "type": "float", "minimum_value": "0", - "maximum_value_warning": "machine_nozzle_size", + "maximum_value_warning": "5*layer_height", "default_value": 0.1, "limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr", "enabled": "support_enable or support_meshes_present", From 831af362cb9acb61192f76421c33f884c88b2f2b Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 14 Feb 2024 15:46:40 +0100 Subject: [PATCH 41/46] Constantify magic values. part of CURA-11406 --- cura/OAuth2/AuthorizationService.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 1832ff37c2..4e8d28173a 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Ultimaker B.V. +# Copyright (c) 2024 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. import json @@ -26,6 +26,8 @@ if TYPE_CHECKING: MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers" +REFRESH_TOKEN_MAX_RETRIES = 15 +REFRESH_TOKEN_RETRY_INTERVAL = 1000 class AuthorizationService: """The authorization service is responsible for handling the login flow, storing user credentials and providing @@ -60,7 +62,7 @@ class AuthorizationService: self._refresh_token_retries = 0 self._refresh_token_retry_timer = QTimer() - self._refresh_token_retry_timer.setInterval(1000) + self._refresh_token_retry_timer.setInterval(REFRESH_TOKEN_RETRY_INTERVAL) self._refresh_token_retry_timer.setSingleShot(True) self._refresh_token_retry_timer.timeout.connect(self.refreshAccessToken) @@ -182,7 +184,7 @@ class AuthorizationService: HttpRequestManager.getInstance().setDelayRequests(False) self.onAuthStateChanged.emit(logged_in = True) else: - if self._refresh_token_retries >= 15: + if self._refresh_token_retries >= REFRESH_TOKEN_MAX_RETRIES: self._refresh_token_retries = 0 Logger.warning("Failed to get a new access token from the server, giving up.") HttpRequestManager.getInstance().setDelayRequests(False) From f54d6099cd97c995b3a01beb177969a4a9a2a244 Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Thu, 15 Feb 2024 11:23:34 +0100 Subject: [PATCH 42/46] removed the preference made it a member of class platformphysics CURA-10542 --- cura/CuraApplication.py | 4 ++++ cura/PlatformPhysics.py | 24 ++++++++++++----------- plugins/3MFReader/WorkspaceDialog.py | 5 +++++ plugins/3MFReader/WorkspaceDialog.qml | 2 +- resources/qml/Preferences/GeneralPage.qml | 6 +++++- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 76e3e4b400..153788b867 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1082,6 +1082,10 @@ class CuraApplication(QtApplication): def getTextManager(self, *args) -> "TextManager": return self._text_manager + @pyqtSlot(bool) + def getLocalDropToBuildplate(self, drop_to_build_plate: bool) ->None: + return self._physics.setAppPerModelDropDown(drop_to_build_plate) + def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions": if self._cura_formula_functions is None: self._cura_formula_functions = CuraFormulaFunctions(self) diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index b7fe549601..6a26190a56 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -39,7 +39,13 @@ class PlatformPhysics: Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False) Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", False) - Application.getInstance().getPreferences().addPreference("physics/per_model_drop", False) + self._app_per_model_drop = Application.getInstance().getPreferences().getValue("physics/automatic_drop_down") + + def getAppPerModelDropDown(self): + return self._app_per_model_drop + + def setAppPerModelDropDown(self, drop_to_buildplate): + self._app_per_model_drop = drop_to_buildplate def _onSceneChanged(self, source): if not source.callDecoration("isSliceable"): @@ -55,9 +61,6 @@ class PlatformPhysics: app_preferences = app_instance.getPreferences() app_automatic_drop_down = app_preferences.getValue("physics/automatic_drop_down") app_automatic_push_free = app_preferences.getValue("physics/automatic_push_free") - # silent preference setting to mimic preference automatic_drop_down only different when user changes it explicitely while opening model - app_per_model_drop = app_preferences.getValue("physics/per_model_drop") - root = self._controller.getScene().getRoot() build_volume = app_instance.getBuildVolume() @@ -85,11 +88,10 @@ class PlatformPhysics: # Move it downwards if bottom is above platform move_vector = Vector() - # if per model drop is different then app_automatic_drop - # in case of 3mf loading when user changes this setting for that model - if (app_per_model_drop != app_automatic_drop_down): - node.setSetting(SceneNodeSettings.AutoDropDown, app_per_model_drop) - if node.getSetting(SceneNodeSettings.AutoDropDown, app_per_model_drop) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down + # if per model drop is different then app_automatic_drop, in case of 3mf loading when user changes this setting for that model + if (self._app_per_model_drop != app_automatic_drop_down): + node.setSetting(SceneNodeSettings.AutoDropDown, self._app_per_model_drop) + if node.getSetting(SceneNodeSettings.AutoDropDown, self._app_per_model_drop) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0 move_vector = move_vector.set(y = -bbox.bottom + z_offset) @@ -177,8 +179,8 @@ class PlatformPhysics: op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector) op.push() - # setting this silent preference same as app_automatic_drop_down - app_preferences.setValue("physics/per_model_drop", app_automatic_drop_down) + # setting this drop to model same as app_automatic_drop_down + self._app_per_model_drop = app_automatic_drop_down # After moving, we have to evaluate the boundary checks for nodes build_volume.updateNodeBoundaryCheck() diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 0203fc92b5..5b8ddeb2f9 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -299,6 +299,11 @@ class WorkspaceDialog(QObject): Application.getInstance().getBackend().close() + @pyqtSlot(bool) + def setDropToBuildPlateForModel(self, drop_to_buildplate: bool) -> None: + CuraApplication.getInstance().getLocalDropToBuildplate(drop_to_buildplate) + + def setMaterialConflict(self, material_conflict: bool) -> None: if self._has_material_conflict != material_conflict: self._has_material_conflict = material_conflict diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index eefa0f713a..cb1664a2c0 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -311,7 +311,7 @@ UM.Dialog id: checkDropModels text: catalog.i18nc("@text:window", "Drop models to buildplate") checked: UM.Preferences.getValue("physics/automatic_drop_down") - onCheckedChanged: UM.Preferences.setValue("physics/per_model_drop", checked) + onCheckedChanged: manager.setDropToBuildPlateForModel(checked) } function reloadValue() { diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index af63743931..0fbc319fb9 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -509,7 +509,11 @@ UM.PreferencesPage id: dropDownCheckbox text: catalog.i18nc("@option:check", "Automatically drop models to the build plate") checked: boolCheck(UM.Preferences.getValue("physics/automatic_drop_down")) - onCheckedChanged: UM.Preferences.setValue("physics/automatic_drop_down", checked) + onCheckedChanged: + { + UM.Preferences.setValue("physics/automatic_drop_down", checked) + CuraApplication.getLocalDropToBuildplate(checked) + } } } From d68a454fa9170eea4659f4dee2fc84fc71d15d3d Mon Sep 17 00:00:00 2001 From: "saumya.jain" Date: Thu, 15 Feb 2024 11:35:09 +0100 Subject: [PATCH 43/46] function name change to getWorkplaceDropToBuildplate CURA-10542 --- cura/CuraApplication.py | 2 +- plugins/3MFReader/WorkspaceDialog.py | 2 +- resources/qml/Preferences/GeneralPage.qml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 153788b867..20e54fa57c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1083,7 +1083,7 @@ class CuraApplication(QtApplication): return self._text_manager @pyqtSlot(bool) - def getLocalDropToBuildplate(self, drop_to_build_plate: bool) ->None: + def getWorkplaceDropToBuildplate(self, drop_to_build_plate: bool) ->None: return self._physics.setAppPerModelDropDown(drop_to_build_plate) def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions": diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 5b8ddeb2f9..02e71f2185 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -301,7 +301,7 @@ class WorkspaceDialog(QObject): @pyqtSlot(bool) def setDropToBuildPlateForModel(self, drop_to_buildplate: bool) -> None: - CuraApplication.getInstance().getLocalDropToBuildplate(drop_to_buildplate) + CuraApplication.getInstance().getWorkplaceDropToBuildplate(drop_to_buildplate) def setMaterialConflict(self, material_conflict: bool) -> None: diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 0fbc319fb9..69607a3f6b 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -512,7 +512,7 @@ UM.PreferencesPage onCheckedChanged: { UM.Preferences.setValue("physics/automatic_drop_down", checked) - CuraApplication.getLocalDropToBuildplate(checked) + CuraApplication.getWorkplaceDropToBuildplate(checked) } } } From 831c72dbe5d64b468eb2089ecdd3cce24a584f59 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 15 Feb 2024 15:03:13 +0100 Subject: [PATCH 44/46] Fix unit-tests. related to internal ticket CURA-11406 --- tests/TestOAuth2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestOAuth2.py b/tests/TestOAuth2.py index 09fa555af4..82d138a71e 100644 --- a/tests/TestOAuth2.py +++ b/tests/TestOAuth2.py @@ -97,7 +97,7 @@ def test__parseJWTNoRefreshToken(): mock_reply = Mock() # The user profile that the service should respond with. mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError) http_mock = Mock() - http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply) + http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) http_mock.readJSON = Mock(return_value = {"data": {"user_id": "id_ego_or_superego", "username": "Ghostkeeper"}}) with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)): From 58f8eae80cd84cf0112a4d851a842f3ff36cc430 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 15 Feb 2024 15:45:49 +0100 Subject: [PATCH 45/46] Fix more unit-tests. related to internal ticket CURA-11406 --- tests/TestOAuth2.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestOAuth2.py b/tests/TestOAuth2.py index 82d138a71e..c7985e39f3 100644 --- a/tests/TestOAuth2.py +++ b/tests/TestOAuth2.py @@ -119,8 +119,8 @@ def test__parseJWTFailOnRefresh(): mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate. mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave". http_mock = Mock() - http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply) - http_mock.post = lambda url, data, headers_dict, callback, error_callback: callback(mock_reply) + http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) + http_mock.post = lambda url, data, headers_dict, callback, error_callback, timeout: callback(mock_reply) with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})): with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)): @@ -142,7 +142,7 @@ def test__parseJWTSucceedOnRefresh(): mock_reply_failure = Mock() mock_reply_failure.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) http_mock = Mock() - def mock_get(url, headers_dict, callback, error_callback): + def mock_get(url, headers_dict, callback, error_callback, timeout): if(headers_dict == {"Authorization": "Bearer beep"}): callback(mock_reply_success) else: @@ -181,8 +181,8 @@ def test_refreshAccessTokenFailed(): mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate. mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave". http_mock = Mock() - http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply) - http_mock.post = lambda url, data, headers_dict, callback, error_callback: callback(mock_reply) + http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) + http_mock.post = lambda url, data, headers_dict, callback, error_callback, timeout: callback(mock_reply) with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})): with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)): @@ -263,7 +263,7 @@ def test_loginAndLogout() -> None: mock_reply = Mock() # The user profile that the service should respond with. mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError) http_mock = Mock() - http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply) + http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) http_mock.readJSON = Mock(return_value = {"data": {"user_id": "di_resu", "username": "Emanresu"}}) # Let the service think there was a successful response From 77823a9c122331e24496c75be34c6365b2bf37b0 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 15 Feb 2024 16:01:32 +0100 Subject: [PATCH 46/46] Fix more unit-tests II. related to internal ticket CURA-11406 --- tests/TestOAuth2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestOAuth2.py b/tests/TestOAuth2.py index c7985e39f3..41edaebbf7 100644 --- a/tests/TestOAuth2.py +++ b/tests/TestOAuth2.py @@ -120,7 +120,7 @@ def test__parseJWTFailOnRefresh(): mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave". http_mock = Mock() http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) - http_mock.post = lambda url, data, headers_dict, callback, error_callback, timeout: callback(mock_reply) + http_mock.post = lambda url, data, headers_dict, callback, error_callback, urgent, timeout: callback(mock_reply) with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})): with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)): @@ -182,7 +182,7 @@ def test_refreshAccessTokenFailed(): mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave". http_mock = Mock() http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply) - http_mock.post = lambda url, data, headers_dict, callback, error_callback, timeout: callback(mock_reply) + http_mock.post = lambda url, data, headers_dict, callback, error_callback, urgent, timeout: callback(mock_reply) with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})): with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):