From c132300fd553d28e10f1a6b9a361dd78688cac70 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 23 Oct 2017 13:56:26 +0200 Subject: [PATCH 01/54] start --- cura/Settings/ExtruderManager.py | 44 +++++++++---------- .../MachineSettingsAction.py | 22 ++++++---- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index c8daca7f92..50525b6aeb 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -28,6 +28,20 @@ if TYPE_CHECKING: # # This keeps a list of extruder stacks for each machine. class ExtruderManager(QObject): + + ## Registers listeners and such to listen to changes to the extruders. + def __init__(self, parent = None): + super().__init__(parent) + + self._extruder_trains = {} # Per machine, a dictionary of extruder container stack IDs. Only for separately defined extruders. + self._active_extruder_index = -1 # Indicates the index of the active extruder stack. -1 means no active extruder stack + self._selected_object_extruders = [] + self._global_container_stack_definition_id = None + self._addCurrentMachineExtruders() + + Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) + Selection.selectionChanged.connect(self.resetSelectedObjectExtruders) + ## Signal to notify other components when the list of extruders for a machine definition changes. extrudersChanged = pyqtSignal(QVariant) @@ -38,18 +52,6 @@ class ExtruderManager(QObject): ## Notify when the user switches the currently active extruder. activeExtruderChanged = pyqtSignal() - ## Registers listeners and such to listen to changes to the extruders. - def __init__(self, parent = None): - super().__init__(parent) - self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. Only for separately defined extruders. - self._active_extruder_index = -1 # Indicates the index of the active extruder stack. -1 means no active extruder stack - self._selected_object_extruders = [] - Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) - self._global_container_stack_definition_id = None - self._addCurrentMachineExtruders() - - Selection.selectionChanged.connect(self.resetSelectedObjectExtruders) - ## Gets the unique identifier of the currently active extruder stack. # # The currently active extruder stack is the stack that is currently being @@ -59,10 +61,10 @@ class ExtruderManager(QObject): @pyqtProperty(str, notify = activeExtruderChanged) def activeExtruderStackId(self) -> Optional[str]: if not Application.getInstance().getGlobalContainerStack(): - return None # No active machine, so no active extruder. + return None # No active machine, so no active extruder. try: return self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId() - except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. + except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None ## Return extruder count according to extruder trains. @@ -521,8 +523,8 @@ class ExtruderManager(QObject): machine_extruder_count = global_stack.getProperty("machine_extruder_count", "value") # In case the printer is using one extruder, shouldn't exist active extruder stacks - if machine_extruder_count == 1: - return result + # if machine_extruder_count == 1: + # return result if global_stack and global_stack.getId() in self._extruder_trains: for extruder in sorted(self._extruder_trains[global_stack.getId()]): @@ -537,16 +539,10 @@ class ExtruderManager(QObject): self.globalContainerStackDefinitionChanged.emit() # If the global container changed, the number of extruders could be changed and so the active_extruder_index is updated - extruder_count = global_container_stack.getProperty("machine_extruder_count", "value") - if extruder_count > 1: - if self._active_extruder_index == -1: - self.setActiveExtruderIndex(0) - else: - if self._active_extruder_index != -1: - self.setActiveExtruderIndex(-1) + if self._active_extruder_index == -1: + self.setActiveExtruderIndex(0) self.activeExtruderChanged.emit() - self.resetSelectedObjectExtruders() ## Adds the extruders of the currently active machine. diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 4343c2c780..49f82a5c9b 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -171,17 +171,21 @@ class MachineSettingsAction(MachineAction): definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count) - if extruder_count > 1: - # Multiextrusion + # Make sure one of the extruder stacks is active + if extruder_manager.activeExtruderIndex == -1: + extruder_manager.setActiveExtruderIndex(0) + + # Move settable_per_extruder values out of the global container + extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStack() + global_user_container = self._global_container_stack.getTop() + + for setting_instance in global_user_container.findInstances(): + setting_key = setting_instance.definition.key + + + - # Make sure one of the extruder stacks is active - if extruder_manager.activeExtruderIndex == -1: - extruder_manager.setActiveExtruderIndex(0) - # Move settable_per_extruder values out of the global container - if previous_extruder_count == 1: - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - global_user_container = self._global_container_stack.getTop() for setting_instance in global_user_container.findInstances(): setting_key = setting_instance.definition.key From f0ed3bc588632837921795de5cc74f79a60c9568 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 11:05:35 +0200 Subject: [PATCH 02/54] Always populate extruder stacks when creating global stack - CURA-4482 --- cura/Settings/GlobalStack.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 88218c2f1e..81f9db76d0 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -23,9 +23,9 @@ class GlobalStack(CuraContainerStack): def __init__(self, container_id: str, *args, **kwargs): super().__init__(container_id, *args, **kwargs) - self.addMetaDataEntry("type", "machine") # For backward compatibility + self.addMetaDataEntry("type", "machine") # For backward compatibility - self._extruders = {} + self._extruders = {} # type: Dict[str, "ExtruderStack"] # This property is used to track which settings we are calculating the "resolve" for # and if so, to bypass the resolve to prevent an infinite recursion that would occur @@ -61,12 +61,15 @@ class GlobalStack(CuraContainerStack): # \throws Exceptions.TooManyExtrudersError Raised when trying to add an extruder while we # already have the maximum number of extruders. def addExtruder(self, extruder: ContainerStack) -> None: - extruder_count = self.getProperty("machine_extruder_count", "value") - if extruder_count <= 1: - Logger.log("i", "Not adding extruder[%s] to [%s] because it is a single-extrusion machine.", - extruder.id, self.id) - return + # CURA-4482 + # extruder_count = self.getProperty("machine_extruder_count", "value") + + # CURA-4482 + # if extruder_count <= 1: + # Logger.log("i", "Not adding extruder[%s] to [%s] because it is a single-extrusion machine.", + # extruder.id, self.id) + # return position = extruder.getMetaDataEntry("position") if position is None: From de34464e47a822887c6e8b4d9ddedbd2c3f5cb54 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 11:38:21 +0200 Subject: [PATCH 03/54] Update ProfilesModel to always use extruder stacks + some refactoring - CURA-4482 --- cura/Settings/ProfilesModel.py | 70 ++++++++++++++++------------------ 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index bf1993b184..a04ff00392 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -12,6 +12,11 @@ from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel from cura.QualityManager import QualityManager from cura.Settings.ExtruderManager import ExtruderManager +from typing import List, TYPE_CHECKING + +if TYPE_CHECKING: + from cura.Settings.ExtruderStack import ExtruderStack + ## QML Model for listing the current list of valid quality profiles. # @@ -28,9 +33,10 @@ class ProfilesModel(InstanceContainersModel): Application.getInstance().globalContainerStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) - Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) + self._machine_manager = Application.getInstance().getMachineManager() + self._machine_manager.activeVariantChanged.connect(self._update) + self._machine_manager.activeStackChanged.connect(self._update) + self._machine_manager.activeMaterialChanged.connect(self._update) # Factory function, used by QML @staticmethod @@ -54,17 +60,12 @@ class ProfilesModel(InstanceContainersModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return [] - global_stack_definition = global_container_stack.getBottom() + + global_stack_definition = global_container_stack.definition # Get the list of extruders and place the selected extruder at the front of the list. - extruder_manager = ExtruderManager.getInstance() - active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = extruder_manager.getActiveExtruderStacks() - materials = [global_container_stack.material] - if active_extruder in extruder_stacks: - extruder_stacks.remove(active_extruder) - extruder_stacks = [active_extruder] + extruder_stacks - materials = [extruder.material for extruder in extruder_stacks] + extruder_stacks = self._getOrderedExtruderStacksList() + materials = [extruder.material for extruder in extruder_stacks] # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. @@ -87,35 +88,16 @@ class ProfilesModel(InstanceContainersModel): ## Re-computes the items in this model, and adds the layer height role. def _recomputeItems(self): - #Some globals that we can re-use. global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return - # Detecting if the machine has multiple extrusion - multiple_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 - # Get the list of extruders and place the selected extruder at the front of the list. - extruder_manager = ExtruderManager.getInstance() - active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = extruder_manager.getActiveExtruderStacks() - if multiple_extrusion: - # Place the active extruder at the front of the list. - # This is a workaround checking if there is an active_extruder or not before moving it to the front of the list. - # Actually, when a printer has multiple extruders, should exist always an active_extruder. However, in some - # cases the active_extruder is still None. - if active_extruder in extruder_stacks: - extruder_stacks.remove(active_extruder) - new_extruder_stacks = [] - if active_extruder is not None: - new_extruder_stacks = [active_extruder] - extruder_stacks = new_extruder_stacks + extruder_stacks - - # Get a list of usable/available qualities for this machine and material - qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - extruder_stacks) + extruder_stacks = self._getOrderedExtruderStacksList() container_registry = ContainerRegistry.getInstance() - machine_manager = Application.getInstance().getMachineManager() + + # Get a list of usable/available qualities for this machine and material + qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) unit = global_container_stack.getBottom().getProperty("layer_height", "unit") if not unit: @@ -174,7 +156,7 @@ class ProfilesModel(InstanceContainersModel): # Quality-changes profile that has no value for layer height. Get the corresponding quality profile and ask that profile. quality_type = profile.getMetaDataEntry("quality_type", None) if quality_type: - quality_results = machine_manager.determineQualityAndQualityChangesForQualityType(quality_type) + quality_results = self._machine_manager.determineQualityAndQualityChangesForQualityType(quality_type) for quality_result in quality_results: if quality_result["stack"] is global_container_stack: quality = quality_result["quality"] @@ -198,6 +180,20 @@ class ProfilesModel(InstanceContainersModel): self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material. yield item - def _setItemLayerHeight(self, item, value, unit): + ## Get a list of extruder stacks with the active extruder at the front of the list. + @staticmethod + def _getOrderedExtruderStacksList() -> List["ExtruderStack"]: + extruder_manager = ExtruderManager.getInstance() + extruder_stacks = extruder_manager.getActiveExtruderStacks() + active_extruder = extruder_manager.getActiveExtruderStack() + + if active_extruder in extruder_stacks: + extruder_stacks.remove(active_extruder) + extruder_stacks = [active_extruder] + extruder_stacks + + return extruder_stacks + + @staticmethod + def _setItemLayerHeight(item, value, unit): item["layer_height"] = str(value) + unit item["layer_height_without_unit"] = str(value) From 152f6f840579b8cbf077fc24e3667b1cbe8bbe40 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 11:51:24 +0200 Subject: [PATCH 04/54] More profiles model refactoring - CURA-4482 --- cura/CrashHandler.py | 1 + cura/Settings/ProfilesModel.py | 24 +++++++------ .../MachineSettingsAction.py | 34 ++++++++++--------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index a78ecb8a72..ad80d286c3 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -53,6 +53,7 @@ class CrashHandler: self.exception_type = exception_type self.value = value self.traceback = tb + self.dialog = QDialog() # While we create the GUI, the information will be stored for sending afterwards self.data = dict() diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index a04ff00392..a46e3d146b 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -32,11 +32,9 @@ class ProfilesModel(InstanceContainersModel): self.addRoleName(self.AvailableRole, "available") Application.getInstance().globalContainerStackChanged.connect(self._update) - - self._machine_manager = Application.getInstance().getMachineManager() - self._machine_manager.activeVariantChanged.connect(self._update) - self._machine_manager.activeStackChanged.connect(self._update) - self._machine_manager.activeMaterialChanged.connect(self._update) + Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) + Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) # Factory function, used by QML @staticmethod @@ -153,17 +151,21 @@ class ProfilesModel(InstanceContainersModel): yield item continue + machine_manager = Application.getInstance().getMachineManager() + # Quality-changes profile that has no value for layer height. Get the corresponding quality profile and ask that profile. quality_type = profile.getMetaDataEntry("quality_type", None) if quality_type: - quality_results = self._machine_manager.determineQualityAndQualityChangesForQualityType(quality_type) + quality_results = machine_manager.determineQualityAndQualityChangesForQualityType(quality_type) for quality_result in quality_results: if quality_result["stack"] is global_container_stack: quality = quality_result["quality"] break - else: #No global container stack in the results: + else: + # No global container stack in the results: if quality_results: - quality = quality_results[0]["quality"] #Take any of the extruders. + # Take any of the extruders. + quality = quality_results[0]["quality"] else: quality = None if quality and quality.hasProperty("layer_height", "value"): @@ -171,11 +173,11 @@ class ProfilesModel(InstanceContainersModel): yield item continue - #Quality has no value for layer height either. Get the layer height from somewhere lower in the stack. + # Quality has no value for layer height either. Get the layer height from somewhere lower in the stack. skip_until_container = global_container_stack.material - if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No material in stack. + if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No material in stack. skip_until_container = global_container_stack.variant - if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No variant in stack. + if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No variant in stack. skip_until_container = global_container_stack.getBottom() self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material. yield item diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 49f82a5c9b..be76c0724a 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -176,25 +176,27 @@ class MachineSettingsAction(MachineAction): extruder_manager.setActiveExtruderIndex(0) # Move settable_per_extruder values out of the global container - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStack() + # extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStack() global_user_container = self._global_container_stack.getTop() - for setting_instance in global_user_container.findInstances(): - setting_key = setting_instance.definition.key - + if extruder_count > 1: + # Multi extrusion + # Make sure one of the extruder stacks is active + if extruder_manager.activeExtruderIndex == -1: + extruder_manager.setActiveExtruderIndex(0) - - - - - for setting_instance in global_user_container.findInstances(): - setting_key = setting_instance.definition.key - settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") - if settable_per_extruder: - limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) - extruder_stack = extruder_stacks[max(0, limit_to_extruder)] - extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) - global_user_container.removeInstance(setting_key) + # Move settable_per_extruder values out of the global container + if previous_extruder_count == 1: + extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() + global_user_container = self._global_container_stack.getTop() + for setting_instance in global_user_container.findInstances(): + setting_key = setting_instance.definition.key + settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") + if settable_per_extruder: + limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) + extruder_stack = extruder_stacks[max(0, limit_to_extruder)] + extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) + global_user_container.removeInstance(setting_key) else: # Single extrusion From 59580c0ade189a6a131ba1f5e848ab0f0cef8072 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 11:52:58 +0200 Subject: [PATCH 05/54] Remove commented out code - CURA-4482 --- cura/Settings/GlobalStack.py | 10 ---------- cura/Settings/ProfilesModel.py | 1 - 2 files changed, 11 deletions(-) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 81f9db76d0..2f27c4ab72 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -61,16 +61,6 @@ class GlobalStack(CuraContainerStack): # \throws Exceptions.TooManyExtrudersError Raised when trying to add an extruder while we # already have the maximum number of extruders. def addExtruder(self, extruder: ContainerStack) -> None: - - # CURA-4482 - # extruder_count = self.getProperty("machine_extruder_count", "value") - - # CURA-4482 - # if extruder_count <= 1: - # Logger.log("i", "Not adding extruder[%s] to [%s] because it is a single-extrusion machine.", - # extruder.id, self.id) - # return - position = extruder.getMetaDataEntry("position") if position is None: Logger.log("w", "No position defined for extruder {extruder}, cannot add it to stack {stack}", extruder = extruder.id, stack = self.id) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index a46e3d146b..7432605481 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -91,7 +91,6 @@ class ProfilesModel(InstanceContainersModel): return extruder_stacks = self._getOrderedExtruderStacksList() - container_registry = ContainerRegistry.getInstance() # Get a list of usable/available qualities for this machine and material From 62cb5a48cb1634c2e47cd6bb5c153bcc92d537e4 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 12:42:33 +0200 Subject: [PATCH 06/54] Refactor user profiles model to always use extruder stack - CURA-4482 --- cura/Settings/UserProfilesModel.py | 42 +++++++----------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/cura/Settings/UserProfilesModel.py b/cura/Settings/UserProfilesModel.py index aa815ef4aa..5ae9055759 100644 --- a/cura/Settings/UserProfilesModel.py +++ b/cura/Settings/UserProfilesModel.py @@ -22,47 +22,23 @@ class UserProfilesModel(ProfilesModel): # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() - machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) + machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) - # Detecting if the machine has multiple extrusion - multiple_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 - # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = extruder_manager.getActiveExtruderStacks() - if multiple_extrusion: - # Place the active extruder at the front of the list. - # This is a workaround checking if there is an active_extruder or not before moving it to the front of the list. - # Actually, when a printer has multiple extruders, should exist always an active_extruder. However, in some - # cases the active_extruder is still None. - if active_extruder in extruder_stacks: - extruder_stacks.remove(active_extruder) - new_extruder_stacks = [] - if active_extruder is not None: - new_extruder_stacks = [active_extruder] - else: - # if there is no active extruder, use the first one in the active extruder stacks - active_extruder = extruder_stacks[0] - extruder_stacks = new_extruder_stacks + extruder_stacks + extruder_stacks = self._getOrderedExtruderStacksList() - # Fetch the list of useable qualities across all extruders. + # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. - quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - extruder_stacks) + quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - - if multiple_extrusion: - # If the printer has multiple extruders then quality changes related to the current extruder are kept - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is not None and - (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or - qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())] - else: - # If not, the quality changes of the global stack are selected - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is None] + filtered_quality_changes = [qc for qc in quality_changes_list if + qc.getMetaDataEntry("quality_type") in quality_type_set and + qc.getMetaDataEntry("extruder") is not None and + (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or + qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())] return filtered_quality_changes From 79754209015e7fce11a66cbc7870a6946245c86f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 13:34:59 +0200 Subject: [PATCH 07/54] Always set active extruder index when loading active machine on start - CURA-4482 --- cura/Settings/MachineManager.py | 5 ++--- cura/Settings/QualitySettingsModel.py | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index fc5c415f87..d0f5cfb119 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -106,9 +106,8 @@ class MachineManager(QObject): if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacks(id = active_machine_id): # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - if self._global_container_stack and self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: - # Make sure _active_container_stack is properly initiated - ExtruderManager.getInstance().setActiveExtruderIndex(0) + # Make sure _active_container_stack is properly initiated + ExtruderManager.getInstance().setActiveExtruderIndex(0) self._auto_materials_changed = {} self._auto_hotends_changed = {} diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py index 2ab4e2a9b5..d0379dc510 100644 --- a/cura/Settings/QualitySettingsModel.py +++ b/cura/Settings/QualitySettingsModel.py @@ -224,7 +224,6 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): if self._extruder_id == "" and settable_per_extruder: continue - label = definition.label if self._i18n_catalog: label = self._i18n_catalog.i18nc(definition.key + " label", label) From 0b5709605654c91e17bf7b4bc7de57f751306659 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 13:44:47 +0200 Subject: [PATCH 08/54] Always use extruder stacks when switching global container in machine manager - CURA-4482 --- cura/Settings/MachineManager.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d0f5cfb119..c52dc65bf3 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -248,13 +248,13 @@ class MachineManager(QObject): if old_index is not None: extruder_manager.setActiveExtruderIndex(old_index) - self._auto_hotends_changed = {} #Processed all of them now. + self._auto_hotends_changed = {} # Processed all of them now. def _onGlobalContainerChanged(self): if self._global_container_stack: try: self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged) - except TypeError: #pyQtSignal gives a TypeError when disconnecting from something that was already disconnected. + except TypeError: # pyQtSignal gives a TypeError when disconnecting from something that was already disconnected. pass try: self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged) @@ -270,10 +270,9 @@ class MachineManager(QObject): quality = self._global_container_stack.quality quality.nameChanged.disconnect(self._onQualityNameChanged) - if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): - extruder_stack.propertyChanged.disconnect(self._onPropertyChanged) - extruder_stack.containersChanged.disconnect(self._onInstanceContainersChanged) + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): + extruder_stack.propertyChanged.disconnect(self._onPropertyChanged) + extruder_stack.containersChanged.disconnect(self._onInstanceContainersChanged) self._global_container_stack = Application.getInstance().getGlobalContainerStack() From 0021dee84bd89705e13739459c6d7f0a52689894 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 14:04:05 +0200 Subject: [PATCH 09/54] Always use extruder stacks when copying value to all extruder - CURA-4482 --- cura/Settings/MachineManager.py | 56 +++++++++++++++------------------ 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c52dc65bf3..f547ccf4a7 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -264,9 +264,12 @@ class MachineManager(QObject): self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged) except TypeError: pass + + # TODO: remove this - CURA-4482 material = self._global_container_stack.material material.nameChanged.disconnect(self._onMaterialNameChanged) + # TODO: remove this - CURA-4482 quality = self._global_container_stack.quality quality.nameChanged.disconnect(self._onQualityNameChanged) @@ -274,41 +277,33 @@ class MachineManager(QObject): extruder_stack.propertyChanged.disconnect(self._onPropertyChanged) extruder_stack.containersChanged.disconnect(self._onInstanceContainersChanged) + # update the local global container stack reference self._global_container_stack = Application.getInstance().getGlobalContainerStack() self.globalContainerChanged.emit() + # after switching the global stack we reconnect all the signals and set the variant and material references if self._global_container_stack: Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId()) + self._global_container_stack.nameChanged.connect(self._onMachineNameChanged) self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged) self._global_container_stack.propertyChanged.connect(self._onPropertyChanged) - if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: - # For multi-extrusion machines, we do not want variant or material profiles in the stack, - # because these are extruder specific and may cause wrong values to be used for extruders - # that did not specify a value in the extruder. - global_variant = self._global_container_stack.variant - if global_variant != self._empty_variant_container: - self._global_container_stack.setVariant(self._empty_variant_container) + # set the global variant to empty as we now use the extruder stack at all times - CURA-4482 + global_variant = self._global_container_stack.variant + if global_variant != self._empty_variant_container: + self._global_container_stack.setVariant(self._empty_variant_container) - global_material = self._global_container_stack.material - if global_material != self._empty_material_container: - self._global_container_stack.setMaterial(self._empty_material_container) + # set the global material to empty as we now use the extruder stack at all times - CURA-4482 + global_material = self._global_container_stack.material + if global_material != self._empty_material_container: + self._global_container_stack.setMaterial(self._empty_material_container) - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): #Listen for changes on all extruder stacks. - extruder_stack.propertyChanged.connect(self._onPropertyChanged) - extruder_stack.containersChanged.connect(self._onInstanceContainersChanged) - - else: - material = self._global_container_stack.material - material.nameChanged.connect(self._onMaterialNameChanged) - - quality = self._global_container_stack.quality - quality.nameChanged.connect(self._onQualityNameChanged) - - self._active_container_stack = self._global_container_stack - self.activeStackChanged.emit() + # Listen for changes on all extruder stacks + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): + extruder_stack.propertyChanged.connect(self._onPropertyChanged) + extruder_stack.containersChanged.connect(self._onInstanceContainersChanged) self._error_check_timer.start() @@ -721,15 +716,16 @@ class MachineManager(QObject): ## Copy the value of the setting of the current extruder to all other extruders as well as the global container. @pyqtSlot(str) def copyValueToExtruders(self, key: str): - if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1: - return - new_value = self._active_container_stack.getProperty(key, "value") - stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] - stacks.append(self._global_container_stack) - for extruder_stack in stacks: + extruder_stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] + + # TODO: remove this - CURA-4482 + extruder_stacks.append(self._global_container_stack) + + # check in which stack the value has to be replaced + for extruder_stack in extruder_stacks: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: - extruder_stack.getTop().setProperty(key, "value", new_value) + extruder_stack.userChanges.setProperty(key, "value", new_value) ## Set the active material by switching out a container # Depending on from/to material+current variant, a quality profile is chosen and set. From d6ef96a8250528a50ee6f7a0eb33b3d8ad6d62a3 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 14:07:47 +0200 Subject: [PATCH 10/54] Add todo comment --- 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 f547ccf4a7..68302186b7 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -725,7 +725,7 @@ class MachineManager(QObject): # check in which stack the value has to be replaced for extruder_stack in extruder_stacks: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: - extruder_stack.userChanges.setProperty(key, "value", new_value) + extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved ## Set the active material by switching out a container # Depending on from/to material+current variant, a quality profile is chosen and set. From 8378c6f3c94a878ea7156057cc1d2d7addeacf18 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 14:30:18 +0200 Subject: [PATCH 11/54] Always add extruder quality changes when getting quality changes by name - CURA-4482 --- cura/Settings/MachineManager.py | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 68302186b7..26de5dba87 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -945,10 +945,8 @@ class MachineManager(QObject): quality_manager = QualityManager.getInstance() global_container_stack = self._global_container_stack - global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) - - quality_changes_profiles = quality_manager.findQualityChangesByName(quality_changes_name, - global_machine_definition) + global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) + quality_changes_profiles = quality_manager.findQualityChangesByName(quality_changes_name, global_machine_definition) global_quality_changes = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") is None] if global_quality_changes: @@ -956,47 +954,52 @@ class MachineManager(QObject): else: Logger.log("e", "Could not find the global quality changes container with name %s", quality_changes_name) return None + + # TODO: remove this - CURA-4482 material = global_container_stack.material - # For the global stack, find a quality which matches the quality_type in - # the quality changes profile and also satisfies any material constraints. + # find a quality type that matches both machine and materials quality_type = global_quality_changes.getMetaDataEntry("quality_type") - if global_container_stack.getProperty("machine_extruder_count", "value") > 1: - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = True) - else: - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material]) - if not global_quality: - global_quality = self._empty_quality_container - # Find the values for each extruder. extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - for stack in extruder_stacks: - extruder_definition = quality_manager.getParentMachineDefinition(stack.getBottom()) + # append the extruder quality changes + for extruder_stack in extruder_stacks: + extruder_definition = quality_manager.getParentMachineDefinition(extruder_stack.definition) + + quality_changes_list = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") == extruder_definition.getId()] - quality_changes_list = [qcp for qcp in quality_changes_profiles - if qcp.getMetaDataEntry("extruder") == extruder_definition.getId()] if quality_changes_list: quality_changes = quality_changes_list[0] + # TODO: remove this - CURA-4482 else: quality_changes = global_quality_changes if not quality_changes: quality_changes = self._empty_quality_changes_container - material = stack.material + material = extruder_stack.material quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material]) - if not quality: #No quality profile found for this quality type. + + if not quality: + # No quality profile found for this quality type. quality = self._empty_quality_container - result.append({"stack": stack, "quality": quality, "quality_changes": quality_changes}) + result.append({ + "stack": extruder_stack, + "quality": quality, + "quality_changes": quality_changes + }) - if extruder_stacks: - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material], global_quality = "True") - if not global_quality: - global_quality = self._empty_quality_container - result.append({"stack": global_container_stack, "quality": global_quality, "quality_changes": global_quality_changes}) - else: - result.append({"stack": global_container_stack, "quality": global_quality, "quality_changes": global_quality_changes}) + # append the global quality changes + global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material], global_quality = True) + if not global_quality: + global_quality = self._empty_quality_container + + result.append({ + "stack": global_container_stack, + "quality": global_quality, + "quality_changes": global_quality_changes + }) return result From 38fdb5e56f72aa96ffc04f87e9877196fce05dd6 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 14:45:24 +0200 Subject: [PATCH 12/54] Refactor extruders model to always use extruder stacks + cleanup - CURA-4482 --- cura/Settings/ExtrudersModel.py | 72 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index b13e51723b..f2bb9f761c 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -66,18 +66,18 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self._update_extruder_timer = QTimer() self._update_extruder_timer.setInterval(100) self._update_extruder_timer.setSingleShot(True) - self._update_extruder_timer.timeout.connect(self.__updateExtruders) + self._update_extruder_timer.connect(self.__updateExtruders) self._add_global = False self._simple_names = False - self._active_machine_extruders = [] # type: Iterable[ExtruderStack] + self._active_machine_extruders = [] # type: Iterable[ExtruderStack] self._add_optional_extruder = False - #Listen to changes. - Application.getInstance().globalContainerStackChanged.connect(self._extrudersChanged) #When the machine is swapped we must update the active machine extruders. - ExtruderManager.getInstance().extrudersChanged.connect(self._extrudersChanged) #When the extruders change we must link to the stack-changed signal of the new extruder. - self._extrudersChanged() #Also calls _updateExtruders. + # Listen to changes + Application.getInstance().globalContainerStackChanged.connect(self._extrudersChanged) # When the machine is swapped we must update the active machine extruders + ExtruderManager.getInstance().extrudersChanged.connect(self._extrudersChanged) # When the extruders change we must link to the stack-changed signal of the new extruder + self._extrudersChanged() # Also calls _updateExtruders def setAddGlobal(self, add): if add != self._add_global: @@ -128,21 +128,24 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): def _extrudersChanged(self, machine_id = None): if machine_id is not None: if Application.getInstance().getGlobalContainerStack() is None: - return #No machine, don't need to update the current machine's extruders. + # No machine, don't need to update the current machine's extruders + return if machine_id != Application.getInstance().getGlobalContainerStack().getId(): - return #Not the current machine. - #Unlink from old extruders. + # Not the current machine + return + + # Unlink from old extruders for extruder in self._active_machine_extruders: extruder.containersChanged.disconnect(self._onExtruderStackContainersChanged) - #Link to new extruders. + # Link to new extruders self._active_machine_extruders = [] extruder_manager = ExtruderManager.getInstance() for extruder in extruder_manager.getExtruderStacks(): extruder.containersChanged.connect(self._onExtruderStackContainersChanged) self._active_machine_extruders.append(extruder) - self._updateExtruders() #Since the new extruders may have different properties, update our own model. + self._updateExtruders() # Since the new extruders may have different properties, update our own model. def _onExtruderStackContainersChanged(self, container): # Update when there is an empty container or material change @@ -150,7 +153,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): # The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name self._updateExtruders() - modelChanged = pyqtSignal() def _updateExtruders(self): @@ -161,14 +163,17 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): # This should be called whenever the list of extruders changes. @UM.FlameProfiler.profile def __updateExtruders(self): - changed = False + extruders_changed = False if self.rowCount() != 0: - changed = True + extruders_changed = True items = [] + global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: + + # TODO: remove this - CURA-4482 if self._add_global: material = global_container_stack.material color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0] @@ -180,40 +185,44 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): "definition": "" } items.append(item) - changed = True + extruders_changed = True + # get machine extruder count for verification machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value") - manager = ExtruderManager.getInstance() - for extruder in manager.getMachineExtruders(global_container_stack.getId()): + + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()): position = extruder.getMetaDataEntry("position", default = "0") # Get the position try: position = int(position) - except ValueError: #Not a proper int. + except ValueError: + # Not a proper int. position = -1 if position >= machine_extruder_count: continue - extruder_name = extruder.getName() - material = extruder.material - variant = extruder.variant - default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0] - color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color - item = { #Construct an item with only the relevant information. + default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0] + color = extruder.material.getMetaDataEntry("color_code", default = default_color) if material else default_color + + # construct an item with only the relevant information + item = { "id": extruder.getId(), - "name": extruder_name, + "name": extruder.getName(), "color": color, "index": position, "definition": extruder.getBottom().getId(), - "material": material.getName() if material else "", - "variant": variant.getName() if variant else "", + "material": extruder.material.getName() if material else "", + "variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core } - items.append(item) - changed = True - if changed: + items.append(item) + extruders_changed = True + + if extruders_changed: + # sort by extruder index items.sort(key = lambda i: i["index"]) + # We need optional extruder to be last, so add it after we do sorting. - # This way we can simply intrepret the -1 of the index as the last item (which it now always is) + # This way we can simply interpret the -1 of the index as the last item (which it now always is) if self._add_optional_extruder: item = { "id": "", @@ -223,5 +232,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): "definition": "" } items.append(item) + self.setItems(items) self.modelChanged.emit() From 723f6ce2265c889cb3f5b4385420fc43cf7f3238 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 15:10:52 +0200 Subject: [PATCH 13/54] Only get extruder settings from extruder stack - CURA-4482 --- cura/Settings/ExtruderManager.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 50525b6aeb..0b48568364 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -398,16 +398,12 @@ class ExtruderManager(QObject): # \param setting_key \type{str} The setting to get the property of. # \param property \type{str} The property to get. # \return \type{List} the list of results - def getAllExtruderSettings(self, setting_key, property): - global_container_stack = Application.getInstance().getGlobalContainerStack() - if global_container_stack.getProperty("machine_extruder_count", "value") <= 1: - return [global_container_stack.getProperty(setting_key, property)] - + def getAllExtruderSettings(self, setting_key: str, prop: str): result = [] for index in self.extruderIds: extruder_stack_id = self.extruderIds[str(index)] - stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] - result.append(stack.getProperty(setting_key, property)) + extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + result.append(extruder_stack.getProperty(setting_key, prop)) return result ## Gets the extruder stacks that are actually being used at the moment. From b91824aab1bad7391ab5b16623297e823b77e445 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 26 Oct 2017 17:54:36 +0200 Subject: [PATCH 14/54] Move towards making extruder manager a first class citizen - CURA-4482 --- cura/BuildVolume.py | 51 +++++++++-------- cura/ConvexHullDecorator.py | 21 ++++--- cura/CuraApplication.py | 27 +++++---- cura/Settings/CuraStackBuilder.py | 5 +- cura/Settings/ExtruderManager.py | 58 ++++++++++++++------ cura/Settings/ExtrudersModel.py | 2 +- cura/Settings/MachineManager.py | 2 +- cura/Settings/QualityAndUserProfilesModel.py | 42 +++----------- cura/Settings/SettingInheritanceManager.py | 21 ++++--- 9 files changed, 121 insertions(+), 108 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index e87bfebd94..ba9314477d 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -917,24 +917,23 @@ class BuildVolume(SceneNode): # which extruder to get the setting, if there are multiple extruders. # \param property The property to get from the setting. # \return The property of the specified setting in the specified extruder. - def _getSettingFromExtruder(self, setting_key, extruder_setting_key, property = "value"): - multi_extrusion = self._global_container_stack.getProperty("machine_extruder_count", "value") > 1 + def _getSettingFromExtruder(self, setting_key, extruder_setting_key, prop = "value"): + extruder_index = self._global_container_stack.getProperty(extruder_setting_key, "value") - if not multi_extrusion: - stack = self._global_container_stack + # TODO: remove this - CURA-4482 + if str(extruder_index) == "-1": # If extruder index is -1 use global instead + extruder_stack = self._global_container_stack else: - extruder_index = self._global_container_stack.getProperty(extruder_setting_key, "value") + extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] + extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] - if str(extruder_index) == "-1": # If extruder index is -1 use global instead - stack = self._global_container_stack - else: - extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] - stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + value = extruder_stack.getProperty(setting_key, prop) + setting_type = extruder_stack.getProperty(setting_key, "type") - value = stack.getProperty(setting_key, property) - setting_type = stack.getProperty(setting_key, "type") + # default 0 for numerical values if not value and (setting_type == "int" or setting_type == "float"): return 0 + return value ## Convenience function to calculate the disallowed radius around the edge. @@ -945,6 +944,7 @@ class BuildVolume(SceneNode): def _getEdgeDisallowedSize(self): if not self._global_container_stack: return 0 + container_stack = self._global_container_stack used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks() @@ -953,26 +953,33 @@ class BuildVolume(SceneNode): return 0.1 # Return a very small value, so we do draw disallowed area's near the edges. adhesion_type = container_stack.getProperty("adhesion_type", "value") + if adhesion_type == "skirt": skirt_distance = self._getSettingFromAdhesionExtruder("skirt_gap") skirt_line_count = self._getSettingFromAdhesionExtruder("skirt_line_count") bed_adhesion_size = skirt_distance + (self._getSettingFromAdhesionExtruder("skirt_brim_line_width") * skirt_line_count) * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor") / 100.0 - if len(used_extruders) > 1: - for extruder_stack in used_extruders: - bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 - #We don't create an additional line for the extruder we're printing the skirt with. - bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + + for extruder_stack in used_extruders: + bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 + + # We don't create an additional line for the extruder we're printing the skirt with. + bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + elif adhesion_type == "brim": bed_adhesion_size = self._getSettingFromAdhesionExtruder("skirt_brim_line_width") * self._getSettingFromAdhesionExtruder("brim_line_count") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor") / 100.0 - if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: - for extruder_stack in used_extruders: - bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 - #We don't create an additional line for the extruder we're printing the brim with. - bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + + for extruder_stack in used_extruders: + bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 + + # We don't create an additional line for the extruder we're printing the brim with. + bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + elif adhesion_type == "raft": bed_adhesion_size = self._getSettingFromAdhesionExtruder("raft_margin") + elif adhesion_type == "none": bed_adhesion_size = 0 + else: raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?") diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py index bfeb690192..50fa8ce7f6 100644 --- a/cura/ConvexHullDecorator.py +++ b/cura/ConvexHullDecorator.py @@ -302,24 +302,23 @@ class ConvexHullDecorator(SceneNodeDecorator): self._onChanged() ## Private convenience function to get a setting from the correct extruder (as defined by limit_to_extruder property). - def _getSettingProperty(self, setting_key, property = "value"): + def _getSettingProperty(self, setting_key, prop = "value"): per_mesh_stack = self._node.callDecoration("getStack") if per_mesh_stack: - return per_mesh_stack.getProperty(setting_key, property) - - multi_extrusion = self._global_stack.getProperty("machine_extruder_count", "value") > 1 - if not multi_extrusion: - return self._global_stack.getProperty(setting_key, property) + return per_mesh_stack.getProperty(setting_key, prop) extruder_index = self._global_stack.getProperty(setting_key, "limit_to_extruder") - if extruder_index == "-1": #No limit_to_extruder. + if extruder_index == "-1": + # No limit_to_extruder extruder_stack_id = self._node.callDecoration("getActiveExtruder") - if not extruder_stack_id: #Decoration doesn't exist. + if not extruder_stack_id: + # Decoration doesn't exist extruder_stack_id = ExtruderManager.getInstance().extruderIds["0"] extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] - return extruder_stack.getProperty(setting_key, property) - else: #Limit_to_extruder is set. The global stack handles this then. - return self._global_stack.getProperty(setting_key, property) + return extruder_stack.getProperty(setting_key, prop) + else: + # Limit_to_extruder is set. The global stack handles this then + return self._global_stack.getProperty(setting_key, prop) ## Returns true if node is a descendant or the same as the root node. def __isDescendant(self, root, node): diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1680e7c6a6..7904066966 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -200,6 +200,7 @@ class CuraApplication(QtApplication): self._machine_action_manager = MachineActionManager.MachineActionManager() self._machine_manager = None # This is initialized on demand. + self._extruder_manager = None self._material_manager = None self._setting_inheritance_manager = None self._simple_mode_settings_manager = None @@ -259,20 +260,24 @@ class CuraApplication(QtApplication): # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() + empty_variant_container = copy.deepcopy(empty_container) empty_variant_container._id = "empty_variant" empty_variant_container.addMetaDataEntry("type", "variant") ContainerRegistry.getInstance().addContainer(empty_variant_container) + empty_material_container = copy.deepcopy(empty_container) empty_material_container._id = "empty_material" empty_material_container.addMetaDataEntry("type", "material") ContainerRegistry.getInstance().addContainer(empty_material_container) + empty_quality_container = copy.deepcopy(empty_container) empty_quality_container._id = "empty_quality" empty_quality_container.setName("Not Supported") empty_quality_container.addMetaDataEntry("quality_type", "normal") empty_quality_container.addMetaDataEntry("type", "quality") ContainerRegistry.getInstance().addContainer(empty_quality_container) + empty_quality_changes_container = copy.deepcopy(empty_container) empty_quality_changes_container._id = "empty_quality_changes" empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") @@ -413,7 +418,7 @@ class CuraApplication(QtApplication): def discardOrKeepProfileChangesClosed(self, option): if option == "discard": global_stack = self.getGlobalContainerStack() - for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + for extruder in self._extruder_manager.getMachineExtruders(global_stack.getId()): extruder.getTop().clear() global_stack.getTop().clear() @@ -421,7 +426,7 @@ class CuraApplication(QtApplication): # 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()): + for extruder in self._extruder_manager.getMachineExtruders(global_stack.getId()): user_extruder_container = extruder.getTop() if user_extruder_container: user_extruder_container.update() @@ -686,16 +691,13 @@ class CuraApplication(QtApplication): self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface...")) - # Initialise extruder so as to listen to global container stack changes before the first global container stack is set. - ExtruderManager.getInstance() + qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager) qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager) qmlRegisterSingletonType(MaterialManager, "Cura", 1, 0, "MaterialManager", self.getMaterialManager) - qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", - self.getSettingInheritanceManager) - qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", - self.getSimpleModeSettingsManager) - + qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager) + qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) + self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) self.initializeEngine() @@ -717,6 +719,11 @@ class CuraApplication(QtApplication): self._machine_manager = MachineManager.createMachineManager() return self._machine_manager + def getExtruderManager(self, *args): + if self._extruder_manager is None: + self._extruder_manager = ExtruderManager.createExtruderManager() + return self._extruder_manager + def getMaterialManager(self, *args): if self._material_manager is None: self._material_manager = MaterialManager.createMaterialManager() @@ -784,7 +791,7 @@ class CuraApplication(QtApplication): actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml"))) qmlRegisterSingletonType(actions_url, "Cura", 1, 0, "Actions") - engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.getInstance()) + # engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.getInstance()) for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 09815da319..e3774b0153 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -62,6 +62,7 @@ class CuraStackBuilder: variant = "default", next_stack = new_global_stack ) + new_global_stack.addExtruder(new_extruder) return new_global_stack @@ -79,7 +80,9 @@ class CuraStackBuilder: stack.setName(definition.getName()) stack.setDefinition(definition) stack.addMetaDataEntry("position", definition.getMetaDataEntry("position")) - if "next_stack" in kwargs: #Add stacks before containers are added, since they may trigger a setting update. + + if "next_stack" in kwargs: + # Add stacks before containers are added, since they may trigger a setting update. stack.setNextStack(kwargs["next_stack"]) user_container = InstanceContainer(new_stack_id + "_user") diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 0b48568364..a32b333326 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -83,18 +83,23 @@ class ExtruderManager(QObject): @pyqtProperty("QVariantMap", notify = extrudersChanged) def extruderIds(self): extruder_stack_ids = {} + global_stack_id = Application.getInstance().getGlobalContainerStack().getId() - extruder_stack_ids["-1"] = global_stack_id + + # TODO: remove this? - CURA-4482 + # extruder_stack_ids["-1"] = global_stack_id + if global_stack_id in self._extruder_trains: for position in self._extruder_trains[global_stack_id]: extruder_stack_ids[position] = self._extruder_trains[global_stack_id][position].getId() + return extruder_stack_ids @pyqtSlot(str, result = str) - def getQualityChangesIdByExtruderStackId(self, id: str) -> str: + def getQualityChangesIdByExtruderStackId(self, extruder_stack_id: str) -> str: for position in self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()]: extruder = self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()][position] - if extruder.getId() == id: + if extruder.getId() == extruder_stack_id: return extruder.qualityChanges.getId() ## The instance of the singleton pattern. @@ -102,6 +107,10 @@ class ExtruderManager(QObject): # It's None if the extruder manager hasn't been created yet. __instance = None + @staticmethod + def createExtruderManager(): + return ExtruderManager() + ## Gets an instance of the extruder manager, or creates one if no instance # exists yet. # @@ -420,20 +429,21 @@ class ExtruderManager(QObject): global_stack = Application.getInstance().getGlobalContainerStack() container_registry = ContainerRegistry.getInstance() - if global_stack.getProperty("machine_extruder_count", "value") <= 1: #For single extrusion. - return [global_stack] - used_extruder_stack_ids = set() - #Get the extruders of all meshes in the scene. + # Get the extruders of all meshes in the scene support_enabled = False support_bottom_enabled = False support_roof_enabled = False + scene_root = Application.getInstance().getController().getScene().getRoot() - meshes = [node for node in DepthFirstIterator(scene_root) if type(node) is SceneNode and node.isSelectable()] #Only use the nodes that will be printed. + + # Get the extruders of all printable meshes in the scene + meshes = [node for node in DepthFirstIterator(scene_root) if type(node) is SceneNode and node.isSelectable()] for mesh in meshes: extruder_stack_id = mesh.callDecoration("getActiveExtruder") - if not extruder_stack_id: #No per-object settings for this node. + if not extruder_stack_id: + # No per-object settings for this node extruder_stack_id = self.extruderIds["0"] used_extruder_stack_ids.add(extruder_stack_id) @@ -469,9 +479,10 @@ class ExtruderManager(QObject): if support_roof_enabled: used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_roof_extruder_nr", "value"))]) - #The platform adhesion extruder. Not used if using none. + # The platform adhesion extruder. Not used if using none. if global_stack.getProperty("adhesion_type", "value") != "none": used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("adhesion_extruder_nr", "value"))]) + try: return [container_registry.findContainerStacks(id = stack_id)[0] for stack_id in used_extruder_stack_ids] except IndexError: # One or more of the extruders was not found. @@ -518,10 +529,6 @@ class ExtruderManager(QObject): result = [] machine_extruder_count = global_stack.getProperty("machine_extruder_count", "value") - # In case the printer is using one extruder, shouldn't exist active extruder stacks - # if machine_extruder_count == 1: - # return result - if global_stack and global_stack.getId() in self._extruder_trains: for extruder in sorted(self._extruder_trains[global_stack.getId()]): result.append(self._extruder_trains[global_stack.getId()][extruder]) @@ -544,8 +551,23 @@ class ExtruderManager(QObject): ## Adds the extruders of the currently active machine. def _addCurrentMachineExtruders(self) -> None: global_stack = Application.getInstance().getGlobalContainerStack() + extruders_changed = False + if global_stack and global_stack.getBottom(): - self.addMachineExtruders(global_stack.getBottom(), global_stack.getId()) + container_registry = ContainerRegistry.getInstance() + machine_id = global_stack.getBottom().getId() + + # Gets the extruder trains that we just created as well as any that still existed. + extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_id) + for extruder_train in extruder_trains: + self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train + + # regardless of what the next stack is, we have to set it again, because of signal routing. + extruder_train.setNextStack(global_stack) + extruders_changed = True + + if extruders_changed: + self.extrudersChanged.emit(machine_id) ## Get all extruder values for a certain setting. # @@ -560,7 +582,7 @@ class ExtruderManager(QObject): global_stack = Application.getInstance().getGlobalContainerStack() result = [] - for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + for extruder in ExtruderManager.getMachineExtruders(global_stack.getId()): # only include values from extruders that are "active" for the current machine instance if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value"): continue @@ -600,7 +622,7 @@ class ExtruderManager(QObject): } result = [] - for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + for extruder in ExtruderManager.getMachineExtruders(global_stack.getId()): # only include values from extruders that are "active" for the current machine instance if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value", context = context): continue @@ -624,7 +646,7 @@ class ExtruderManager(QObject): # # This is exposed to qml for display purposes # - # \param key The key of the setting to retieve values for. + # \param key The key of the setting to retrieve values for. # # \return String representing the extruder values @pyqtSlot(str, result="QVariant") diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index f2bb9f761c..996bf51138 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -66,7 +66,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self._update_extruder_timer = QTimer() self._update_extruder_timer.setInterval(100) self._update_extruder_timer.setSingleShot(True) - self._update_extruder_timer.connect(self.__updateExtruders) + self._update_extruder_timer.timeout.connect(self.__updateExtruders) self._add_global = False self._simple_names = False diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 26de5dba87..c4be25abd9 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1173,7 +1173,7 @@ class MachineManager(QObject): return containers[0].getBottom().getId() @staticmethod - def createMachineManager(engine=None, script_engine=None): + def createMachineManager(): return MachineManager() @deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7") diff --git a/cura/Settings/QualityAndUserProfilesModel.py b/cura/Settings/QualityAndUserProfilesModel.py index 9d7d913d5e..2e181c6031 100644 --- a/cura/Settings/QualityAndUserProfilesModel.py +++ b/cura/Settings/QualityAndUserProfilesModel.py @@ -22,47 +22,23 @@ class QualityAndUserProfilesModel(ProfilesModel): # Fetch the list of quality changes. quality_manager = QualityManager.getInstance() - machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) + machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) - # Detecting if the machine has multiple extrusion - multiple_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 - # Get the list of extruders extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = extruder_manager.getActiveExtruderStacks() - if multiple_extrusion: - # Place the active extruder at the front of the list. - # This is a workaround checking if there is an active_extruder or not before moving it to the front of the list. - # Actually, when a printer has multiple extruders, should exist always an active_extruder. However, in some - # cases the active_extruder is still None. - if active_extruder in extruder_stacks: - extruder_stacks.remove(active_extruder) - new_extruder_stacks = [] - if active_extruder is not None: - new_extruder_stacks = [active_extruder] - else: - # if there is no active extruder, use the first one in the active extruder stacks - active_extruder = extruder_stacks[0] - extruder_stacks = new_extruder_stacks + extruder_stacks + extruder_stacks = self._getOrderedExtruderStacksList() - # Fetch the list of useable qualities across all extruders. + # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. - quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - extruder_stacks) + quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - - if multiple_extrusion: - # If the printer has multiple extruders then quality changes related to the current extruder are kept - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is not None and - (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or - qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())] - else: - # If not, the quality changes of the global stack are selected - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is None] + filtered_quality_changes = [qc for qc in quality_changes_list if + qc.getMetaDataEntry("quality_type") in quality_type_set and + qc.getMetaDataEntry("extruder") is not None and + (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or + qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())] return quality_list + filtered_quality_changes diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py index 8c9f5b20d6..00f637d34c 100644 --- a/cura/Settings/SettingInheritanceManager.py +++ b/cura/Settings/SettingInheritanceManager.py @@ -47,21 +47,20 @@ class SettingInheritanceManager(QObject): @pyqtSlot(str, str, result = "QStringList") def getOverridesForExtruder(self, key, extruder_index): - multi_extrusion = self._global_container_stack.getProperty("machine_extruder_count", "value") > 1 - if not multi_extrusion: - return self._settings_with_inheritance_warning - extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index) - if not extruder: - Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index) - return [] + result = [] - definitions = self._global_container_stack.definition.findDefinitions(key=key) + extruder_stack = ExtruderManager.getInstance().getExtruderStack(extruder_index) + if not extruder_stack: + Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index) + return result + + definitions = self._global_container_stack.definition.findDefinitions(key = key) if not definitions: Logger.log("w", "Could not find definition for key [%s] (2)", key) - return [] - result = [] + return result + for key in definitions[0].getAllKeys(): - if self._settingIsOverwritingInheritance(key, extruder): + if self._settingIsOverwritingInheritance(key, extruder_stack): result.append(key) return result From d718e6e36c3b44c9a4e81618a031bc7f727bfc18 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 09:08:20 +0100 Subject: [PATCH 15/54] Create extruder stack for single extruder machines on start - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 60 +++- cura/Settings/CuraStackBuilder.py | 2 +- cura/Settings/ExtruderManager.py | 334 ++++++++++----------- cura/Settings/ExtrudersModel.py | 4 +- cura/Settings/MachineManager.py | 15 +- cura/Settings/SettingInheritanceManager.py | 4 +- cura/Settings/SettingOverrideDecorator.py | 6 +- resources/definitions/101Hero.def.json | 4 - resources/definitions/3dator.def.json | 7 +- resources/qml/Cura.qml | 2 +- resources/qml/ExtruderButton.qml | 2 +- resources/qml/Menus/ContextMenu.qml | 2 +- resources/qml/Menus/MaterialMenu.qml | 16 +- resources/qml/Menus/NozzleMenu.qml | 14 +- resources/qml/Preferences/ProfilesPage.qml | 2 +- resources/qml/PrintMonitor.qml | 2 +- resources/qml/Settings/SettingItem.qml | 2 +- resources/qml/Settings/SettingView.qml | 8 +- resources/qml/SidebarHeader.qml | 4 +- resources/qml/SidebarSimple.qml | 2 +- 20 files changed, 268 insertions(+), 224 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 12f27e8156..26dc8b775e 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -12,6 +12,7 @@ from PyQt5.QtWidgets import QMessageBox from UM.Decorators import override from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.InstanceContainer import InstanceContainer from UM.Application import Application from UM.Logger import Logger @@ -42,12 +43,13 @@ class CuraContainerRegistry(ContainerRegistry): # Global stack based on metadata information. @override(ContainerRegistry) def addContainer(self, container): + # Note: Intentional check with type() because we want to ignore subclasses if type(container) == ContainerStack: container = self._convertContainerStack(container) if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()): - #Check against setting version of the definition. + # Check against setting version of the definition. required_setting_version = CuraApplication.SettingVersion actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0)) if required_setting_version != actual_setting_version: @@ -256,7 +258,8 @@ class CuraContainerRegistry(ContainerRegistry): @override(ContainerRegistry) def load(self): super().load() - self._fixupExtruders() + self._registerSingleExtrusionMachinesExtruderStacks() + self._connectUpgradedExtruderStacksToMachines() ## Update an imported profile to match the current machine configuration. # @@ -357,8 +360,8 @@ class CuraContainerRegistry(ContainerRegistry): return global_container_stack.material.getId() return "" - ## Returns true if the current machien requires its own quality profiles - # \return true if the current machien requires its own quality profiles + ## Returns true if the current machine requires its own quality profiles + # \return true if the current machine requires its own quality profiles def _machineHasOwnQualities(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: @@ -391,12 +394,59 @@ class CuraContainerRegistry(ContainerRegistry): return new_stack + def _registerSingleExtrusionMachinesExtruderStacks(self): + machines = ContainerRegistry.getInstance().findContainerStacks(machine_extruder_trains = {"0": "fdmextruder"}) + for machine in machines: + self._addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder") + + def _addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): + new_extruder_id = extruder_id + + if machine.extruders and len(machine.extruders) > 0: + new_extruder_id = machine.extruders["0"].getId() + + extruder_definitions = self.findDefinitionContainers(id = new_extruder_id) + + if not extruder_definitions: + Logger.log("w", "Could not find definition containers for extruder %s", new_extruder_id) + return + + extruder_definition = extruder_definitions[0] + unique_name = self.uniqueName(machine.getId() + " " + new_extruder_id) + + extruder_stack = ExtruderStack.ExtruderStack(unique_name) + extruder_stack.setName(extruder_definition.getName()) + extruder_stack.setDefinition(extruder_definition) + extruder_stack.addMetaDataEntry("machine", machine.getId()) + extruder_stack.addMetaDataEntry("position", "0") + extruder_stack.setNextStack(machine) + + # if machine.userChanges: + # # set existing user changes if found + # extruder_stack.setUserChanges(machine.userChanges) + # else: + # # create empty user changes container otherwise + # user_container = InstanceContainer(extruder_stack.getId() + "_user") + # user_container.addMetaDataEntry("type", "user") + # user_container.addMetaDataEntry("machine", extruder_stack.getId()) + # from cura.CuraApplication import CuraApplication + # user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + # user_container.setDefinition(extruder_definition) + # extruder_stack.setUserChanges(user_container) + # self.addContainer(user_container) + + # extruder_stack.setVariantById("default") + # extruder_stack.setMaterialById("default") + # extruder_stack.setQualityById("default") + + self.addContainer(extruder_stack) + # Fix the extruders that were upgraded to ExtruderStack instances during addContainer. # The stacks are now responsible for setting the next stack on deserialize. However, # due to problems with loading order, some stacks may not have the proper next stack # set after upgrading, because the proper global stack was not yet loaded. This method # makes sure those extruders also get the right stack set. - def _fixupExtruders(self): + def _connectUpgradedExtruderStacksToMachines(self): extruder_stacks = self.findContainers(ExtruderStack.ExtruderStack) for extruder_stack in extruder_stacks: if extruder_stack.getNextStack(): diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index e3774b0153..368fd9847d 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -62,7 +62,7 @@ class CuraStackBuilder: variant = "default", next_stack = new_global_stack ) - new_global_stack.addExtruder(new_extruder) + # new_global_stack.addExtruder(new_extruder) return new_global_stack diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index a32b333326..97b622132a 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -1,21 +1,18 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant #For communicating data and events to Qt. +from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant # For communicating data and events to Qt. from UM.FlameProfiler import pyqtSlot -from UM.Application import Application #To get the global container stack to find the current machine. +from UM.Application import Application # To get the global container stack to find the current machine. from UM.Logger import Logger -from UM.Decorators import deprecated from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator -from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers by ID. -from UM.Settings.InstanceContainer import InstanceContainer +from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID. from UM.Settings.SettingFunction import SettingFunction from UM.Settings.ContainerStack import ContainerStack -from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext from typing import Optional, List, TYPE_CHECKING, Union @@ -214,39 +211,39 @@ class ExtruderManager(QObject): result.append(self.getExtruderStack(i)) return result - ## Adds all extruders of a specific machine definition to the extruder - # manager. + # ## Adds all extruders of a specific machine definition to the extruder + # # manager. + # # + # # \param machine_definition The machine definition to add the extruders for. + # # \param machine_id The machine_id to add the extruders for. + # @deprecated("Use CuraStackBuilder", "2.6") + # def addMachineExtruders(self, machine_definition: DefinitionContainerInterface, machine_id: str) -> None: + # changed = False + # machine_definition_id = machine_definition.getId() + # if machine_id not in self._extruder_trains: + # self._extruder_trains[machine_id] = { } + # changed = True + # container_registry = ContainerRegistry.getInstance() + # if container_registry: + # # Add the extruder trains that don't exist yet. + # for extruder_definition in container_registry.findDefinitionContainers(machine = machine_definition_id): + # position = extruder_definition.getMetaDataEntry("position", None) + # if not position: + # Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) + # if not container_registry.findContainerStacks(machine = machine_id, position = position): # Doesn't exist yet. + # self.createExtruderTrain(extruder_definition, machine_definition, position, machine_id) + # changed = True # - # \param machine_definition The machine definition to add the extruders for. - # \param machine_id The machine_id to add the extruders for. - @deprecated("Use CuraStackBuilder", "2.6") - def addMachineExtruders(self, machine_definition: DefinitionContainerInterface, machine_id: str) -> None: - changed = False - machine_definition_id = machine_definition.getId() - if machine_id not in self._extruder_trains: - self._extruder_trains[machine_id] = { } - changed = True - container_registry = ContainerRegistry.getInstance() - if container_registry: - # Add the extruder trains that don't exist yet. - for extruder_definition in container_registry.findDefinitionContainers(machine = machine_definition_id): - position = extruder_definition.getMetaDataEntry("position", None) - if not position: - Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) - if not container_registry.findContainerStacks(machine = machine_id, position = position): # Doesn't exist yet. - self.createExtruderTrain(extruder_definition, machine_definition, position, machine_id) - changed = True - - # Gets the extruder trains that we just created as well as any that still existed. - extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_id) - for extruder_train in extruder_trains: - self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train - - # regardless of what the next stack is, we have to set it again, because of signal routing. - extruder_train.setNextStack(Application.getInstance().getGlobalContainerStack()) - changed = True - if changed: - self.extrudersChanged.emit(machine_id) + # # Gets the extruder trains that we just created as well as any that still existed. + # extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_id) + # for extruder_train in extruder_trains: + # self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train + # + # # regardless of what the next stack is, we have to set it again, because of signal routing. + # extruder_train.setNextStack(Application.getInstance().getGlobalContainerStack()) + # changed = True + # if changed: + # self.extrudersChanged.emit(machine_id) def registerExtruder(self, extruder_train, machine_id): changed = False @@ -267,137 +264,137 @@ class ExtruderManager(QObject): if changed: self.extrudersChanged.emit(machine_id) - ## Creates a container stack for an extruder train. + # ## Creates a container stack for an extruder train. + # # + # # The container stack has an extruder definition at the bottom, which is + # # linked to a machine definition. Then it has a variant profile, a material + # # profile, a quality profile and a user profile, in that order. + # # + # # The resulting container stack is added to the registry. + # # + # # \param extruder_definition The extruder to create the extruder train for. + # # \param machine_definition The machine that the extruder train belongs to. + # # \param position The position of this extruder train in the extruder slots of the machine. + # # \param machine_id The id of the "global" stack this extruder is linked to. + # @deprecated("Use CuraStackBuilder::createExtruderStack", "2.6") + # def createExtruderTrain(self, extruder_definition: DefinitionContainerInterface, machine_definition: DefinitionContainerInterface, + # position, machine_id: str) -> None: + # # Cache some things. + # container_registry = ContainerRegistry.getInstance() + # machine_definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_definition) # - # The container stack has an extruder definition at the bottom, which is - # linked to a machine definition. Then it has a variant profile, a material - # profile, a quality profile and a user profile, in that order. + # # Create a container stack for this extruder. + # extruder_stack_id = container_registry.uniqueName(extruder_definition.getId()) + # container_stack = ContainerStack(extruder_stack_id) + # container_stack.setName(extruder_definition.getName()) # Take over the display name to display the stack with. + # container_stack.addMetaDataEntry("type", "extruder_train") + # container_stack.addMetaDataEntry("machine", machine_id) + # container_stack.addMetaDataEntry("position", position) + # container_stack.addContainer(extruder_definition) # - # The resulting container stack is added to the registry. + # # Find the variant to use for this extruder. + # variant = container_registry.findInstanceContainers(id = "empty_variant")[0] + # if machine_definition.getMetaDataEntry("has_variants"): + # # First add any variant. Later, overwrite with preference if the preference is valid. + # variants = container_registry.findInstanceContainers(definition = machine_definition_id, type = "variant") + # if len(variants) >= 1: + # variant = variants[0] + # preferred_variant_id = machine_definition.getMetaDataEntry("preferred_variant") + # if preferred_variant_id: + # preferred_variants = container_registry.findInstanceContainers(id = preferred_variant_id, definition = machine_definition_id, type = "variant") + # if len(preferred_variants) >= 1: + # variant = preferred_variants[0] + # else: + # Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) + # # And leave it at the default variant. + # container_stack.addContainer(variant) # - # \param extruder_definition The extruder to create the extruder train for. - # \param machine_definition The machine that the extruder train belongs to. - # \param position The position of this extruder train in the extruder slots of the machine. - # \param machine_id The id of the "global" stack this extruder is linked to. - @deprecated("Use CuraStackBuilder::createExtruderStack", "2.6") - def createExtruderTrain(self, extruder_definition: DefinitionContainerInterface, machine_definition: DefinitionContainerInterface, - position, machine_id: str) -> None: - # Cache some things. - container_registry = ContainerRegistry.getInstance() - machine_definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_definition) - - # Create a container stack for this extruder. - extruder_stack_id = container_registry.uniqueName(extruder_definition.getId()) - container_stack = ContainerStack(extruder_stack_id) - container_stack.setName(extruder_definition.getName()) # Take over the display name to display the stack with. - container_stack.addMetaDataEntry("type", "extruder_train") - container_stack.addMetaDataEntry("machine", machine_id) - container_stack.addMetaDataEntry("position", position) - container_stack.addContainer(extruder_definition) - - # Find the variant to use for this extruder. - variant = container_registry.findInstanceContainers(id = "empty_variant")[0] - if machine_definition.getMetaDataEntry("has_variants"): - # First add any variant. Later, overwrite with preference if the preference is valid. - variants = container_registry.findInstanceContainers(definition = machine_definition_id, type = "variant") - if len(variants) >= 1: - variant = variants[0] - preferred_variant_id = machine_definition.getMetaDataEntry("preferred_variant") - if preferred_variant_id: - preferred_variants = container_registry.findInstanceContainers(id = preferred_variant_id, definition = machine_definition_id, type = "variant") - if len(preferred_variants) >= 1: - variant = preferred_variants[0] - else: - Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) - # And leave it at the default variant. - container_stack.addContainer(variant) - - # Find a material to use for this variant. - material = container_registry.findInstanceContainers(id = "empty_material")[0] - if machine_definition.getMetaDataEntry("has_materials"): - # First add any material. Later, overwrite with preference if the preference is valid. - machine_has_variant_materials = machine_definition.getMetaDataEntry("has_variant_materials", default = False) - if machine_has_variant_materials or machine_has_variant_materials == "True": - materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id, variant = variant.getId()) - else: - materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id) - if len(materials) >= 1: - material = materials[0] - preferred_material_id = machine_definition.getMetaDataEntry("preferred_material") - if preferred_material_id: - global_stack = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) - if global_stack: - approximate_material_diameter = str(round(global_stack[0].getProperty("material_diameter", "value"))) - else: - approximate_material_diameter = str(round(machine_definition.getProperty("material_diameter", "value"))) - - search_criteria = { "type": "material", "id": preferred_material_id, "approximate_diameter": approximate_material_diameter} - if machine_definition.getMetaDataEntry("has_machine_materials"): - search_criteria["definition"] = machine_definition_id - - if machine_definition.getMetaDataEntry("has_variants") and variant: - search_criteria["variant"] = variant.id - else: - search_criteria["definition"] = "fdmprinter" - - preferred_materials = container_registry.findInstanceContainers(**search_criteria) - if len(preferred_materials) >= 1: - # In some cases we get multiple materials. In that case, prefer materials that are marked as read only. - read_only_preferred_materials = [preferred_material for preferred_material in preferred_materials if preferred_material.isReadOnly()] - if len(read_only_preferred_materials) >= 1: - material = read_only_preferred_materials[0] - else: - material = preferred_materials[0] - else: - Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) - # And leave it at the default material. - container_stack.addContainer(material) - - # Find a quality to use for this extruder. - quality = container_registry.getEmptyInstanceContainer() - - search_criteria = { "type": "quality" } - if machine_definition.getMetaDataEntry("has_machine_quality"): - search_criteria["definition"] = machine_definition_id - if machine_definition.getMetaDataEntry("has_materials") and material: - search_criteria["material"] = material.id - else: - search_criteria["definition"] = "fdmprinter" - - preferred_quality = machine_definition.getMetaDataEntry("preferred_quality") - if preferred_quality: - search_criteria["id"] = preferred_quality - - containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - if not containers and preferred_quality: - Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality, machine_id) - search_criteria.pop("id", None) - containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - if containers: - quality = containers[0] - - container_stack.addContainer(quality) - - empty_quality_changes = container_registry.findInstanceContainers(id = "empty_quality_changes")[0] - container_stack.addContainer(empty_quality_changes) - - user_profile = container_registry.findInstanceContainers(type = "user", extruder = extruder_stack_id) - if user_profile: # There was already a user profile, loaded from settings. - user_profile = user_profile[0] - else: - user_profile = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. - user_profile.addMetaDataEntry("type", "user") - user_profile.addMetaDataEntry("extruder", extruder_stack_id) - from cura.CuraApplication import CuraApplication - user_profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_profile.setDefinition(machine_definition) - container_registry.addContainer(user_profile) - container_stack.addContainer(user_profile) - - # regardless of what the next stack is, we have to set it again, because of signal routing. - container_stack.setNextStack(Application.getInstance().getGlobalContainerStack()) - - container_registry.addContainer(container_stack) + # # Find a material to use for this variant. + # material = container_registry.findInstanceContainers(id = "empty_material")[0] + # if machine_definition.getMetaDataEntry("has_materials"): + # # First add any material. Later, overwrite with preference if the preference is valid. + # machine_has_variant_materials = machine_definition.getMetaDataEntry("has_variant_materials", default = False) + # if machine_has_variant_materials or machine_has_variant_materials == "True": + # materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id, variant = variant.getId()) + # else: + # materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id) + # if len(materials) >= 1: + # material = materials[0] + # preferred_material_id = machine_definition.getMetaDataEntry("preferred_material") + # if preferred_material_id: + # global_stack = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) + # if global_stack: + # approximate_material_diameter = str(round(global_stack[0].getProperty("material_diameter", "value"))) + # else: + # approximate_material_diameter = str(round(machine_definition.getProperty("material_diameter", "value"))) + # + # search_criteria = { "type": "material", "id": preferred_material_id, "approximate_diameter": approximate_material_diameter} + # if machine_definition.getMetaDataEntry("has_machine_materials"): + # search_criteria["definition"] = machine_definition_id + # + # if machine_definition.getMetaDataEntry("has_variants") and variant: + # search_criteria["variant"] = variant.id + # else: + # search_criteria["definition"] = "fdmprinter" + # + # preferred_materials = container_registry.findInstanceContainers(**search_criteria) + # if len(preferred_materials) >= 1: + # # In some cases we get multiple materials. In that case, prefer materials that are marked as read only. + # read_only_preferred_materials = [preferred_material for preferred_material in preferred_materials if preferred_material.isReadOnly()] + # if len(read_only_preferred_materials) >= 1: + # material = read_only_preferred_materials[0] + # else: + # material = preferred_materials[0] + # else: + # Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) + # # And leave it at the default material. + # container_stack.addContainer(material) + # + # # Find a quality to use for this extruder. + # quality = container_registry.getEmptyInstanceContainer() + # + # search_criteria = { "type": "quality" } + # if machine_definition.getMetaDataEntry("has_machine_quality"): + # search_criteria["definition"] = machine_definition_id + # if machine_definition.getMetaDataEntry("has_materials") and material: + # search_criteria["material"] = material.id + # else: + # search_criteria["definition"] = "fdmprinter" + # + # preferred_quality = machine_definition.getMetaDataEntry("preferred_quality") + # if preferred_quality: + # search_criteria["id"] = preferred_quality + # + # containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + # if not containers and preferred_quality: + # Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality, machine_id) + # search_criteria.pop("id", None) + # containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + # if containers: + # quality = containers[0] + # + # container_stack.addContainer(quality) + # + # empty_quality_changes = container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + # container_stack.addContainer(empty_quality_changes) + # + # user_profile = container_registry.findInstanceContainers(type = "user", extruder = extruder_stack_id) + # if user_profile: # There was already a user profile, loaded from settings. + # user_profile = user_profile[0] + # else: + # user_profile = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. + # user_profile.addMetaDataEntry("type", "user") + # user_profile.addMetaDataEntry("extruder", extruder_stack_id) + # from cura.CuraApplication import CuraApplication + # user_profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + # user_profile.setDefinition(machine_definition) + # container_registry.addContainer(user_profile) + # container_stack.addContainer(user_profile) + # + # # regardless of what the next stack is, we have to set it again, because of signal routing. + # container_stack.setNextStack(Application.getInstance().getGlobalContainerStack()) + # + # container_registry.addContainer(container_stack) def getAllExtruderValues(self, setting_key): return self.getAllExtruderSettings(setting_key, "value") @@ -545,7 +542,6 @@ class ExtruderManager(QObject): if self._active_extruder_index == -1: self.setActiveExtruderIndex(0) - self.activeExtruderChanged.emit() self.resetSelectedObjectExtruders() ## Adds the extruders of the currently active machine. @@ -562,7 +558,7 @@ class ExtruderManager(QObject): for extruder_train in extruder_trains: self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train - # regardless of what the next stack is, we have to set it again, because of signal routing. + # regardless of what the next stack is, we have to set it again, because of signal routing. ??? extruder_train.setNextStack(global_stack) extruders_changed = True @@ -582,7 +578,7 @@ class ExtruderManager(QObject): global_stack = Application.getInstance().getGlobalContainerStack() result = [] - for extruder in ExtruderManager.getMachineExtruders(global_stack.getId()): + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): # only include values from extruders that are "active" for the current machine instance if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value"): continue diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 996bf51138..40d13461cc 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -201,7 +201,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): continue default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0] - color = extruder.material.getMetaDataEntry("color_code", default = default_color) if material else default_color + color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color # construct an item with only the relevant information item = { @@ -210,7 +210,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): "color": color, "index": position, "definition": extruder.getBottom().getId(), - "material": extruder.material.getName() if material else "", + "material": extruder.material.getName() if extruder.material else "", "variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core } diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c4be25abd9..bcc64fdefb 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -300,6 +300,17 @@ class MachineManager(QObject): if global_material != self._empty_material_container: self._global_container_stack.setMaterial(self._empty_material_container) + # TODO: update stack builder since this is not always a user created stack + # if len(self._global_container_stack.extruders) == 0: + # extruder_stack = CuraStackBuilder.createExtruderStack( + # self._global_container_stack.getId(), + # definition = self._global_container_stack.definition, + # machine_definition = self._global_container_stack.definition, + # ) + # extruder_stack.setNextStack(self._global_container_stack) + # extruder_stack.propertyChanged.connect(self._onPropertyChanged) + # extruder_stack.containersChanged.connect(self._onInstanceContainersChanged) + # Listen for changes on all extruder stacks for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.propertyChanged.connect(self._onPropertyChanged) @@ -320,8 +331,8 @@ class MachineManager(QObject): old_active_container_stack = self._active_container_stack self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() - if not self._active_container_stack: - self._active_container_stack = self._global_container_stack + # if not self._active_container_stack: + # self._active_container_stack = self._global_container_stack self._error_check_timer.start() diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py index 00f637d34c..0d4cd02cdb 100644 --- a/cura/Settings/SettingInheritanceManager.py +++ b/cura/Settings/SettingInheritanceManager.py @@ -77,8 +77,8 @@ class SettingInheritanceManager(QObject): def _onActiveExtruderChanged(self): new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack() - if not new_active_stack: - new_active_stack = self._global_container_stack + # if not new_active_stack: + # new_active_stack = self._global_container_stack if new_active_stack != self._active_container_stack: # Check if changed if self._active_container_stack: # Disconnect signal from old container (if any) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index 4e0893a35f..5026f9760d 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -27,11 +27,7 @@ class SettingOverrideDecorator(SceneNodeDecorator): self._stack = PerObjectContainerStack(stack_id = id(self)) self._stack.setDirty(False) # This stack does not need to be saved. self._stack.addContainer(InstanceContainer(container_id = "SettingOverrideInstanceContainer")) - - if ExtruderManager.getInstance().extruderCount > 1: - self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() - else: - self._extruder_stack = None + self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() self._stack.propertyChanged.connect(self._onSettingChanged) diff --git a/resources/definitions/101Hero.def.json b/resources/definitions/101Hero.def.json index 3d19aef626..aaea743b47 100644 --- a/resources/definitions/101Hero.def.json +++ b/resources/definitions/101Hero.def.json @@ -7,10 +7,6 @@ "visible": true, "author": "rikky", "manufacturer": "101Hero", - "machine_extruder_trains": - { - "0": "fdmextruder" - }, "file_formats": "text/x-gcode", "platform": "101hero-platform.stl", "supports_usb_connection": true diff --git a/resources/definitions/3dator.def.json b/resources/definitions/3dator.def.json index b72a49a35b..513ee8f0e1 100644 --- a/resources/definitions/3dator.def.json +++ b/resources/definitions/3dator.def.json @@ -10,11 +10,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "supports_usb_connection": true, - "platform": "3dator_platform.stl", - "machine_extruder_trains": - { - "0": "fdmextruder" - } + "platform": "3dator_platform.stl" }, "overrides": { @@ -29,7 +25,6 @@ "layer_height": { "default_value": 0.2 }, "speed_print": { "default_value": 50 }, "speed_infill": { "default_value": 60 }, - "machine_extruder_count": { "default_value": 1 }, "machine_heated_bed": { "default_value": true }, "machine_center_is_zero": { "default_value": false }, "machine_height": { "default_value": 260 }, diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index cb0211f29f..325902e1be 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -177,7 +177,7 @@ UM.MainWindow MenuSeparator { } - MenuItem { text: catalog.i18nc("@action:inmenu", "Set as Active Extruder"); onTriggered: ExtruderManager.setActiveExtruderIndex(model.index) } + MenuItem { text: catalog.i18nc("@action:inmenu", "Set as Active Extruder"); onTriggered: Cura.ExtruderManager.setActiveExtruderIndex(model.index) } } onObjectAdded: settingsMenu.insertItem(index, object) onObjectRemoved: settingsMenu.removeItem(object) diff --git a/resources/qml/ExtruderButton.qml b/resources/qml/ExtruderButton.qml index 99196b0c9f..9212c705f7 100644 --- a/resources/qml/ExtruderButton.qml +++ b/resources/qml/ExtruderButton.qml @@ -18,7 +18,7 @@ Button style: UM.Theme.styles.tool_button; iconSource: UM.Theme.getIcon("extruder_button") - checked: ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1 + checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1 enabled: UM.Selection.hasSelection property color customColor: base.hovered ? UM.Theme.getColor("button_hover") : UM.Theme.getColor("button"); diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index 39d497722f..b2c95ebcd8 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -31,7 +31,7 @@ Menu visible: base.shouldShowExtruders enabled: UM.Selection.hasSelection checkable: true - checked: ExtruderManager.selectedObjectExtruders.indexOf(model.id) != -1 + checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(model.id) != -1 onTriggered: CuraActions.setExtruderForSelection(model.id) shortcut: "Ctrl+" + (model.index + 1) } diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 359f4f41d0..1feb351bb1 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -72,16 +72,16 @@ Menu { text: model.name checkable: true - checked: model.id == Cura.MachineManager.allActiveMaterialIds[ExtruderManager.extruderIds[extruderIndex]] + checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] exclusiveGroup: group onTriggered: { // This workaround is done because of the application menus for materials and variants for multiextrusion printers. // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. - var activeExtruderIndex = ExtruderManager.activeExtruderIndex; - ExtruderManager.setActiveExtruderIndex(extruderIndex); + var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; + Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); Cura.MachineManager.setActiveMaterial(model.id); - ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); } } onObjectAdded: menu.insertItem(index, object) @@ -115,16 +115,16 @@ Menu { text: model.name checkable: true - checked: model.id == Cura.MachineManager.allActiveMaterialIds[ExtruderManager.extruderIds[extruderIndex]] + checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] exclusiveGroup: group onTriggered: { // This workaround is done because of the application menus for materials and variants for multiextrusion printers. // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. - var activeExtruderIndex = ExtruderManager.activeExtruderIndex; - ExtruderManager.setActiveExtruderIndex(extruderIndex); + var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; + Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); Cura.MachineManager.setActiveMaterial(model.id); - ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); } } onObjectAdded: brandMaterialsMenu.insertItem(index, object) diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 1c75a346f3..9dead66499 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -38,15 +38,15 @@ Menu visible: printerConnected && Cura.MachineManager.printerOutputDevices[0].hotendIds.length > extruderIndex && !isClusterPrinter onTriggered: { - var activeExtruderIndex = ExtruderManager.activeExtruderIndex; - ExtruderManager.setActiveExtruderIndex(extruderIndex); + var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; + Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); var hotendId = Cura.MachineManager.printerOutputDevices[0].hotendIds[extruderIndex]; var itemIndex = nozzleInstantiator.model.find("name", hotendId); if(itemIndex > -1) { Cura.MachineManager.setActiveVariant(nozzleInstantiator.model.getItem(itemIndex).id); } - ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); } } @@ -69,14 +69,14 @@ Menu MenuItem { text: model.name checkable: true - checked: model.id == Cura.MachineManager.allActiveVariantIds[ExtruderManager.extruderIds[extruderIndex]] + checked: model.id == Cura.MachineManager.allActiveVariantIds[Cura.ExtruderManager.extruderIds[extruderIndex]] exclusiveGroup: group onTriggered: { - var activeExtruderIndex = ExtruderManager.activeExtruderIndex; - ExtruderManager.setActiveExtruderIndex(extruderIndex); + var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; + Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); Cura.MachineManager.setActiveVariant(model.id); - ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); } } onObjectAdded: menu.insertItem(index, object) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index c7b6b3e933..e3ba9b23a4 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -208,7 +208,7 @@ UM.ManagementPage anchors.right: parent.right anchors.bottom: parent.bottom - currentIndex: ExtruderManager.extruderCount > 0 ? ExtruderManager.activeExtruderIndex + 1 : 0 + currentIndex: Cura.ExtruderManager.extruderCount > 0 ? Cura.ExtruderManager.activeExtruderIndex + 1 : 0 ProfileTab { diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index a2626e53de..34e68148b8 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -87,7 +87,7 @@ Column Label //Extruder name. { - text: ExtruderManager.getExtruderName(index) != "" ? ExtruderManager.getExtruderName(index) : catalog.i18nc("@label", "Extruder") + text: Cura.ExtruderManager.getExtruderName(index) != "" ? Cura.ExtruderManager.getExtruderName(index) : catalog.i18nc("@label", "Extruder") color: UM.Theme.getColor("text") font: UM.Theme.getFont("default") anchors.left: parent.left diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 2bf2c17273..6234e5f1f7 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -157,7 +157,7 @@ Item { var tooltipText = catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders") + "."; if ((resolve != "None") && (stackLevel != 0)) { // We come here if a setting has a resolve and the setting is not manually edited. - tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + ExtruderManager.getInstanceExtruderValues(definition.key) + "]."; + tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + Cura.ExtruderManager.getInstanceExtruderValues(definition.key) + "]."; } base.showTooltip(tooltipText); } diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 56fd789564..93bb52de79 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -268,7 +268,7 @@ Item Behavior on opacity { NumberAnimation { duration: 100 } } enabled: { - if(!ExtruderManager.activeExtruderStackId && machineExtruderCount.properties.value > 1) + if (!Cura.ExtruderManager.activeExtruderStackId && machineExtruderCount.properties.value > 1) { // disable all controls on the global tab, except categories return model.type == "category" @@ -338,12 +338,12 @@ Item if(inheritStackProvider.properties.limit_to_extruder != null && inheritStackProvider.properties.limit_to_extruder >= 0) { //We have limit_to_extruder, so pick that stack. - return ExtruderManager.extruderIds[String(inheritStackProvider.properties.limit_to_extruder)]; + return Cura.ExtruderManager.extruderIds[String(inheritStackProvider.properties.limit_to_extruder)]; } - if(ExtruderManager.activeExtruderStackId) + if(Cura.ExtruderManager.activeExtruderStackId) { //We're on an extruder tab. Pick the current extruder. - return ExtruderManager.activeExtruderStackId; + return Cura.ExtruderManager.activeExtruderStackId; } //No extruder tab is selected. Pick the global stack. Shouldn't happen any more since we removed the global tab. return activeMachineId; diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index f3887e2885..2ea5b0b3d2 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -14,7 +14,7 @@ Column { id: base; - property int currentExtruderIndex: ExtruderManager.activeExtruderIndex; + property int currentExtruderIndex: Cura.ExtruderManager.activeExtruderIndex; property bool currentExtruderVisible: extrudersList.visible; spacing: Math.floor(UM.Theme.getSize("sidebar_margin").width * 0.9) @@ -93,7 +93,7 @@ Column onClicked: { forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. - ExtruderManager.setActiveExtruderIndex(index); + Cura.ExtruderManager.setActiveExtruderIndex(index); } style: ButtonStyle diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 65a3d612dc..34780d2219 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -19,7 +19,7 @@ Item property Action configureSettings; property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime; - property bool settingsEnabled: ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1 + property bool settingsEnabled: Cura.ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1 Component.onCompleted: PrintInformation.enabled = true Component.onDestruction: PrintInformation.enabled = false From f36c9ffbc0d7100ba11cbd56b9aeb0a5ee4854bc Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 09:49:24 +0100 Subject: [PATCH 16/54] Create extruder stack for single extrusion machines when adding new machine - CURA-4482 --- cura/BuildVolume.py | 9 ++----- cura/Settings/CuraStackBuilder.py | 42 ++++++++++++++++++++++--------- cura/Settings/ExtruderManager.py | 5 ++++ cura/Settings/MachineManager.py | 2 -- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index ba9314477d..7362a5aff2 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -919,13 +919,8 @@ class BuildVolume(SceneNode): # \return The property of the specified setting in the specified extruder. def _getSettingFromExtruder(self, setting_key, extruder_setting_key, prop = "value"): extruder_index = self._global_container_stack.getProperty(extruder_setting_key, "value") - - # TODO: remove this - CURA-4482 - if str(extruder_index) == "-1": # If extruder index is -1 use global instead - extruder_stack = self._global_container_stack - else: - extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] - extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] + extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] value = extruder_stack.getProperty(setting_key, prop) setting_type = extruder_stack.getProperty(setting_key, "type") diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 368fd9847d..b9fbbc43f0 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -47,22 +47,40 @@ class CuraStackBuilder: new_global_stack.setName(generated_name) - for extruder_definition in registry.findDefinitionContainers(machine = machine_definition.id): - position = extruder_definition.getMetaDataEntry("position", None) - if not position: - Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.id) + extruder_definition = registry.findDefinitionContainers(machine = machine_definition.getId()) - new_extruder_id = registry.uniqueName(extruder_definition.id) + if not extruder_definition: + # create extruder stack for single extrusion machines that have no separate extruder definition files + extruder_definition = registry.findDefinitionContainers(id = "fdmextruder") + new_extruder_id = registry.uniqueName(machine_definition.getId() + " " + "fdmextruder") new_extruder = cls.createExtruderStack( new_extruder_id, - definition = extruder_definition, - machine_definition = machine_definition, - quality = "default", - material = "default", - variant = "default", - next_stack = new_global_stack + definition=extruder_definition, + machine_definition=machine_definition, + quality="default", + material="default", + variant="default", + next_stack=new_global_stack ) - # new_global_stack.addExtruder(new_extruder) + new_global_stack.addExtruder(new_extruder) + else: + # create extruder stack for each found extruder definition + for extruder_definition in registry.findDefinitionContainers(machine = machine_definition.id): + position = extruder_definition.getMetaDataEntry("position", None) + if not position: + Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.id) + + new_extruder_id = registry.uniqueName(extruder_definition.id) + new_extruder = cls.createExtruderStack( + new_extruder_id, + definition = extruder_definition, + machine_definition = machine_definition, + quality = "default", + material = "default", + variant = "default", + next_stack = new_global_stack + ) + new_global_stack.addExtruder(new_extruder) return new_global_stack diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 97b622132a..38bc41813b 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -193,6 +193,7 @@ class ExtruderManager(QObject): if global_container_stack.getId() in self._extruder_trains: if str(self._active_extruder_index) in self._extruder_trains[global_container_stack.getId()]: return self._extruder_trains[global_container_stack.getId()][str(self._active_extruder_index)] + return None ## Get an extruder stack by index @@ -435,6 +436,10 @@ class ExtruderManager(QObject): scene_root = Application.getInstance().getController().getScene().getRoot() + # If no extruders are registered in the extruder manager yet, return an empty array + if len(self.extruderIds) == 0: + return [] + # Get the extruders of all printable meshes in the scene meshes = [node for node in DepthFirstIterator(scene_root) if type(node) is SceneNode and node.isSelectable()] for mesh in meshes: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 13751794f0..0f3a690967 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -340,8 +340,6 @@ class MachineManager(QObject): old_active_container_stack = self._active_container_stack self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() - # if not self._active_container_stack: - # self._active_container_stack = self._global_container_stack self._error_check_timer.start() From 4701518404a5243a28b9f342d6613c15ab8e705d Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 10:23:30 +0100 Subject: [PATCH 17/54] Add default position to fdm extruder definition - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 30 +++++++++++----------- cura/Settings/CuraStackBuilder.py | 2 +- resources/definitions/fdmextruder.def.json | 3 ++- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 11c4cf2d4a..6ce87aafea 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -424,23 +424,23 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.addMetaDataEntry("position", "0") extruder_stack.setNextStack(machine) - # if machine.userChanges: - # # set existing user changes if found - # extruder_stack.setUserChanges(machine.userChanges) - # else: - # # create empty user changes container otherwise - # user_container = InstanceContainer(extruder_stack.getId() + "_user") - # user_container.addMetaDataEntry("type", "user") - # user_container.addMetaDataEntry("machine", extruder_stack.getId()) - # from cura.CuraApplication import CuraApplication - # user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - # user_container.setDefinition(extruder_definition) - # extruder_stack.setUserChanges(user_container) - # self.addContainer(user_container) + if machine.userChanges: + # set existing user changes if found + extruder_stack.setUserChanges(machine.userChanges) + else: + # create empty user changes container otherwise + user_container = InstanceContainer(extruder_stack.getId() + "_user") + user_container.addMetaDataEntry("type", "user") + user_container.addMetaDataEntry("machine", extruder_stack.getId()) + from cura.CuraApplication import CuraApplication + user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + user_container.setDefinition(extruder_definition) + extruder_stack.setUserChanges(user_container) + self.addContainer(user_container) # extruder_stack.setVariantById("default") - # extruder_stack.setMaterialById("default") - # extruder_stack.setQualityById("default") + extruder_stack.setMaterialById("default") + extruder_stack.setQualityById("default") self.addContainer(extruder_stack) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index b9fbbc43f0..57eefa0397 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -51,7 +51,7 @@ class CuraStackBuilder: if not extruder_definition: # create extruder stack for single extrusion machines that have no separate extruder definition files - extruder_definition = registry.findDefinitionContainers(id = "fdmextruder") + extruder_definition = registry.findDefinitionContainers(id = "fdmextruder")[0] new_extruder_id = registry.uniqueName(machine_definition.getId() + " " + "fdmextruder") new_extruder = cls.createExtruderStack( new_extruder_id, diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json index 8ed194fc2d..ada35fafe0 100644 --- a/resources/definitions/fdmextruder.def.json +++ b/resources/definitions/fdmextruder.def.json @@ -8,7 +8,8 @@ "author": "Ultimaker", "manufacturer": "Unknown", "setting_version": 1, - "visible": false + "visible": false, + "position": "0" }, "settings": { From bc6984a0edacf5948c73c23ce2f694ac1c6c031a Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 13:19:28 +0100 Subject: [PATCH 18/54] Fixes for selecting active variant, material and quality - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 10 ++-- cura/Settings/CuraStackBuilder.py | 2 +- cura/Settings/ExtruderManager.py | 23 +++++---- cura/Settings/MachineManager.py | 65 +++++++++++++++----------- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 6ce87aafea..4923a343a0 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -405,6 +405,7 @@ class CuraContainerRegistry(ContainerRegistry): def _addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): new_extruder_id = extruder_id + # if extruders are defined in the machine definition use those instead if machine.extruders and len(machine.extruders) > 0: new_extruder_id = machine.extruders["0"].getId() @@ -415,13 +416,12 @@ class CuraContainerRegistry(ContainerRegistry): return extruder_definition = extruder_definitions[0] - unique_name = self.uniqueName(machine.getId() + " " + new_extruder_id) + unique_name = self.uniqueName(machine.getName() + " " + new_extruder_id) extruder_stack = ExtruderStack.ExtruderStack(unique_name) extruder_stack.setName(extruder_definition.getName()) extruder_stack.setDefinition(extruder_definition) - extruder_stack.addMetaDataEntry("machine", machine.getId()) - extruder_stack.addMetaDataEntry("position", "0") + extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) extruder_stack.setNextStack(machine) if machine.userChanges: @@ -429,7 +429,7 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.setUserChanges(machine.userChanges) else: # create empty user changes container otherwise - user_container = InstanceContainer(extruder_stack.getId() + "_user") + user_container = InstanceContainer(extruder_stack.id + "_user") user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("machine", extruder_stack.getId()) from cura.CuraApplication import CuraApplication @@ -438,7 +438,7 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.setUserChanges(user_container) self.addContainer(user_container) - # extruder_stack.setVariantById("default") + extruder_stack.setVariantById("default") extruder_stack.setMaterialById("default") extruder_stack.setQualityById("default") diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 57eefa0397..a661237722 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -52,7 +52,7 @@ class CuraStackBuilder: if not extruder_definition: # create extruder stack for single extrusion machines that have no separate extruder definition files extruder_definition = registry.findDefinitionContainers(id = "fdmextruder")[0] - new_extruder_id = registry.uniqueName(machine_definition.getId() + " " + "fdmextruder") + new_extruder_id = registry.uniqueName(machine_definition.getName() + " " + extruder_definition.id) new_extruder = cls.createExtruderStack( new_extruder_id, definition=extruder_definition, diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 38bc41813b..40ac2f1c63 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -543,9 +543,8 @@ class ExtruderManager(QObject): self._global_container_stack_definition_id = global_container_stack.getBottom().getId() self.globalContainerStackDefinitionChanged.emit() - # If the global container changed, the number of extruders could be changed and so the active_extruder_index is updated - if self._active_extruder_index == -1: - self.setActiveExtruderIndex(0) + # If the global container changed, the machine changed and might have extruders that were not registered yet + self._addCurrentMachineExtruders() self.resetSelectedObjectExtruders() @@ -554,21 +553,29 @@ class ExtruderManager(QObject): global_stack = Application.getInstance().getGlobalContainerStack() extruders_changed = False - if global_stack and global_stack.getBottom(): + if global_stack: container_registry = ContainerRegistry.getInstance() - machine_id = global_stack.getBottom().getId() + global_stack_id = global_stack.getId() # Gets the extruder trains that we just created as well as any that still existed. - extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_id) + extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = global_stack_id) + + # Make sure the extruder trains for the new machine can be placed in the set of sets + if global_stack_id not in self._extruder_trains: + self._extruder_trains[global_stack_id] = {} + extruders_changed = True + + # Register the extruder trains by position for extruder_train in extruder_trains: - self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train + self._extruder_trains[global_stack_id][extruder_train.getMetaDataEntry("position")] = extruder_train # regardless of what the next stack is, we have to set it again, because of signal routing. ??? extruder_train.setNextStack(global_stack) extruders_changed = True if extruders_changed: - self.extrudersChanged.emit(machine_id) + self.extrudersChanged.emit(global_stack_id) + self.setActiveExtruderIndex(0) ## Get all extruder values for a certain setting. # diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0f3a690967..69435b7077 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -161,7 +161,7 @@ class MachineManager(QObject): @pyqtProperty(int, constant=True) def totalNumberOfSettings(self) -> int: - return len(ContainerRegistry.getInstance().findDefinitionContainers(id="fdmprinter")[0].getAllKeys()) + return len(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0].getAllKeys()) def _onHotendIdChanged(self, index: Union[str, int], hotend_id: str) -> None: if not self._global_container_stack: @@ -386,15 +386,6 @@ class MachineManager(QObject): else: Logger.log("w", "Failed creating a new machine!") - ## Create a name that is not empty and unique - # \param container_type \type{string} Type of the container (machine, quality, ...) - # \param current_name \type{} Current name of the container, which may be an acceptable option - # \param new_name \type{string} Base name, which may not be unique - # \param fallback_name \type{string} Name to use when (stripped) new_name is empty - # \return \type{string} Name that is unique for the specified type and name/id - def _createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str: - return ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name) - def _checkStacksHaveErrors(self) -> bool: if self._global_container_stack is None: #No active machine. return False @@ -950,15 +941,12 @@ class MachineManager(QObject): global_container_stack = self._global_container_stack if not global_container_stack: return [] + global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - if extruder_stacks: - stacks = extruder_stacks - else: - stacks = [global_container_stack] - for stack in stacks: + # find qualities for extruders + for stack in extruder_stacks: material = stack.material # TODO: fix this @@ -966,19 +954,33 @@ class MachineManager(QObject): material = self._new_material_container quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material]) + if not quality: # No quality profile is found for this quality type. quality = self._empty_quality_container - result.append({"stack": stack, "quality": quality, "quality_changes": empty_quality_changes}) - if extruder_stacks: - # Add an extra entry for the global stack. - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = "True") + result.append({ + "stack": stack, + "quality": quality, + "quality_changes": empty_quality_changes + }) - if not global_quality: - global_quality = self._empty_quality_container + # also find a global quality for the machine + global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = True) - result.append({"stack": global_container_stack, "quality": global_quality, "quality_changes": empty_quality_changes}) + # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 + if not global_quality and len(extruder_stacks) == 1: + global_quality = result[0]["quality"] + + # if there is still no global quality, set it to empty (not supported) + if not global_quality: + global_quality = self._empty_quality_container + + result.append({ + "stack": global_container_stack, + "quality": global_quality, + "quality_changes": empty_quality_changes + }) return result @@ -1030,7 +1032,7 @@ class MachineManager(QObject): material = extruder_stack.material - if self._new_material_container and self._active_container_stack.getId() == stack.getId(): + if self._new_material_container and self._active_container_stack.getId() == extruder_stack.getId(): material = self._new_material_container quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material]) @@ -1047,6 +1049,12 @@ class MachineManager(QObject): # append the global quality changes global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material], global_quality = True) + + # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 + if not global_quality and len(extruder_stacks) == 1: + global_quality = result[0]["quality_changes"] + + # if still no global quality changes are found we set it to empty (not supported) if not global_quality: global_quality = self._empty_quality_container @@ -1163,10 +1171,11 @@ class MachineManager(QObject): @pyqtSlot(str, str) def renameMachine(self, machine_id: str, new_name: str): - containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) - if containers: - new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName()) - containers[0].setName(new_name) + container_registry = ContainerRegistry.getInstance() + machine_stack = container_registry.findContainerStacks(id = machine_id) + if machine_stack: + new_name = container_registry.createUniqueName("machine", machine_stack[0].getName(), new_name, machine_stack[0].getBottom().getName()) + machine_stack[0].setName(new_name) self.globalContainerChanged.emit() @pyqtSlot(str) From 6ac81635897d338f79270997c38d772a42114a55 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 13:43:01 +0100 Subject: [PATCH 19/54] Cleanup CuraApplication.py - CURA-4482 --- cura/CuraApplication.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 292ad93121..a3bf4bf462 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -786,7 +786,6 @@ class CuraApplication(QtApplication): qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") - qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel) qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") @@ -796,15 +795,12 @@ class CuraApplication(QtApplication): qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel") - qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager) # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work. actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml"))) qmlRegisterSingletonType(actions_url, "Cura", 1, 0, "Actions") - # engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.getInstance()) - for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] if type_name in ("Cura", "Actions"): From dfe0212a413df932ceb5d9eb615155a49c45a208 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 13:48:08 +0100 Subject: [PATCH 20/54] Comment out unneeded materials fetching --- cura/Settings/CuraContainerRegistry.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 4923a343a0..986792c6bb 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -302,10 +302,13 @@ class CuraContainerRegistry(ContainerRegistry): machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() del quality_type_criteria["definition"] - materials = None + + # materials = None + if "material" in quality_type_criteria: - materials = ContainerRegistry.getInstance().findInstanceContainers(id = quality_type_criteria["material"]) + # materials = ContainerRegistry.getInstance().findInstanceContainers(id = quality_type_criteria["material"]) del quality_type_criteria["material"] + # Do not filter quality containers here with materials because we are trying to import a profile, so it should # NOT be restricted by the active materials on the current machine. materials = None From 359514e08b4a243be8d8228b00f28da1bb7f0427 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 13:49:04 +0100 Subject: [PATCH 21/54] Cleanup CuraContainerRegistry.py - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 986792c6bb..d69a97c92f 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -12,13 +12,12 @@ from PyQt5.QtWidgets import QMessageBox from UM.Decorators import override from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerStack import ContainerStack -from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.InstanceContainer import InstanceContainer from UM.Application import Application from UM.Logger import Logger from UM.Message import Message from UM.Platform import Platform -from UM.PluginRegistry import PluginRegistry #For getting the possible profile writers to write with. +from UM.PluginRegistry import PluginRegistry # For getting the possible profile writers to write with. from UM.Util import parseBool from . import ExtruderStack From 569047693e2f5a7ac38d051a59a44c12c2bddb1d Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 13:55:47 +0100 Subject: [PATCH 22/54] Rename loop variable to be more explicit - CURA-4482 --- cura/Settings/MachineManager.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 69435b7077..a858f15cfc 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -946,11 +946,11 @@ class MachineManager(QObject): extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() # find qualities for extruders - for stack in extruder_stacks: - material = stack.material + for extruder_stack in extruder_stacks: + material = extruder_stack.material # TODO: fix this - if self._new_material_container and stack.getId() == self._active_container_stack.getId(): + if self._new_material_container and extruder_stack.getId() == self._active_container_stack.getId(): material = self._new_material_container quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material]) @@ -960,7 +960,7 @@ class MachineManager(QObject): quality = self._empty_quality_container result.append({ - "stack": stack, + "stack": extruder_stack, "quality": quality, "quality_changes": empty_quality_changes }) @@ -1003,7 +1003,6 @@ class MachineManager(QObject): Logger.log("e", "Could not find the global quality changes container with name %s", quality_changes_name) return None - # TODO: remove this - CURA-4482 material = global_container_stack.material # find a quality type that matches both machine and materials @@ -1024,7 +1023,6 @@ class MachineManager(QObject): if quality_changes_list: quality_changes = quality_changes_list[0] - # TODO: remove this - CURA-4482 else: quality_changes = global_quality_changes if not quality_changes: From e7f1900f71cc2e292a734e1629d9498b75ca07bf Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 14:01:15 +0100 Subject: [PATCH 23/54] Remove layer height from custom profiles in dropdown as it might have changed - CURA-4482 --- cura/Settings/MachineManager.py | 3 --- resources/qml/Menus/ProfileMenu.qml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a858f15cfc..b2baf433dd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -728,9 +728,6 @@ class MachineManager(QObject): new_value = self._active_container_stack.getProperty(key, "value") extruder_stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] - # TODO: remove this - CURA-4482 - extruder_stacks.append(self._global_container_stack) - # check in which stack the value has to be replaced for extruder_stack in extruder_stacks: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index fecea5ef99..edce2641af 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -41,7 +41,7 @@ Menu MenuItem { - text: model.name + " - " + model.layer_height + text: model.name checkable: true checked: Cura.MachineManager.activeQualityChangesId == model.id exclusiveGroup: group From f20ba4a118b9102e9486f79a1040865e0d29934c Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 14:37:58 +0100 Subject: [PATCH 24/54] Only create new extruder stack for single extrusion machine if it does not exist yet - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 61 ++++++++++++++------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index d69a97c92f..0c0386ade1 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -406,45 +406,48 @@ class CuraContainerRegistry(ContainerRegistry): def _addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): new_extruder_id = extruder_id + extruder_stack = None # if extruders are defined in the machine definition use those instead if machine.extruders and len(machine.extruders) > 0: new_extruder_id = machine.extruders["0"].getId() + extruder_stack = machine.extruders["0"] - extruder_definitions = self.findDefinitionContainers(id = new_extruder_id) + # if the extruder stack doesn't exist yet we create and add it + if not extruder_stack: + extruder_definitions = self.findDefinitionContainers(id = new_extruder_id) + if not extruder_definitions: + Logger.log("w", "Could not find definition containers for extruder %s", new_extruder_id) + return - if not extruder_definitions: - Logger.log("w", "Could not find definition containers for extruder %s", new_extruder_id) - return + extruder_definition = extruder_definitions[0] + unique_name = self.uniqueName(machine.getName() + " " + new_extruder_id) - extruder_definition = extruder_definitions[0] - unique_name = self.uniqueName(machine.getName() + " " + new_extruder_id) + extruder_stack = ExtruderStack.ExtruderStack(unique_name) + extruder_stack.setName(extruder_definition.getName()) + extruder_stack.setDefinition(extruder_definition) + extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) + extruder_stack.setNextStack(machine) - extruder_stack = ExtruderStack.ExtruderStack(unique_name) - extruder_stack.setName(extruder_definition.getName()) - extruder_stack.setDefinition(extruder_definition) - extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) - extruder_stack.setNextStack(machine) + if machine.userChanges: + # set existing user changes if found + extruder_stack.setUserChanges(machine.userChanges) + else: + # create empty user changes container otherwise + user_container = InstanceContainer(extruder_stack.id + "_user") + user_container.addMetaDataEntry("type", "user") + user_container.addMetaDataEntry("machine", extruder_stack.getId()) + from cura.CuraApplication import CuraApplication + user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + user_container.setDefinition(extruder_definition) + extruder_stack.setUserChanges(user_container) + self.addContainer(user_container) - if machine.userChanges: - # set existing user changes if found - extruder_stack.setUserChanges(machine.userChanges) - else: - # create empty user changes container otherwise - user_container = InstanceContainer(extruder_stack.id + "_user") - user_container.addMetaDataEntry("type", "user") - user_container.addMetaDataEntry("machine", extruder_stack.getId()) - from cura.CuraApplication import CuraApplication - user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_container.setDefinition(extruder_definition) - extruder_stack.setUserChanges(user_container) - self.addContainer(user_container) + extruder_stack.setVariantById("default") + extruder_stack.setMaterialById("default") + extruder_stack.setQualityById("default") - extruder_stack.setVariantById("default") - extruder_stack.setMaterialById("default") - extruder_stack.setQualityById("default") - - self.addContainer(extruder_stack) + self.addContainer(extruder_stack) # Fix the extruders that were upgraded to ExtruderStack instances during addContainer. # The stacks are now responsible for setting the next stack on deserialize. However, From 911f619000d505a8916cf25a5e0c62fc95dc021f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 14:43:48 +0100 Subject: [PATCH 25/54] Fix for getting machine extruders from manager instance - CURA-4482 --- cura/Settings/ExtruderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 40ac2f1c63..295b10e6db 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -630,7 +630,7 @@ class ExtruderManager(QObject): } result = [] - for extruder in ExtruderManager.getMachineExtruders(global_stack.getId()): + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): # only include values from extruders that are "active" for the current machine instance if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value", context = context): continue From cc267646e7475800679423aca5ac909efb432598 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 14:48:52 +0100 Subject: [PATCH 26/54] Always use extruder stacks when building slicer message and deprecate otherwise - CURA-4482 --- plugins/CuraEngineBackend/StartSliceJob.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index a53daa4e63..49dfc71769 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -9,6 +9,7 @@ import time from UM.Job import Job from UM.Application import Application from UM.Logger import Logger +from UM.Decorators import deprecated from UM.Scene.SceneNode import SceneNode from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -158,13 +159,9 @@ class StartSliceJob(Job): self._buildGlobalSettingsMessage(stack) self._buildGlobalInheritsStackMessage(stack) - # Only add extruder stacks if there are multiple extruders - # Single extruder machines only use the global stack to store setting values - if stack.getProperty("machine_extruder_count", "value") > 1: - for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): - self._buildExtruderMessage(extruder_stack) - else: - self._buildExtruderMessageFromGlobalStack(stack) + # Build messages for extruder stacks + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): + self._buildExtruderMessage(extruder_stack) for group in object_groups: group_message = self._slice_message.addRepeatedMessage("object_lists") @@ -251,6 +248,7 @@ class StartSliceJob(Job): Job.yieldThread() ## Create extruder message from global stack + @deprecated("Extruder stack is always used since version 3.1, even with single extrusion machines", "3.1") def _buildExtruderMessageFromGlobalStack(self, stack): message = self._slice_message.addRepeatedMessage("extruders") From c23c031152fd67f5d5e87c9918cc858143327b85 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 14:51:31 +0100 Subject: [PATCH 27/54] Always use extruder stacks in slice info - CURA-4482 --- plugins/SliceInfoPlugin/SliceInfo.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 0514c4dacf..6ba34e04c8 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -87,15 +87,10 @@ class SliceInfo(Extension): data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")} + # add extruder specific data to slice info data["extruders"] = [] - extruder_count = len(global_container_stack.extruders) - extruders = [] - if extruder_count > 1: - extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) - extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position")) - - if not extruders: - extruders = [global_container_stack] + extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) + extruders = sorted(extruders, key=lambda extruder: extruder.getMetaDataEntry("position")) for extruder in extruders: extruder_dict = dict() From 77cd10374c3aa6211c40d791a19c7564d12200b4 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:00:22 +0100 Subject: [PATCH 28/54] Always set the active extruder stack when loading project file settings - CURA-4482 --- plugins/3MFReader/ThreeMFReader.py | 17 +++++------------ plugins/SliceInfoPlugin/SliceInfo.py | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index a34bf771d7..786226ae61 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -107,20 +107,13 @@ class ThreeMFReader(MeshReader): um_node.addDecorator(SettingOverrideDecorator()) global_container_stack = Application.getInstance().getGlobalContainerStack() + # Ensure the correct next container for the SettingOverride decorator is set. if global_container_stack: - multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 + default_stack = ExtruderManager.getInstance().getExtruderStack(0) - # Ensure that all extruder data is reset - if not multi_extrusion: - default_stack_id = global_container_stack.getId() - else: - default_stack = ExtruderManager.getInstance().getExtruderStack(0) - if default_stack: - default_stack_id = default_stack.getId() - else: - default_stack_id = global_container_stack.getId() - um_node.callDecoration("setActiveExtruder", default_stack_id) + if default_stack: + um_node.callDecoration("setActiveExtruder", default_stack.getId()) # Get the definition & set it definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom()) @@ -139,7 +132,7 @@ class ThreeMFReader(MeshReader): else: Logger.log("w", "Unable to find extruder in position %s", setting_value) continue - setting_container.setProperty(key,"value", setting_value) + setting_container.setProperty(key, "value", setting_value) if len(um_node.getChildren()) > 0: group_decorator = GroupDecorator() diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 6ba34e04c8..79963a4740 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -90,7 +90,7 @@ class SliceInfo(Extension): # add extruder specific data to slice info data["extruders"] = [] extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) - extruders = sorted(extruders, key=lambda extruder: extruder.getMetaDataEntry("position")) + extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position")) for extruder in extruders: extruder_dict = dict() From a7383b42d5645ab64a0eac14482454a09b3d2356 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:04:06 +0100 Subject: [PATCH 29/54] Always use extruder stack when adding settings per object - CURA-4482 --- .../PerObjectSettingsTool.py | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py index d0cb53c4f8..dc6efafa13 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py @@ -78,31 +78,26 @@ class PerObjectSettingsTool(Tool): def _onGlobalContainerChanged(self): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: + + # used for enabling or disabling per extruder settings per object self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 - # Ensure that all extruder data is reset - if not self._multi_extrusion: - default_stack_id = global_container_stack.getId() - else: - default_stack = ExtruderManager.getInstance().getExtruderStack(0) - if default_stack: - default_stack_id = default_stack.getId() - else: - default_stack_id = global_container_stack.getId() + extruder_stack = ExtruderManager.getInstance().getExtruderStack(0) - root_node = Application.getInstance().getController().getScene().getRoot() - for node in DepthFirstIterator(root_node): - new_stack_id = default_stack_id - # Get position of old extruder stack for this node - old_extruder_pos = node.callDecoration("getActiveExtruderPosition") - if old_extruder_pos is not None: - # Fetch current (new) extruder stack at position - new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos) - if new_stack: - new_stack_id = new_stack.getId() - node.callDecoration("setActiveExtruder", new_stack_id) + if extruder_stack: + root_node = Application.getInstance().getController().getScene().getRoot() + for node in DepthFirstIterator(root_node): + new_stack_id = extruder_stack.getId() + # Get position of old extruder stack for this node + old_extruder_pos = node.callDecoration("getActiveExtruderPosition") + if old_extruder_pos is not None: + # Fetch current (new) extruder stack at position + new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos) + if new_stack: + new_stack_id = new_stack.getId() + node.callDecoration("setActiveExtruder", new_stack_id) - self._updateEnabled() + self._updateEnabled() def _updateEnabled(self): selected_objects = Selection.getAllSelectedObjects() From 52782b8d13b5886a8df9aeed43338ca2d18e6d34 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:08:59 +0100 Subject: [PATCH 30/54] Always use the extruder stacks to determine model color in solid view - CURA-4482 --- plugins/SolidView/SolidView.py | 46 +++++++++++----------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 8f0c9a4dc1..bc1b08cc5e 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -46,19 +46,10 @@ class SolidView(View): self._disabled_shader.setUniformValue("u_diffuseColor2", Color(*theme.getColor("model_unslicable_alt").getRgb())) self._disabled_shader.setUniformValue("u_width", 50.0) - multi_extrusion = False - global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: - multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1 - - if multi_extrusion: - support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value") - support_angle_stack = ExtruderManager.getInstance().getExtruderStack(support_extruder_nr) - if not support_angle_stack: - support_angle_stack = global_container_stack - else: - support_angle_stack = global_container_stack + support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value") + support_angle_stack = ExtruderManager.getInstance().getExtruderStack(support_extruder_nr) if Preferences.getInstance().getValue("view/show_overhang"): angle = support_angle_stack.getProperty("support_angle", "value") @@ -71,33 +62,26 @@ class SolidView(View): else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) - for node in DepthFirstIterator(scene.getRoot()): if not node.render(renderer): if node.getMeshData() and node.isVisible(): uniforms = {} shade_factor = 1.0 - if not multi_extrusion: - if global_container_stack: - material = global_container_stack.findContainer({ "type": "material" }) - material_color = material.getMetaDataEntry("color_code", default = self._extruders_model.defaultColors[0]) if material else self._extruders_model.defaultColors[0] - else: - material_color = self._extruders_model.defaultColors[0] - else: - # Get color to render this mesh in from ExtrudersModel - extruder_index = 0 - extruder_id = node.callDecoration("getActiveExtruder") - if extruder_id: - extruder_index = max(0, self._extruders_model.find("id", extruder_id)) - try: - material_color = self._extruders_model.getItem(extruder_index)["color"] - except KeyError: - material_color = self._extruders_model.defaultColors[0] + # Get color to render this mesh in from ExtrudersModel + extruder_index = 0 + extruder_id = node.callDecoration("getActiveExtruder") + if extruder_id: + extruder_index = max(0, self._extruders_model.find("id", extruder_id)) + try: + material_color = self._extruders_model.getItem(extruder_index)["color"] + except KeyError: + material_color = self._extruders_model.defaultColors[0] + + if extruder_index != ExtruderManager.getInstance().activeExtruderIndex: + # Shade objects that are printed with the non-active extruder 25% darker + shade_factor = 0.6 - if extruder_index != ExtruderManager.getInstance().activeExtruderIndex: - # Shade objects that are printed with the non-active extruder 25% darker - shade_factor = 0.6 try: # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0]) From f421166b182a407bbbb3f89d3fdd9ba8b4e74c8b Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:11:27 +0100 Subject: [PATCH 31/54] Clarify 3mf saving multi extrusion setting - CURA-4482 --- plugins/3MFWriter/ThreeMFWriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index a764d30fac..6254bef03a 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -87,7 +87,7 @@ class ThreeMFWriter(MeshWriter): if stack is not None: changed_setting_keys = set(stack.getTop().getAllKeys()) - # Ensure that we save the extruder used for this object. + # Ensure that we save the extruder used for this object in a multi-extrusion setup if stack.getProperty("machine_extruder_count", "value") > 1: changed_setting_keys.add("extruder_nr") From b8757b46b350d03b4085b9712b909ec62a774447 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:16:51 +0100 Subject: [PATCH 32/54] Always use extruder stack in machine settings action plugin, keep support for older project files - CURA-4482 --- .../MachineSettingsAction.py | 129 +++++++++--------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index d4d6c430a8..d7fdc216f4 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -116,7 +116,7 @@ class MachineSettingsAction(MachineAction): @pyqtSlot(int) def setMachineExtruderCount(self, extruder_count): - machine_manager = Application.getInstance().getMachineManager() + # machine_manager = Application.getInstance().getMachineManager() extruder_manager = ExtruderManager.getInstance() definition_changes_container = self._global_container_stack.definitionChanges @@ -127,33 +127,34 @@ class MachineSettingsAction(MachineAction): if extruder_count == previous_extruder_count: return - extruder_material_id = None - extruder_variant_id = None - if extruder_count == 1: - # Get the material and variant of the first extruder before setting the number extruders to 1 - if machine_manager.hasMaterials: - extruder_material_id = machine_manager.allActiveMaterialIds[extruder_manager.extruderIds["0"]] - if machine_manager.hasVariants: - extruder_variant_id = machine_manager.allActiveVariantIds[extruder_manager.extruderIds["0"]] + # extruder_material_id = None + # extruder_variant_id = None - # Copy any settable_per_extruder setting value from the extruders to the global stack - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - extruder_stacks.reverse() # make sure the first extruder is done last, so its settings override any higher extruder settings - - global_user_container = self._global_container_stack.getTop() - for extruder_stack in extruder_stacks: - extruder_index = extruder_stack.getMetaDataEntry("position") - extruder_user_container = extruder_stack.getTop() - for setting_instance in extruder_user_container.findInstances(): - setting_key = setting_instance.definition.key - settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") - - if settable_per_extruder: - limit_to_extruder = self._global_container_stack.getProperty(setting_key, "limit_to_extruder") - - if limit_to_extruder == "-1" or limit_to_extruder == extruder_index: - global_user_container.setProperty(setting_key, "value", extruder_user_container.getProperty(setting_key, "value")) - extruder_user_container.removeInstance(setting_key) + # if extruder_count == 1: + # # Get the material and variant of the first extruder before setting the number extruders to 1 + # if machine_manager.hasMaterials: + # extruder_material_id = machine_manager.allActiveMaterialIds[extruder_manager.extruderIds["0"]] + # if machine_manager.hasVariants: + # extruder_variant_id = machine_manager.allActiveVariantIds[extruder_manager.extruderIds["0"]] + # + # # Copy any settable_per_extruder setting value from the extruders to the global stack + # extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() + # extruder_stacks.reverse() # make sure the first extruder is done last, so its settings override any higher extruder settings + # + # global_user_container = self._global_container_stack.getTop() + # for extruder_stack in extruder_stacks: + # extruder_index = extruder_stack.getMetaDataEntry("position") + # extruder_user_container = extruder_stack.getTop() + # for setting_instance in extruder_user_container.findInstances(): + # setting_key = setting_instance.definition.key + # settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") + # + # if settable_per_extruder: + # limit_to_extruder = self._global_container_stack.getProperty(setting_key, "limit_to_extruder") + # + # if limit_to_extruder == "-1" or limit_to_extruder == extruder_index: + # global_user_container.setProperty(setting_key, "value", extruder_user_container.getProperty(setting_key, "value")) + # extruder_user_container.removeInstance(setting_key) # reset all extruder number settings whose value is no longer valid for setting_instance in self._global_container_stack.userChanges.findInstances(): @@ -185,50 +186,52 @@ class MachineSettingsAction(MachineAction): # extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStack() global_user_container = self._global_container_stack.getTop() - if extruder_count > 1: - # Multi extrusion - # Make sure one of the extruder stacks is active - if extruder_manager.activeExtruderIndex == -1: - extruder_manager.setActiveExtruderIndex(0) + # if extruder_count > 1: - # Move settable_per_extruder values out of the global container - if previous_extruder_count == 1: - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - global_user_container = self._global_container_stack.getTop() - for setting_instance in global_user_container.findInstances(): - setting_key = setting_instance.definition.key - settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") - if settable_per_extruder: - limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) - extruder_stack = extruder_stacks[max(0, limit_to_extruder)] - extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) - global_user_container.removeInstance(setting_key) - else: - # Single extrusion + # Make sure one of the extruder stacks is active + extruder_manager.setActiveExtruderIndex(0) - # Make sure the machine stack is active - if extruder_manager.activeExtruderIndex > -1: - extruder_manager.setActiveExtruderIndex(-1) + # Move settable_per_extruder values out of the global container + # After CURA-4482 this should not be the case anymore, but we still want to support older project files. + if previous_extruder_count == 1: + extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() + global_user_container = self._global_container_stack.getTop() - # Restore material and variant on global stack - # MachineManager._onGlobalContainerChanged removes the global material and variant of multiextruder machines - if extruder_material_id or extruder_variant_id: - # Prevent the DiscardOrKeepProfileChangesDialog from popping up (twice) if there are user changes - # The dialog is not relevant here, since we're restoring the previous situation as good as possible - preferences = Preferences.getInstance() - choice_on_profile_override = preferences.getValue("cura/choice_on_profile_override") - preferences.setValue("cura/choice_on_profile_override", "always_keep") + for setting_instance in global_user_container.findInstances(): + setting_key = setting_instance.definition.key + settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") - if extruder_material_id: - machine_manager.setActiveMaterial(extruder_material_id) - if extruder_variant_id: - machine_manager.setActiveVariant(extruder_variant_id) + if settable_per_extruder: + limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) + extruder_stack = extruder_stacks[max(0, limit_to_extruder)] + extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) + global_user_container.removeInstance(setting_key) - preferences.setValue("cura/choice_on_profile_override", choice_on_profile_override) + # else: + # # Single extrusion + # + # # Make sure the machine stack is active + # if extruder_manager.activeExtruderIndex > -1: + # extruder_manager.setActiveExtruderIndex(-1) + # + # # Restore material and variant on global stack + # # MachineManager._onGlobalContainerChanged removes the global material and variant of multiextruder machines + # if extruder_material_id or extruder_variant_id: + # # Prevent the DiscardOrKeepProfileChangesDialog from popping up (twice) if there are user changes + # # The dialog is not relevant here, since we're restoring the previous situation as good as possible + # preferences = Preferences.getInstance() + # choice_on_profile_override = preferences.getValue("cura/choice_on_profile_override") + # preferences.setValue("cura/choice_on_profile_override", "always_keep") + # + # if extruder_material_id: + # machine_manager.setActiveMaterial(extruder_material_id) + # if extruder_variant_id: + # machine_manager.setActiveVariant(extruder_variant_id) + # + # preferences.setValue("cura/choice_on_profile_override", choice_on_profile_override) self.forceUpdate() - @pyqtSlot() def forceUpdate(self): # Force rebuilding the build volume by reloading the global container stack. From cc6be48a7973b6a2ae35ab05d2feb75f1edc07cb Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:19:16 +0100 Subject: [PATCH 33/54] Always use extruder stack when updating material diameter - CURA-4482 --- .../MachineSettingsAction.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index d7fdc216f4..868e87ca7c 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -284,16 +284,13 @@ class MachineSettingsAction(MachineAction): if not self._global_container_stack.getMetaDataEntry("has_materials", False): return - machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value") - if machine_extruder_count > 1: - material = ExtruderManager.getInstance().getActiveExtruderStack().material - else: - material = self._global_container_stack.material + material = ExtruderManager.getInstance().getActiveExtruderStack().material material_diameter = material.getProperty("material_diameter", "value") - if not material_diameter: # in case of "empty" material + if not material_diameter: + # in case of "empty" material material_diameter = 0 - material_approximate_diameter = str(round(material_diameter)) + material_approximate_diameter = str(round(material_diameter)) definition_changes = self._global_container_stack.definitionChanges machine_diameter = definition_changes.getProperty("material_diameter", "value") if not machine_diameter: @@ -303,10 +300,7 @@ class MachineSettingsAction(MachineAction): if material_approximate_diameter != machine_approximate_diameter: Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.") - if machine_extruder_count > 1: - stacks = ExtruderManager.getInstance().getExtruderStacks() - else: - stacks = [self._global_container_stack] + stacks = ExtruderManager.getInstance().getExtruderStacks() if self._global_container_stack.getMetaDataEntry("has_machine_materials", False): materials_definition = self._global_container_stack.definition.getId() @@ -347,7 +341,7 @@ class MachineSettingsAction(MachineAction): search_criteria["id"] = stack.getMetaDataEntry("preferred_material") materials = self._container_registry.findInstanceContainers(**search_criteria) if not materials: - # Preferrd material with new diameter is not found, search for any material + # Preferred material with new diameter is not found, search for any material search_criteria.pop("id", None) materials = self._container_registry.findInstanceContainers(**search_criteria) if not materials: From c59e4bb3e161179ab991beb3ac6c5941ecacfd96 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:20:25 +0100 Subject: [PATCH 34/54] Cleanup machine settings action - CURA-4482 --- .../MachineSettingsAction.py | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 868e87ca7c..44d0e05485 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -127,35 +127,6 @@ class MachineSettingsAction(MachineAction): if extruder_count == previous_extruder_count: return - # extruder_material_id = None - # extruder_variant_id = None - - # if extruder_count == 1: - # # Get the material and variant of the first extruder before setting the number extruders to 1 - # if machine_manager.hasMaterials: - # extruder_material_id = machine_manager.allActiveMaterialIds[extruder_manager.extruderIds["0"]] - # if machine_manager.hasVariants: - # extruder_variant_id = machine_manager.allActiveVariantIds[extruder_manager.extruderIds["0"]] - # - # # Copy any settable_per_extruder setting value from the extruders to the global stack - # extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - # extruder_stacks.reverse() # make sure the first extruder is done last, so its settings override any higher extruder settings - # - # global_user_container = self._global_container_stack.getTop() - # for extruder_stack in extruder_stacks: - # extruder_index = extruder_stack.getMetaDataEntry("position") - # extruder_user_container = extruder_stack.getTop() - # for setting_instance in extruder_user_container.findInstances(): - # setting_key = setting_instance.definition.key - # settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder") - # - # if settable_per_extruder: - # limit_to_extruder = self._global_container_stack.getProperty(setting_key, "limit_to_extruder") - # - # if limit_to_extruder == "-1" or limit_to_extruder == extruder_index: - # global_user_container.setProperty(setting_key, "value", extruder_user_container.getProperty(setting_key, "value")) - # extruder_user_container.removeInstance(setting_key) - # reset all extruder number settings whose value is no longer valid for setting_instance in self._global_container_stack.userChanges.findInstances(): setting_key = setting_instance.definition.key @@ -183,11 +154,8 @@ class MachineSettingsAction(MachineAction): extruder_manager.setActiveExtruderIndex(0) # Move settable_per_extruder values out of the global container - # extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStack() global_user_container = self._global_container_stack.getTop() - # if extruder_count > 1: - # Make sure one of the extruder stacks is active extruder_manager.setActiveExtruderIndex(0) @@ -207,29 +175,6 @@ class MachineSettingsAction(MachineAction): extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) global_user_container.removeInstance(setting_key) - # else: - # # Single extrusion - # - # # Make sure the machine stack is active - # if extruder_manager.activeExtruderIndex > -1: - # extruder_manager.setActiveExtruderIndex(-1) - # - # # Restore material and variant on global stack - # # MachineManager._onGlobalContainerChanged removes the global material and variant of multiextruder machines - # if extruder_material_id or extruder_variant_id: - # # Prevent the DiscardOrKeepProfileChangesDialog from popping up (twice) if there are user changes - # # The dialog is not relevant here, since we're restoring the previous situation as good as possible - # preferences = Preferences.getInstance() - # choice_on_profile_override = preferences.getValue("cura/choice_on_profile_override") - # preferences.setValue("cura/choice_on_profile_override", "always_keep") - # - # if extruder_material_id: - # machine_manager.setActiveMaterial(extruder_material_id) - # if extruder_variant_id: - # machine_manager.setActiveVariant(extruder_variant_id) - # - # preferences.setValue("cura/choice_on_profile_override", choice_on_profile_override) - self.forceUpdate() @pyqtSlot() From 8676792ef8a7eee79dbc630f09d7ee948988dff1 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:23:45 +0100 Subject: [PATCH 35/54] Disable annoying debug message about not found printer definition --- plugins/MachineSettingsAction/MachineSettingsAction.py | 9 ++------- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 44d0e05485..dacbe2efc5 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -149,18 +149,13 @@ class MachineSettingsAction(MachineAction): definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count) - # Make sure one of the extruder stacks is active - if extruder_manager.activeExtruderIndex == -1: - extruder_manager.setActiveExtruderIndex(0) - - # Move settable_per_extruder values out of the global container - global_user_container = self._global_container_stack.getTop() - # Make sure one of the extruder stacks is active extruder_manager.setActiveExtruderIndex(0) # Move settable_per_extruder values out of the global container # After CURA-4482 this should not be the case anymore, but we still want to support older project files. + global_user_container = self._global_container_stack.getTop() + if previous_extruder_count == 1: extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() global_user_container = self._global_container_stack.getTop() diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 51a3c51a8b..7af011ee2e 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -547,7 +547,7 @@ class XmlMaterialProfile(InstanceContainer): definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = machine_id) if not definitions: - Logger.log("w", "No definition found for machine ID %s", machine_id) + # Logger.log("w", "No definition found for machine ID %s", machine_id) continue definition = definitions[0] From ce896177cb066f95ecf140e9c81c8603f74b7819 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 16:32:04 +0100 Subject: [PATCH 36/54] Cleanup 3mf workspace reader - CURA-4482 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 28d12bf2d5..170b616677 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -644,9 +644,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Get the stack(s) saved in the workspace. Logger.log("d", "Workspace loading is checking stacks containers...") - # -- # load global stack file try: + stack = None + if self._resolve_strategies["machine"] == "override": container_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original) stack = container_stacks[0] @@ -682,12 +683,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._container_registry.addContainer(stack) containers_added.append(stack) else: - Logger.log("e", "Resolve strategy of %s for machine is not supported", - self._resolve_strategies["machine"]) + Logger.log("e", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"]) # Create a new definition_changes container if it was empty if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer(): - stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack._id + "_settings")) + stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings")) global_stack = stack Job.yieldThread() except: @@ -697,16 +697,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._container_registry.removeContainer(container.getId()) return - # - # Use the number of extruders from the global stack instead of the number of extruder stacks this project file - # contains. The Custom FDM Printer can have multiple extruders, but the actual number of extruders in used is - # defined in the global stack. - # Because for single-extrusion machines, there won't be an extruder stack, so relying on the the extruder count - # in the global stack can avoid problems in those cases. - # - extruder_count_from_global_stack = global_stack.getProperty("machine_extruder_count", "value") - - # -- # load extruder stack files try: for extruder_stack_file in extruder_stack_files: From 2e1da5857083e8b0b9576c93a15e726e0e57b2f6 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 17:06:34 +0100 Subject: [PATCH 37/54] Cleanup - CURA-4482 --- cura/Settings/MachineManager.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b2baf433dd..62095945af 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -274,14 +274,6 @@ class MachineManager(QObject): except TypeError: pass - # TODO: remove this - CURA-4482 - material = self._global_container_stack.material - material.nameChanged.disconnect(self._onMaterialNameChanged) - - # TODO: remove this - CURA-4482 - quality = self._global_container_stack.quality - quality.nameChanged.disconnect(self._onQualityNameChanged) - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.propertyChanged.disconnect(self._onPropertyChanged) extruder_stack.containersChanged.disconnect(self._onInstanceContainersChanged) @@ -309,17 +301,6 @@ class MachineManager(QObject): if global_material != self._empty_material_container: self._global_container_stack.setMaterial(self._empty_material_container) - # TODO: update stack builder since this is not always a user created stack - # if len(self._global_container_stack.extruders) == 0: - # extruder_stack = CuraStackBuilder.createExtruderStack( - # self._global_container_stack.getId(), - # definition = self._global_container_stack.definition, - # machine_definition = self._global_container_stack.definition, - # ) - # extruder_stack.setNextStack(self._global_container_stack) - # extruder_stack.propertyChanged.connect(self._onPropertyChanged) - # extruder_stack.containersChanged.connect(self._onInstanceContainersChanged) - # Listen for changes on all extruder stacks for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.propertyChanged.connect(self._onPropertyChanged) From 8f41185f228eaf153bcc37bb6bf1eb1018a7d0e5 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 17:18:19 +0100 Subject: [PATCH 38/54] Fix extruder manager single instance from qml - CURA-4482 --- cura/Settings/ExtruderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 295b10e6db..e5eb00c4b4 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -106,7 +106,7 @@ class ExtruderManager(QObject): @staticmethod def createExtruderManager(): - return ExtruderManager() + return ExtruderManager().getInstance() ## Gets an instance of the extruder manager, or creates one if no instance # exists yet. From 957009a768d8fa8808dbf14ec06e8abfca04e120 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 31 Oct 2017 17:32:21 +0100 Subject: [PATCH 39/54] Fix finding global quality for multi extrusion machines - CURA-4482 --- 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 62095945af..b345649052 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -944,7 +944,7 @@ class MachineManager(QObject): }) # also find a global quality for the machine - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = True) + global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = "True") # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 if not global_quality and len(extruder_stacks) == 1: From 97421ecf5812cc055f7fbfff45f6bd271de7a462 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 1 Nov 2017 13:31:25 +0100 Subject: [PATCH 40/54] Create container stacks when loading older project file - CURA-4482 --- cura/Settings/CuraContainerRegistry.py | 4 ++-- plugins/3MFReader/ThreeMFWorkspaceReader.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 0c0386ade1..526685465e 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -402,9 +402,9 @@ class CuraContainerRegistry(ContainerRegistry): def _registerSingleExtrusionMachinesExtruderStacks(self): machines = ContainerRegistry.getInstance().findContainerStacks(machine_extruder_trains = {"0": "fdmextruder"}) for machine in machines: - self._addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder") + self.addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder") - def _addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): + def addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): new_extruder_id = extruder_id extruder_stack = None diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 170b616677..a3aadc79b8 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -739,9 +739,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Create a new definition_changes container if it was empty if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer(): - stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack._id + "_settings")) - if global_stack.getProperty("machine_extruder_count", "value") > 1: - extruder_stacks.append(stack) + stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings")) + + extruder_stacks.append(stack) + + # If not extruder stacks were saved in the project file (pre 3.1) create one manually + # We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this + if not extruder_stacks: + self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder") + except: Logger.logException("w", "We failed to serialize the stack. Trying to clean up.") # Something went really wrong. Try to remove any data that we added. @@ -774,7 +780,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): for stack in [global_stack] + extruder_stacks: stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container) - # # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those # MUST get updated too. From e23e6cfa31e55e2de1e9bd8af31af7beb316ac3f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 1 Nov 2017 13:59:21 +0100 Subject: [PATCH 41/54] Fix for global quality in case of user created quality profile - CURA-4482 --- cura/Settings/MachineManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b345649052..7bbbd868f4 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1024,11 +1024,11 @@ class MachineManager(QObject): }) # append the global quality changes - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material], global_quality = True) + global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material], global_quality = "True") # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 if not global_quality and len(extruder_stacks) == 1: - global_quality = result[0]["quality_changes"] + global_quality = result[0]["quality"] # if still no global quality changes are found we set it to empty (not supported) if not global_quality: From e29fdbe76d77a47a57537b79736d7ee24714d87d Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 1 Nov 2017 14:32:58 +0100 Subject: [PATCH 42/54] Cleanup - CURA-4482 --- cura/Settings/ExtruderManager.py | 174 +----------------- .../MachineSettingsAction.py | 3 +- 2 files changed, 3 insertions(+), 174 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index e5eb00c4b4..34b283107d 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -75,17 +75,12 @@ class ExtruderManager(QObject): return 0 ## Gets a dict with the extruder stack ids with the extruder number as the key. - # The key "-1" indicates the global stack id. - # @pyqtProperty("QVariantMap", notify = extrudersChanged) def extruderIds(self): extruder_stack_ids = {} global_stack_id = Application.getInstance().getGlobalContainerStack().getId() - # TODO: remove this? - CURA-4482 - # extruder_stack_ids["-1"] = global_stack_id - if global_stack_id in self._extruder_trains: for position in self._extruder_trains[global_stack_id]: extruder_stack_ids[position] = self._extruder_trains[global_stack_id][position].getId() @@ -212,40 +207,6 @@ class ExtruderManager(QObject): result.append(self.getExtruderStack(i)) return result - # ## Adds all extruders of a specific machine definition to the extruder - # # manager. - # # - # # \param machine_definition The machine definition to add the extruders for. - # # \param machine_id The machine_id to add the extruders for. - # @deprecated("Use CuraStackBuilder", "2.6") - # def addMachineExtruders(self, machine_definition: DefinitionContainerInterface, machine_id: str) -> None: - # changed = False - # machine_definition_id = machine_definition.getId() - # if machine_id not in self._extruder_trains: - # self._extruder_trains[machine_id] = { } - # changed = True - # container_registry = ContainerRegistry.getInstance() - # if container_registry: - # # Add the extruder trains that don't exist yet. - # for extruder_definition in container_registry.findDefinitionContainers(machine = machine_definition_id): - # position = extruder_definition.getMetaDataEntry("position", None) - # if not position: - # Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) - # if not container_registry.findContainerStacks(machine = machine_id, position = position): # Doesn't exist yet. - # self.createExtruderTrain(extruder_definition, machine_definition, position, machine_id) - # changed = True - # - # # Gets the extruder trains that we just created as well as any that still existed. - # extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_id) - # for extruder_train in extruder_trains: - # self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train - # - # # regardless of what the next stack is, we have to set it again, because of signal routing. - # extruder_train.setNextStack(Application.getInstance().getGlobalContainerStack()) - # changed = True - # if changed: - # self.extrudersChanged.emit(machine_id) - def registerExtruder(self, extruder_train, machine_id): changed = False @@ -265,138 +226,6 @@ class ExtruderManager(QObject): if changed: self.extrudersChanged.emit(machine_id) - # ## Creates a container stack for an extruder train. - # # - # # The container stack has an extruder definition at the bottom, which is - # # linked to a machine definition. Then it has a variant profile, a material - # # profile, a quality profile and a user profile, in that order. - # # - # # The resulting container stack is added to the registry. - # # - # # \param extruder_definition The extruder to create the extruder train for. - # # \param machine_definition The machine that the extruder train belongs to. - # # \param position The position of this extruder train in the extruder slots of the machine. - # # \param machine_id The id of the "global" stack this extruder is linked to. - # @deprecated("Use CuraStackBuilder::createExtruderStack", "2.6") - # def createExtruderTrain(self, extruder_definition: DefinitionContainerInterface, machine_definition: DefinitionContainerInterface, - # position, machine_id: str) -> None: - # # Cache some things. - # container_registry = ContainerRegistry.getInstance() - # machine_definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_definition) - # - # # Create a container stack for this extruder. - # extruder_stack_id = container_registry.uniqueName(extruder_definition.getId()) - # container_stack = ContainerStack(extruder_stack_id) - # container_stack.setName(extruder_definition.getName()) # Take over the display name to display the stack with. - # container_stack.addMetaDataEntry("type", "extruder_train") - # container_stack.addMetaDataEntry("machine", machine_id) - # container_stack.addMetaDataEntry("position", position) - # container_stack.addContainer(extruder_definition) - # - # # Find the variant to use for this extruder. - # variant = container_registry.findInstanceContainers(id = "empty_variant")[0] - # if machine_definition.getMetaDataEntry("has_variants"): - # # First add any variant. Later, overwrite with preference if the preference is valid. - # variants = container_registry.findInstanceContainers(definition = machine_definition_id, type = "variant") - # if len(variants) >= 1: - # variant = variants[0] - # preferred_variant_id = machine_definition.getMetaDataEntry("preferred_variant") - # if preferred_variant_id: - # preferred_variants = container_registry.findInstanceContainers(id = preferred_variant_id, definition = machine_definition_id, type = "variant") - # if len(preferred_variants) >= 1: - # variant = preferred_variants[0] - # else: - # Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) - # # And leave it at the default variant. - # container_stack.addContainer(variant) - # - # # Find a material to use for this variant. - # material = container_registry.findInstanceContainers(id = "empty_material")[0] - # if machine_definition.getMetaDataEntry("has_materials"): - # # First add any material. Later, overwrite with preference if the preference is valid. - # machine_has_variant_materials = machine_definition.getMetaDataEntry("has_variant_materials", default = False) - # if machine_has_variant_materials or machine_has_variant_materials == "True": - # materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id, variant = variant.getId()) - # else: - # materials = container_registry.findInstanceContainers(type = "material", definition = machine_definition_id) - # if len(materials) >= 1: - # material = materials[0] - # preferred_material_id = machine_definition.getMetaDataEntry("preferred_material") - # if preferred_material_id: - # global_stack = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) - # if global_stack: - # approximate_material_diameter = str(round(global_stack[0].getProperty("material_diameter", "value"))) - # else: - # approximate_material_diameter = str(round(machine_definition.getProperty("material_diameter", "value"))) - # - # search_criteria = { "type": "material", "id": preferred_material_id, "approximate_diameter": approximate_material_diameter} - # if machine_definition.getMetaDataEntry("has_machine_materials"): - # search_criteria["definition"] = machine_definition_id - # - # if machine_definition.getMetaDataEntry("has_variants") and variant: - # search_criteria["variant"] = variant.id - # else: - # search_criteria["definition"] = "fdmprinter" - # - # preferred_materials = container_registry.findInstanceContainers(**search_criteria) - # if len(preferred_materials) >= 1: - # # In some cases we get multiple materials. In that case, prefer materials that are marked as read only. - # read_only_preferred_materials = [preferred_material for preferred_material in preferred_materials if preferred_material.isReadOnly()] - # if len(read_only_preferred_materials) >= 1: - # material = read_only_preferred_materials[0] - # else: - # material = preferred_materials[0] - # else: - # Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) - # # And leave it at the default material. - # container_stack.addContainer(material) - # - # # Find a quality to use for this extruder. - # quality = container_registry.getEmptyInstanceContainer() - # - # search_criteria = { "type": "quality" } - # if machine_definition.getMetaDataEntry("has_machine_quality"): - # search_criteria["definition"] = machine_definition_id - # if machine_definition.getMetaDataEntry("has_materials") and material: - # search_criteria["material"] = material.id - # else: - # search_criteria["definition"] = "fdmprinter" - # - # preferred_quality = machine_definition.getMetaDataEntry("preferred_quality") - # if preferred_quality: - # search_criteria["id"] = preferred_quality - # - # containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - # if not containers and preferred_quality: - # Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality, machine_id) - # search_criteria.pop("id", None) - # containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - # if containers: - # quality = containers[0] - # - # container_stack.addContainer(quality) - # - # empty_quality_changes = container_registry.findInstanceContainers(id = "empty_quality_changes")[0] - # container_stack.addContainer(empty_quality_changes) - # - # user_profile = container_registry.findInstanceContainers(type = "user", extruder = extruder_stack_id) - # if user_profile: # There was already a user profile, loaded from settings. - # user_profile = user_profile[0] - # else: - # user_profile = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. - # user_profile.addMetaDataEntry("type", "user") - # user_profile.addMetaDataEntry("extruder", extruder_stack_id) - # from cura.CuraApplication import CuraApplication - # user_profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - # user_profile.setDefinition(machine_definition) - # container_registry.addContainer(user_profile) - # container_stack.addContainer(user_profile) - # - # # regardless of what the next stack is, we have to set it again, because of signal routing. - # container_stack.setNextStack(Application.getInstance().getGlobalContainerStack()) - # - # container_registry.addContainer(container_stack) - def getAllExtruderValues(self, setting_key): return self.getAllExtruderSettings(setting_key, "value") @@ -678,7 +507,8 @@ class ExtruderManager(QObject): value = extruder.getRawProperty(key, "value") if isinstance(value, SettingFunction): value = value(extruder) - else: #Just a value from global. + else: + # Just a value from global. value = Application.getInstance().getGlobalContainerStack().getProperty(key, "value") return value diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index dacbe2efc5..2de5b6e9b8 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -116,8 +116,7 @@ class MachineSettingsAction(MachineAction): @pyqtSlot(int) def setMachineExtruderCount(self, extruder_count): - # machine_manager = Application.getInstance().getMachineManager() - extruder_manager = ExtruderManager.getInstance() + extruder_manager = Application.getInstance().getExtruderManager() definition_changes_container = self._global_container_stack.definitionChanges if not self._global_container_stack or definition_changes_container == self._empty_container: From 28ce2b1dc6d3382a5d146fa2aa928af18541ce68 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 6 Nov 2017 09:49:13 +0100 Subject: [PATCH 43/54] Ignore VariSlice plugin --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 570c932d28..ac1e8eba92 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ plugins/ProfileFlattener plugins/cura-god-mode-plugin plugins/cura-big-flame-graph plugins/cura-siemensnx-plugin +plugins/CuraVariSlicePlugin #Build stuff CMakeCache.txt From 913bcf45b184fe01392e41803a260d37b333a30c Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 14 Nov 2017 11:53:24 +0100 Subject: [PATCH 44/54] Add stderr to send errors to --- .../RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py b/plugins/RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py index d87499273b..5ad2caed0b 100644 --- a/plugins/RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py +++ b/plugins/RemovableDriveOutputDevice/OSXRemovableDrivePlugin.py @@ -4,8 +4,6 @@ from . import RemovableDrivePlugin -from UM.Logger import Logger - import subprocess import os @@ -15,12 +13,12 @@ import plistlib class OSXRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin): def checkRemovableDrives(self): drives = {} - p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout = subprocess.PIPE) + p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout = subprocess.PIPE, stderr = subprocess.PIPE) plist = plistlib.loads(p.communicate()[0]) result = self._recursiveSearch(plist, "removable_media") - p = subprocess.Popen(["system_profiler", "SPCardReaderDataType", "-xml"], stdout=subprocess.PIPE) + p = subprocess.Popen(["system_profiler", "SPCardReaderDataType", "-xml"], stdout=subprocess.PIPE, stderr = subprocess.PIPE) plist = plistlib.loads(p.communicate()[0]) result.extend(self._recursiveSearch(plist, "removable_media")) From 8dd91519a67983b913c4d18d7ccb4dcbf3cdef82 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Wed, 15 Nov 2017 00:52:37 +0100 Subject: [PATCH 45/54] Move Support Chunk Size out of children of skip_some_zags The rule is that leaf settings are the ones that are used by the engine. The support_skip_some_zags setting is used by the engine. --- resources/definitions/fdmprinter.def.json | 54 ++++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ae7050a546..b17769eba2 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5075,7 +5075,8 @@ "default_value": false, "settable_per_mesh": true }, - "support_skip_some_zags": { + "support_skip_some_zags": + { "label": "Break Up Support In Chunks", "description": "Skip some support line connections to make the support structure easier to break away. This setting is applicable to the Zig Zag support infill pattern.", "type": "bool", @@ -5083,35 +5084,36 @@ "enabled": "support_enable and (support_pattern == 'zigzag')", "limit_to_extruder": "support_infill_extruder_nr", "settable_per_mesh": false, + "settable_per_extruder": true + }, + "support_skip_zag_per_mm": + { + "label": "Support Chunk Size", + "description": "Leave out a connection between support lines once every N millimeter to make the support structure easier to break away.", + "type": "float", + "unit": "mm", + "default_value": 20, + "minimum_value": "0", + "minimum_value_warning": "support_line_distance", + "enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", + "limit_to_extruder": "support_infill_extruder_nr", + "settable_per_mesh": false, "settable_per_extruder": true, - "children": { - "support_skip_zag_per_mm": { - "label": "Support Chunk Size", - "description": "Leave out a connection between support lines once every N millimeter to make the support structure easier to break away.", - "type": "float", - "unit": "mm", - "default_value": 20, - "minimum_value": "0", - "minimum_value_warning": "support_line_distance", + "children": + { + "support_zag_skip_count": + { + "label": "Support Chunk Line Count", + "description": "Skip one in every N connection lines to make the support structure easier to break away.", + "type": "int", + "default_value": 5, + "value": "round(support_skip_zag_per_mm / support_line_distance)", + "minimum_value": "1", + "minimum_value_warning": "3", "enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", "limit_to_extruder": "support_infill_extruder_nr", "settable_per_mesh": false, - "settable_per_extruder": true, - "children": { - "support_zag_skip_count": { - "label": "Support Chunk Line Count", - "description": "Skip one in every N connection lines to make the support structure easier to break away.", - "type": "int", - "default_value": 5, - "value": "round(support_skip_zag_per_mm / support_line_distance)", - "minimum_value": "1", - "minimum_value_warning": "3", - "enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", - "limit_to_extruder": "support_infill_extruder_nr", - "settable_per_mesh": false, - "settable_per_extruder": true - } - } + "settable_per_extruder": true } } }, From b2da4894b1f4eca8b39a288b6fc73ab830e69950 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Wed, 15 Nov 2017 01:21:08 +0100 Subject: [PATCH 46/54] CuraApplication: Rename file --> file_name 'file' is a built-in function! --- cura/CuraApplication.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 41358b83f5..96ca15741e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -719,8 +719,8 @@ class CuraApplication(QtApplication): if run_headless or self._engine.rootObjects: self.closeSplash() - for file in self.getCommandLineOption("file", []): - self._openFile(file) + for file_name in self.getCommandLineOption("file", []): + 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._openFile(file_name) From 7aeaf661ae4a604a583de911dabd5876748686e8 Mon Sep 17 00:00:00 2001 From: Andreea Scorojitu Date: Wed, 15 Nov 2017 13:40:46 +0100 Subject: [PATCH 47/54] Change_Color_UI_elements_CURA-4548 --- resources/themes/cura-light/theme.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index ceb5b64263..f084e87da2 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -83,8 +83,8 @@ "error": [255, 140, 0, 255], "sidebar_header_bar": [31, 36, 39, 255], - "sidebar_header_active": [31, 36, 39, 255], - "sidebar_header_hover": [31, 36, 39, 255], + "sidebar_header_active": [68, 72, 75, 255], + "sidebar_header_hover": [68, 72, 75, 255], "sidebar_header_highlight": [68, 192, 255, 255], "sidebar_header_highlight_hover": [68, 192, 255, 255], "sidebar_header_text_inactive": [255, 255, 255, 255], From 15a50511b728a61d9aca9247f88133cc4835d91a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Nov 2017 16:03:28 +0100 Subject: [PATCH 48/54] Don't crash if support density is 0 Found while working on CURA-4523. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b17769eba2..6628086179 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3495,7 +3495,7 @@ "minimum_value_warning": "support_line_width", "default_value": 2.66, "enabled": "support_enable", - "value": "(support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))", + "value": "0 if support_infill_rate == 0 else (support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))", "limit_to_extruder": "support_infill_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": true @@ -5107,7 +5107,7 @@ "description": "Skip one in every N connection lines to make the support structure easier to break away.", "type": "int", "default_value": 5, - "value": "round(support_skip_zag_per_mm / support_line_distance)", + "value": "0 if support_line_distance == 0 else round(support_skip_zag_per_mm / support_line_distance)", "minimum_value": "1", "minimum_value_warning": "3", "enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", From f27494d60acda7af5854a44817008bbda5e81c95 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Nov 2017 10:59:14 +0100 Subject: [PATCH 49/54] Move ironing into shell category It is no longer considered experimental. --- resources/definitions/fdmprinter.def.json | 236 +++++++++++----------- 1 file changed, 118 insertions(+), 118 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6628086179..bf65baf1d9 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1340,6 +1340,124 @@ "type": "int", "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true + }, + "ironing_enabled": + { + "label": "Enable Ironing", + "description": "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface.", + "type": "bool", + "default_value": false, + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "ironing_only_highest_layer": + { + "label": "Iron Only Highest Layer", + "description": "Only perform ironing on the very last layer of the mesh. This saves time if the lower layers don't need a smooth surface finish.", + "type": "bool", + "default_value": false, + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "ironing_pattern": + { + "label": "Ironing Pattern", + "description": "The pattern to use for ironing top surfaces.", + "type": "enum", + "options": + { + "concentric": "Concentric", + "zigzag": "Zig Zag" + }, + "default_value": "zigzag", + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "ironing_line_spacing": + { + "label": "Ironing Line Spacing", + "description": "The distance between the lines of ironing.", + "type": "float", + "unit": "mm", + "default_value": 0.1, + "minimum_value": "0.001", + "maximum_value_warning": "machine_nozzle_tip_outer_diameter", + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "ironing_flow": + { + "label": "Ironing Flow", + "description": "The amount of material, relative to a normal skin line, to extrude during ironing. Keeping the nozzle filled helps filling some of the crevices of the top surface, but too much results in overextrusion and blips on the side of the surface.", + "type": "float", + "unit": "%", + "default_value": 10.0, + "minimum_value": "0", + "maximum_value_warning": "50", + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "ironing_inset": + { + "label": "Ironing Inset", + "description": "A distance to keep from the edges of the model. Ironing all the way to the edge of the mesh may result in a jagged edge on your print.", + "type": "float", + "unit": "mm", + "default_value": 0.35, + "value": "wall_line_width_0 / 2", + "minimum_value_warning": "0", + "maximum_value_warning": "wall_line_width_0", + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "speed_ironing": + { + "label": "Ironing Speed", + "description": "The speed at which to pass over the top surface.", + "type": "float", + "unit": "mm/s", + "default_value": 20.0, + "value": "speed_topbottom * 20 / 30", + "minimum_value": "0.001", + "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", + "maximum_value_warning": "100", + "enabled": "ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "acceleration_ironing": + { + "label": "Ironing Acceleration", + "description": "The acceleration with which ironing is performed.", + "unit": "mm/s²", + "type": "float", + "minimum_value": "0.1", + "minimum_value_warning": "100", + "maximum_value_warning": "10000", + "default_value": 3000, + "value": "acceleration_topbottom", + "enabled": "resolveOrValue('acceleration_enabled') and ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "jerk_ironing": + { + "label": "Ironing Jerk", + "description": "The maximum instantaneous velocity change while performing ironing.", + "unit": "mm/s", + "type": "float", + "minimum_value": "0", + "maximum_value_warning": "50", + "default_value": 20, + "value": "jerk_topbottom", + "enabled": "resolveOrValue('jerk_enabled') and ironing_enabled", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true } } }, @@ -5813,124 +5931,6 @@ "settable_per_mesh": false, "settable_per_extruder": false, "settable_per_meshgroup": false - }, - "ironing_enabled": - { - "label": "Enable Ironing", - "description": "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface.", - "type": "bool", - "default_value": false, - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "ironing_only_highest_layer": - { - "label": "Iron Only Highest Layer", - "description": "Only perform ironing on the very last layer of the mesh. This saves time if the lower layers don't need a smooth surface finish.", - "type": "bool", - "default_value": false, - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "ironing_pattern": - { - "label": "Ironing Pattern", - "description": "The pattern to use for ironing top surfaces.", - "type": "enum", - "options": - { - "concentric": "Concentric", - "zigzag": "Zig Zag" - }, - "default_value": "zigzag", - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "ironing_line_spacing": - { - "label": "Ironing Line Spacing", - "description": "The distance between the lines of ironing.", - "type": "float", - "unit": "mm", - "default_value": 0.1, - "minimum_value": "0.001", - "maximum_value_warning": "machine_nozzle_tip_outer_diameter", - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "ironing_flow": - { - "label": "Ironing Flow", - "description": "The amount of material, relative to a normal skin line, to extrude during ironing. Keeping the nozzle filled helps filling some of the crevices of the top surface, but too much results in overextrusion and blips on the side of the surface.", - "type": "float", - "unit": "%", - "default_value": 10.0, - "minimum_value": "0", - "maximum_value_warning": "50", - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "ironing_inset": - { - "label": "Ironing Inset", - "description": "A distance to keep from the edges of the model. Ironing all the way to the edge of the mesh may result in a jagged edge on your print.", - "type": "float", - "unit": "mm", - "default_value": 0.35, - "value": "wall_line_width_0 / 2", - "minimum_value_warning": "0", - "maximum_value_warning": "wall_line_width_0", - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "speed_ironing": - { - "label": "Ironing Speed", - "description": "The speed at which to pass over the top surface.", - "type": "float", - "unit": "mm/s", - "default_value": 20.0, - "value": "speed_topbottom * 20 / 30", - "minimum_value": "0.001", - "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", - "maximum_value_warning": "100", - "enabled": "ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "acceleration_ironing": - { - "label": "Ironing Acceleration", - "description": "The acceleration with which ironing is performed.", - "unit": "mm/s²", - "type": "float", - "minimum_value": "0.1", - "minimum_value_warning": "100", - "maximum_value_warning": "10000", - "default_value": 3000, - "value": "acceleration_topbottom", - "enabled": "resolveOrValue('acceleration_enabled') and ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "jerk_ironing": - { - "label": "Ironing Jerk", - "description": "The maximum instantaneous velocity change while performing ironing.", - "unit": "mm/s", - "type": "float", - "minimum_value": "0", - "maximum_value_warning": "50", - "default_value": 20, - "value": "jerk_topbottom", - "enabled": "resolveOrValue('jerk_enabled') and ironing_enabled", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true } } }, From cd37f91a0a29ed097832d88db9346c520e926f80 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 10:40:13 +0100 Subject: [PATCH 50/54] Remove unnecessary code in BuildVolume CURA-4482 --- cura/BuildVolume.py | 66 +++++++++++---------------------------------- 1 file changed, 15 insertions(+), 51 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 7362a5aff2..50f63e49d5 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -876,15 +876,6 @@ class BuildVolume(SceneNode): return result - ## Private convenience function to get a setting from the adhesion - # extruder. - # - # \param setting_key The key of the setting to get. - # \param property The property to get from the setting. - # \return The property of the specified setting in the adhesion extruder. - def _getSettingFromAdhesionExtruder(self, setting_key, property = "value"): - return self._getSettingFromExtruder(setting_key, "adhesion_extruder_nr", property) - ## Private convenience function to get a setting from every extruder. # # For single extrusion machines, this gets the setting from the global @@ -899,38 +890,6 @@ class BuildVolume(SceneNode): all_values[i] = 0 return all_values - ## Private convenience function to get a setting from the support infill - # extruder. - # - # \param setting_key The key of the setting to get. - # \param property The property to get from the setting. - # \return The property of the specified setting in the support infill - # extruder. - def _getSettingFromSupportInfillExtruder(self, setting_key, property = "value"): - return self._getSettingFromExtruder(setting_key, "support_infill_extruder_nr", property) - - ## Helper function to get a setting from an extruder specified in another - # setting. - # - # \param setting_key The key of the setting to get. - # \param extruder_setting_key The key of the setting that specifies from - # which extruder to get the setting, if there are multiple extruders. - # \param property The property to get from the setting. - # \return The property of the specified setting in the specified extruder. - def _getSettingFromExtruder(self, setting_key, extruder_setting_key, prop = "value"): - extruder_index = self._global_container_stack.getProperty(extruder_setting_key, "value") - extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] - extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] - - value = extruder_stack.getProperty(setting_key, prop) - setting_type = extruder_stack.getProperty(setting_key, "type") - - # default 0 for numerical values - if not value and (setting_type == "int" or setting_type == "float"): - return 0 - - return value - ## Convenience function to calculate the disallowed radius around the edge. # # This disallowed radius is to allow for space around the models that is @@ -948,29 +907,32 @@ class BuildVolume(SceneNode): return 0.1 # Return a very small value, so we do draw disallowed area's near the edges. adhesion_type = container_stack.getProperty("adhesion_type", "value") - + skirt_brim_line_width = self._global_container_stack.getProperty("skirt_brim_line_width", "value") + initial_layer_line_width_factor = self._global_container_stack.getProperty("initial_layer_line_width_factor", "value") if adhesion_type == "skirt": - skirt_distance = self._getSettingFromAdhesionExtruder("skirt_gap") - skirt_line_count = self._getSettingFromAdhesionExtruder("skirt_line_count") - bed_adhesion_size = skirt_distance + (self._getSettingFromAdhesionExtruder("skirt_brim_line_width") * skirt_line_count) * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor") / 100.0 + skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value") + skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value") + + bed_adhesion_size = skirt_distance + (skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0 for extruder_stack in used_extruders: bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 # We don't create an additional line for the extruder we're printing the skirt with. - bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0 elif adhesion_type == "brim": - bed_adhesion_size = self._getSettingFromAdhesionExtruder("skirt_brim_line_width") * self._getSettingFromAdhesionExtruder("brim_line_count") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor") / 100.0 + brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value") + bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0 for extruder_stack in used_extruders: bed_adhesion_size += extruder_stack.getProperty("skirt_brim_line_width", "value") * extruder_stack.getProperty("initial_layer_line_width_factor", "value") / 100.0 # We don't create an additional line for the extruder we're printing the brim with. - bed_adhesion_size -= self._getSettingFromAdhesionExtruder("skirt_brim_line_width", "value") * self._getSettingFromAdhesionExtruder("initial_layer_line_width_factor", "value") / 100.0 + bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0 elif adhesion_type == "raft": - bed_adhesion_size = self._getSettingFromAdhesionExtruder("raft_margin") + bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value") elif adhesion_type == "none": bed_adhesion_size = 0 @@ -979,8 +941,10 @@ class BuildVolume(SceneNode): raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?") support_expansion = 0 - if self._getSettingFromSupportInfillExtruder("support_offset") and self._global_container_stack.getProperty("support_enable", "value"): - support_expansion += self._getSettingFromSupportInfillExtruder("support_offset") + support_enabled = self._global_container_stack.getProperty("support_enable", "value") + support_offset = self._global_container_stack.getProperty("support_offset", "value") + if support_enabled and support_offset: + support_expansion += support_offset farthest_shield_distance = 0 if container_stack.getProperty("draft_shield_enabled", "value"): From 9b102f9a7ef6c5232e2be57f1cd6f2b57c7bdd46 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 11:02:18 +0100 Subject: [PATCH 51/54] Remove unused function in StartSliceJob CURA-4482 --- plugins/CuraEngineBackend/StartSliceJob.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 49dfc71769..196b18e094 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -9,7 +9,6 @@ import time from UM.Job import Job from UM.Application import Application from UM.Logger import Logger -from UM.Decorators import deprecated from UM.Scene.SceneNode import SceneNode from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -247,20 +246,6 @@ class StartSliceJob(Job): setting.value = str(stack.getProperty(key, "value")).encode("utf-8") Job.yieldThread() - ## Create extruder message from global stack - @deprecated("Extruder stack is always used since version 3.1, even with single extrusion machines", "3.1") - def _buildExtruderMessageFromGlobalStack(self, stack): - message = self._slice_message.addRepeatedMessage("extruders") - - for key in stack.getAllKeys(): - # Do not send settings that are not settable_per_extruder. - if not stack.getProperty(key, "settable_per_extruder"): - continue - setting = message.getMessage("settings").addRepeatedMessage("settings") - setting.name = key - setting.value = str(stack.getProperty(key, "value")).encode("utf-8") - Job.yieldThread() - ## Sends all global settings to the engine. # # The settings are taken from the global stack. This does not include any From aa92d4d0f97bcd36ccd1a7cfff30fd5fc68d843e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 17 Nov 2017 11:46:55 +0100 Subject: [PATCH 52/54] Add to all installation to lib/ folders Some systems have a suffix there to indicate the address size, such as lib64. --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44b4b57f54..9296c4ce4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ find_package(PythonInterp 3.5.0 REQUIRED) install(DIRECTORY resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura) install(DIRECTORY plugins - DESTINATION lib/cura) + DESTINATION lib${LIB_SUFFIX}/cura) if(NOT APPLE AND NOT WIN32) install(FILES cura_app.py DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -47,16 +47,16 @@ if(NOT APPLE AND NOT WIN32) RENAME cura) if(EXISTS /etc/debian_version) install(DIRECTORY cura - DESTINATION lib/python${PYTHON_VERSION_MAJOR}/dist-packages + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}/dist-packages FILES_MATCHING PATTERN *.py) install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py - DESTINATION lib/python${PYTHON_VERSION_MAJOR}/dist-packages/cura) + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}/dist-packages/cura) else() install(DIRECTORY cura - DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages FILES_MATCHING PATTERN *.py) install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py - DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura) + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura) endif() install(FILES ${CMAKE_BINARY_DIR}/cura.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) @@ -72,8 +72,8 @@ else() DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY cura - DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages FILES_MATCHING PATTERN *.py) install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py - DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura) + DESTINATION lib${LIB_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/cura) endif() From e246784df268224d0271e6e303858d5b1a5c500d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 12:43:30 +0100 Subject: [PATCH 53/54] Use parseBool() for metadata bool values CURA-4482 --- cura/Settings/MachineManager.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7bbbd868f4..0daf54c018 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1175,15 +1175,14 @@ class MachineManager(QObject): @pyqtProperty(bool, notify = globalContainerChanged) def hasMaterials(self) -> bool: if self._global_container_stack: - return bool(self._global_container_stack.getMetaDataEntry("has_materials", False)) + return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)) return False @pyqtProperty(bool, notify = globalContainerChanged) def hasVariants(self) -> bool: if self._global_container_stack: - return bool(self._global_container_stack.getMetaDataEntry("has_variants", False)) - + return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False)) return False ## Property to indicate if a machine has "specialized" material profiles. @@ -1191,8 +1190,7 @@ class MachineManager(QObject): @pyqtProperty(bool, notify = globalContainerChanged) def filterMaterialsByMachine(self) -> bool: if self._global_container_stack: - return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False)) - + return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False)) return False ## Property to indicate if a machine has "specialized" quality profiles. @@ -1200,7 +1198,7 @@ class MachineManager(QObject): @pyqtProperty(bool, notify = globalContainerChanged) def filterQualityByMachine(self) -> bool: if self._global_container_stack: - return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False)) + return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False)) return False ## Get the Definition ID of a machine (specified by ID) From 2c39612bc8d06245edb3ffdba26859480c5b0d51 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 12:47:28 +0100 Subject: [PATCH 54/54] Fix UM2 upgrade regarding the variant CURA-4482 UM2 by default doesn't have variants, but if the user enables Olsson Block, the variant option will become available. This commit fixes the following cases: - Make sure that the variant is set on the extruder stack but not the global stack - Extruder stacks don't contain information such as has_variant. Such info should be retrieved from the global stack and not just from the definition container because they can be overriden by other containers. --- cura/Settings/CuraContainerRegistry.py | 5 ++++- cura/Settings/CuraContainerStack.py | 4 +++- cura/Settings/ExtruderStack.py | 5 +++++ plugins/UltimakerMachineActions/UM2UpgradeSelection.py | 4 ++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 526685465e..5cfe867bc2 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -443,7 +443,10 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.setUserChanges(user_container) self.addContainer(user_container) - extruder_stack.setVariantById("default") + variant_id = "default" + if machine.variant.getId() != "empty_variant": + variant_id = machine.variant.getId() + extruder_stack.setVariantById(variant_id) extruder_stack.setMaterialById("default") extruder_stack.setQualityById("default") diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 2d3bf683f6..2a804def4d 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -396,7 +396,9 @@ class CuraContainerStack(ContainerStack): # \note This method assumes the stack has a valid machine definition. def findDefaultVariant(self) -> Optional[ContainerInterface]: definition = self._getMachineDefinition() - if not definition.getMetaDataEntry("has_variants"): + # has_variants can be overridden in other containers and stacks. + # In the case of UM2, it is overridden in the GlobalStack + if not self.getMetaDataEntry("has_variants"): # If the machine does not use variants, we should never set a variant. return None diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index d8ff6645a8..fe7068b7ea 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -115,6 +115,11 @@ class ExtruderStack(CuraContainerStack): if has_global_dependencies: self.getNextStack().propertiesChanged.emit(key, properties) + def findDefaultVariant(self): + # The default variant is defined in the machine stack and/or definition, so use the machine stack to find + # the default variant. + return self.getNextStack().findDefaultVariant() + extruder_stack_mime = MimeType( name = "application/x-cura-extruderstack", diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py index c84033a98e..db277bc485 100644 --- a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py +++ b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py @@ -37,7 +37,7 @@ class UM2UpgradeSelection(MachineAction): def setHasVariants(self, has_variants = True): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: - variant_container = global_container_stack.variant + variant_container = global_container_stack.extruders["0"].variant variant_index = global_container_stack.getContainerIndex(variant_container) if has_variants: @@ -52,7 +52,7 @@ class UM2UpgradeSelection(MachineAction): search_criteria = { "type": "variant", "definition": "ultimaker2", "id": "*0.4*" } containers = self._container_registry.findInstanceContainers(**search_criteria) if containers: - global_container_stack.variant = containers[0] + global_container_stack.extruders["0"].variant = containers[0] else: # The metadata entry is stored in an ini, and ini files are parsed as strings only. # Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.