From b45d0916414b991cb6ef84bf2fba3fe29f80b72c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 3 Aug 2016 12:54:54 +0200 Subject: [PATCH 01/12] Make camera animation feel snappier It no longer eases into the animation, so it feels as if it reacts more immediately. --- cura/CameraAnimation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/CameraAnimation.py b/cura/CameraAnimation.py index e31cbb93a4..a707053d87 100644 --- a/cura/CameraAnimation.py +++ b/cura/CameraAnimation.py @@ -11,8 +11,8 @@ class CameraAnimation(QVariantAnimation): def __init__(self, parent = None): super().__init__(parent) self._camera_tool = None - self.setDuration(500) - self.setEasingCurve(QEasingCurve.InOutQuad) + self.setDuration(300) + self.setEasingCurve(QEasingCurve.OutQuad) def setCameraTool(self, camera_tool): self._camera_tool = camera_tool From 85f2a7c3853cd3bfcf500897f4849bea997adca3 Mon Sep 17 00:00:00 2001 From: "A.Sasin" Date: Tue, 17 Oct 2017 15:01:49 +0200 Subject: [PATCH 02/12] Added update to for Instance container to re calculate values and validate CURA-4447 --- cura/CuraApplication.py | 14 ++++++++++++++ cura/Settings/MachineManager.py | 11 ++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 27451c745c..22fbbafab3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -415,6 +415,20 @@ class CuraApplication(QtApplication): global_stack.getTop().clear() + # if the user decided to keep settings then the user settings should be re-calculated and validated for errors + # before slicing. To ensure that slicer uses right settings values + elif option == "keep": + global_stack = self.getGlobalContainerStack() + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + user_extruder_container = extruder.getTop() + + if user_extruder_container: + user_extruder_container.update() + + user_global_container = global_stack.getTop() + if user_global_container: + user_global_container.update() + @pyqtSlot(int) def messageBoxClosed(self, button): if self._message_box_callback: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 563965915a..e89e11898c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -854,17 +854,18 @@ class MachineManager(QObject): self._replaceQualityOrQualityChangesInStack(stack, stack_quality, postpone_emit=True) self._replaceQualityOrQualityChangesInStack(stack, stack_quality_changes, postpone_emit=True) - # Send emits that are postponed in replaceContainer. - # Here the stacks are finished replacing and every value can be resolved based on the current state. - for setting_info in new_quality_settings_list: - setting_info["stack"].sendPostponedEmits() - # Connect to onQualityNameChanged for stack in name_changed_connect_stacks: stack.nameChanged.connect(self._onQualityNameChanged) if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: self._askUserToKeepOrClearCurrentSettings() + else: + # If the user doesn't have any of adjusted settings then slicing will be triggered by emit() + # Send emits that are postponed in replaceContainer. + # Here the stacks are finished replacing and every value can be resolved based on the current state. + for setting_info in new_quality_settings_list: + setting_info["stack"].sendPostponedEmits() self.activeQualityChanged.emit() From d735921d42aa9ee1fdc6a5c8f31e5aae89bbdfc4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 19 Oct 2017 08:32:26 +0200 Subject: [PATCH 03/12] Take into account the keep/discard interaction when emitting signals CURA-4248 When user switches to a different profile, the keep/discard dialog can show up. Don't emit signals immediately if this interaction takes place because it will trigger an unnecessary slice. --- cura/CuraApplication.py | 6 ++++-- cura/Settings/MachineManager.py | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 22fbbafab3..4b4f743a77 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -393,6 +393,7 @@ class CuraApplication(QtApplication): showDiscardOrKeepProfileChanges = pyqtSignal() def discardOrKeepProfileChanges(self): + has_user_interaction = False choice = Preferences.getInstance().getValue("cura/choice_on_profile_override") if choice == "always_discard": # don't show dialog and DISCARD the profile @@ -403,11 +404,12 @@ class CuraApplication(QtApplication): else: # ALWAYS ask whether to keep or discard the profile self.showDiscardOrKeepProfileChanges.emit() - - #sidebarSimpleDiscardOrKeepProfileChanges = pyqtSignal() + has_user_interaction = True + return has_user_interaction @pyqtSlot(str) def discardOrKeepProfileChangesClosed(self, option): + self.getMachineManager().activeQualityChanged.emit() if option == "discard": global_stack = self.getGlobalContainerStack() for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index e89e11898c..0db07485aa 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -858,8 +858,10 @@ class MachineManager(QObject): for stack in name_changed_connect_stacks: stack.nameChanged.connect(self._onQualityNameChanged) + has_user_interaction = False if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: - self._askUserToKeepOrClearCurrentSettings() + # Show the keep/discard user settings dialog + has_user_interaction = Application.getInstance().discardOrKeepProfileChanges() else: # If the user doesn't have any of adjusted settings then slicing will be triggered by emit() # Send emits that are postponed in replaceContainer. @@ -867,7 +869,8 @@ class MachineManager(QObject): for setting_info in new_quality_settings_list: setting_info["stack"].sendPostponedEmits() - self.activeQualityChanged.emit() + if not has_user_interaction: + self.activeQualityChanged.emit() ## Determine the quality and quality changes settings for the current machine for a quality name. # @@ -986,9 +989,6 @@ class MachineManager(QObject): stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) self._onQualityNameChanged() - def _askUserToKeepOrClearCurrentSettings(self): - Application.getInstance().discardOrKeepProfileChanges() - @pyqtProperty(str, notify = activeVariantChanged) def activeVariantName(self) -> str: if self._active_container_stack: From e9336b9b9e995f80190652ec00767f3d8f4b4e20 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 19 Oct 2017 14:39:32 +0200 Subject: [PATCH 04/12] Small cleanups for discard or keep behavior - CURA-4447 --- cura/CuraApplication.py | 6 +++--- cura/Settings/MachineManager.py | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4b4f743a77..ce09346a34 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -409,12 +409,10 @@ class CuraApplication(QtApplication): @pyqtSlot(str) def discardOrKeepProfileChangesClosed(self, option): - self.getMachineManager().activeQualityChanged.emit() if option == "discard": global_stack = self.getGlobalContainerStack() for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): extruder.getTop().clear() - global_stack.getTop().clear() # if the user decided to keep settings then the user settings should be re-calculated and validated for errors @@ -423,7 +421,6 @@ class CuraApplication(QtApplication): global_stack = self.getGlobalContainerStack() for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): user_extruder_container = extruder.getTop() - if user_extruder_container: user_extruder_container.update() @@ -431,6 +428,9 @@ class CuraApplication(QtApplication): if user_global_container: user_global_container.update() + # notify listeners that quality has changed (after user selected discard or keep) + self.getMachineManager().activeQualityChanged.emit() + @pyqtSlot(int) def messageBoxClosed(self, button): if self._message_box_callback: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0db07485aa..6438453043 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -815,6 +815,7 @@ class MachineManager(QObject): # \param quality_id The quality_id of either a quality or a quality_changes @pyqtSlot(str) def setActiveQuality(self, quality_id: str): + print("set active quality") with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self.blurSettings.emit() @@ -858,10 +859,9 @@ class MachineManager(QObject): for stack in name_changed_connect_stacks: stack.nameChanged.connect(self._onQualityNameChanged) - has_user_interaction = False if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: # Show the keep/discard user settings dialog - has_user_interaction = Application.getInstance().discardOrKeepProfileChanges() + Application.getInstance().discardOrKeepProfileChanges() else: # If the user doesn't have any of adjusted settings then slicing will be triggered by emit() # Send emits that are postponed in replaceContainer. @@ -869,7 +869,6 @@ class MachineManager(QObject): for setting_info in new_quality_settings_list: setting_info["stack"].sendPostponedEmits() - if not has_user_interaction: self.activeQualityChanged.emit() ## Determine the quality and quality changes settings for the current machine for a quality name. From 70cf86c65b42b2fe22540cf5b0a0053081267e10 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 19 Oct 2017 14:40:56 +0200 Subject: [PATCH 05/12] Remove debug print - CURA-4447 --- cura/Settings/MachineManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6438453043..442c61d9ce 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -815,7 +815,6 @@ class MachineManager(QObject): # \param quality_id The quality_id of either a quality or a quality_changes @pyqtSlot(str) def setActiveQuality(self, quality_id: str): - print("set active quality") with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self.blurSettings.emit() From 31a04ed8dac85b2c536a4695659cb4d8496582e4 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 20 Oct 2017 11:37:45 +0200 Subject: [PATCH 06/12] Also emit active quality changed when no dialog interaction occured - CURA-4447 --- cura/Settings/MachineManager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 442c61d9ce..8cd793dfae 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -858,9 +858,11 @@ class MachineManager(QObject): for stack in name_changed_connect_stacks: stack.nameChanged.connect(self._onQualityNameChanged) + has_user_interaction = False + if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: # Show the keep/discard user settings dialog - Application.getInstance().discardOrKeepProfileChanges() + has_user_interaction = Application.getInstance().discardOrKeepProfileChanges() else: # If the user doesn't have any of adjusted settings then slicing will be triggered by emit() # Send emits that are postponed in replaceContainer. @@ -868,6 +870,7 @@ class MachineManager(QObject): for setting_info in new_quality_settings_list: setting_info["stack"].sendPostponedEmits() + if not has_user_interaction: self.activeQualityChanged.emit() ## Determine the quality and quality changes settings for the current machine for a quality name. From 95a2559607c0b3620c10689ef2ef97b14ba65d16 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 20 Oct 2017 12:34:35 +0200 Subject: [PATCH 07/12] indent --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 8cd793dfae..f704378a8f 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -871,7 +871,7 @@ class MachineManager(QObject): setting_info["stack"].sendPostponedEmits() if not has_user_interaction: - self.activeQualityChanged.emit() + self.activeQualityChanged.emit() ## Determine the quality and quality changes settings for the current machine for a quality name. # From 2361e96e29941c366c4a3f07373ffb34a44c423c Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 23 Oct 2017 11:41:20 +0200 Subject: [PATCH 08/12] Wait with updating active stack variant and material until dialog was closed - CURA-4447 --- cura/CuraApplication.py | 3 +++ cura/Settings/MachineManager.py | 33 +++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index ce09346a34..1680e7c6a6 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -407,6 +407,8 @@ class CuraApplication(QtApplication): has_user_interaction = True return has_user_interaction + onDiscardOrKeepProfileChangesClosed = pyqtSignal() # Used to notify other managers that the dialog was closed + @pyqtSlot(str) def discardOrKeepProfileChangesClosed(self, option): if option == "discard": @@ -429,6 +431,7 @@ class CuraApplication(QtApplication): user_global_container.update() # notify listeners that quality has changed (after user selected discard or keep) + self.onDiscardOrKeepProfileChangesClosed.emit() self.getMachineManager().activeQualityChanged.emit() @pyqtSlot(int) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f704378a8f..d32e7dcb4d 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -47,6 +47,10 @@ class MachineManager(QObject): self._active_container_stack = None # type: CuraContainerStack self._global_container_stack = None # type: GlobalStack + # Used to store the new containers until after confirming the dialog + self._new_variant_container = None + self._new_material_container = None + self._error_check_timer = QTimer() self._error_check_timer.setInterval(250) self._error_check_timer.setSingleShot(True) @@ -58,6 +62,7 @@ class MachineManager(QObject): self._instance_container_timer.timeout.connect(self.__onInstanceContainersChanged) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) + ## When the global container is changed, active material probably needs to be updated. self.globalContainerChanged.connect(self.activeMaterialChanged) self.globalContainerChanged.connect(self.activeVariantChanged) @@ -84,6 +89,9 @@ class MachineManager(QObject): ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged) self.activeStackChanged.connect(self.activeStackValueChanged) + # when a user closed dialog check if any delayed material or variant changes need to be applied + Application.getInstance().onDiscardOrKeepProfileChangesClosed.connect(self._executeDelayedActiveContainerStackChanges) + Preferences.getInstance().addPreference("cura/active_machine", "") self._global_event_keys = set() @@ -109,7 +117,7 @@ class MachineManager(QObject): "The selected material is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Incompatible Material")) - globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) + globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) activeMaterialChanged = pyqtSignal() activeVariantChanged = pyqtSignal() activeQualityChanged = pyqtSignal() @@ -747,7 +755,7 @@ class MachineManager(QObject): self.blurSettings.emit() old_material.nameChanged.disconnect(self._onMaterialNameChanged) - self._active_container_stack.material = material_container + self._new_material_container = material_container # self._active_container_stack will be updated with a delay Logger.log("d", "Active material changed") material_container.nameChanged.connect(self._onMaterialNameChanged) @@ -801,13 +809,13 @@ class MachineManager(QObject): old_material = self._active_container_stack.material if old_variant: self.blurSettings.emit() - self._active_container_stack.variant = containers[0] + self._new_variant_container = containers[0] # self._active_container_stack will be updated with a delay Logger.log("d", "Active variant changed to {active_variant_id}".format(active_variant_id = containers[0].getId())) preferred_material_name = None if old_material: preferred_material_name = old_material.getName() - - self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), self._global_container_stack, containers[0], preferred_material_name).id) + preferred_material_id = self._updateMaterialContainer(self._global_container_stack.getBottom(), self._global_container_stack, containers[0], preferred_material_name).id + self.setActiveMaterial(preferred_material_id) else: Logger.log("w", "While trying to set the active variant, no variant was found to replace.") @@ -871,7 +879,20 @@ class MachineManager(QObject): setting_info["stack"].sendPostponedEmits() if not has_user_interaction: - self.activeQualityChanged.emit() + self.activeQualityChanged.emit() + + ## Used to update material and variant in the active container stack with a delay. + # This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing) + # before the user decided to keep or discard any of their changes using the dialog. + # The activeQualityChanged signal triggers this method. + def _executeDelayedActiveContainerStackChanges(self): + if self._new_material_container is not None: + self._active_container_stack.material = self._new_material_container + self._new_material_container = None + + if self._new_variant_container is not None: + self._active_container_stack.variant = self._new_variant_container + self._new_variant_container = None ## Determine the quality and quality changes settings for the current machine for a quality name. # From e63616ca419ca30a613a9f9d9840f3a55ac6b350 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 23 Oct 2017 11:43:15 +0200 Subject: [PATCH 09/12] Update method description - CURA-4447 --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d32e7dcb4d..a4dd311bb4 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -884,7 +884,7 @@ class MachineManager(QObject): ## Used to update material and variant in the active container stack with a delay. # This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing) # before the user decided to keep or discard any of their changes using the dialog. - # The activeQualityChanged signal triggers this method. + # The Application.onDiscardOrKeepProfileChangesClosed signal triggers this method. def _executeDelayedActiveContainerStackChanges(self): if self._new_material_container is not None: self._active_container_stack.material = self._new_material_container From d2ef373d19ae874bb6fbebf4a621ccf3c5f0db88 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 23 Oct 2017 15:50:42 +0200 Subject: [PATCH 10/12] Also apply container changes when no user interaction is required - CURA-4447 --- cura/Settings/MachineManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a4dd311bb4..efc9515ef1 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -879,6 +879,7 @@ class MachineManager(QObject): setting_info["stack"].sendPostponedEmits() if not has_user_interaction: + self._executeDelayedActiveContainerStackChanges() self.activeQualityChanged.emit() ## Used to update material and variant in the active container stack with a delay. From d8e1b5b9b40146b2d7c0c903c45c0a4393d87e8a Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 24 Oct 2017 11:25:12 +0200 Subject: [PATCH 11/12] CURA-4481 add setting Remove Empty First Layers --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 1 + resources/definitions/fdmprinter.def.json | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index c9fac23d91..a352564bc2 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -240,3 +240,4 @@ class ProcessSlicedLayersJob(Job): else: if self._progress_message: self._progress_message.hide() + diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 826449afd9..baae3f7579 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3956,6 +3956,15 @@ "limit_to_extruder": "support_infill_extruder_nr", "enabled": "support_enable and support_use_towers", "settable_per_mesh": true + }, + "remove_empty_first_layers": + { + "label": "Remove Empty First Layers", + "description": "Remove empty layers beneath the first printed layer if they are present.", + "type": "bool", + "default_value": true, + "settable_per_mesh": false, + "settable_per_extruder": false } } }, From c1139c5c45b2a6e9b169af6cc17a580978445abc Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 24 Oct 2017 13:38:14 +0200 Subject: [PATCH 12/12] Update stack error checking when switching matchines - CURA-4447 --- cura/Settings/MachineManager.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index efc9515ef1..fc5c415f87 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -341,6 +341,7 @@ class MachineManager(QObject): self.activeQualityChanged.emit() self.activeVariantChanged.emit() self.activeMaterialChanged.emit() + self._updateStacksHaveErrors() # Prevents unwanted re-slices after changing machine self._error_check_timer.start() def _onInstanceContainersChanged(self, container): @@ -357,6 +358,8 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveMachine(self, stack_id: str) -> None: self.blurSettings.emit() # Ensure no-one has focus. + self._cancelDelayedActiveContainerStackChanges() + containers = ContainerRegistry.getInstance().findContainerStacks(id = stack_id) if containers: Application.getInstance().setGlobalContainerStack(containers[0]) @@ -895,6 +898,12 @@ class MachineManager(QObject): self._active_container_stack.variant = self._new_variant_container self._new_variant_container = None + ## Cancel set changes for material and variant in the active container stack. + # Used for ignoring any changes when switching between printers (setActiveMachine) + def _cancelDelayedActiveContainerStackChanges(self): + self._new_material_container = None + self._new_variant_container = None + ## Determine the quality and quality changes settings for the current machine for a quality name. # # \param quality_name \type{str} the name of the quality.