From c132300fd553d28e10f1a6b9a361dd78688cac70 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 23 Oct 2017 13:56:26 +0200 Subject: [PATCH 01/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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 cd37f91a0a29ed097832d88db9346c520e926f80 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 10:40:13 +0100 Subject: [PATCH 44/47] 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 45/47] 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 e246784df268224d0271e6e303858d5b1a5c500d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 17 Nov 2017 12:43:30 +0100 Subject: [PATCH 46/47] 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 47/47] 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.