From e67286c0d841b21b172cd679ff2e152ead61c1e6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 15 Aug 2017 14:13:59 +0200 Subject: [PATCH 1/4] Do not add extruder stacks for single-extrusion machines CURA-4167 In the current architecture, single-extrusion machines don't have extruder stacks. --- cura/Settings/GlobalStack.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index e49b1a25de..b00ff1a1f1 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -61,6 +61,12 @@ class GlobalStack(CuraContainerStack): # 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 + if extruder_count and len(self._extruders) + 1 > extruder_count: Logger.log("w", "Adding extruder {meta} to {id} but its extruder count is {count}".format(id = self.id, count = extruder_count, meta = str(extruder.getMetaData()))) return @@ -73,7 +79,9 @@ class GlobalStack(CuraContainerStack): if any(item.getId() == extruder.id for item in self._extruders.values()): Logger.log("w", "Extruder [%s] has already been added to this stack [%s]", extruder.id, self._id) return + self._extruders[position] = extruder + Logger.log("i", "Extruder[%s] added to [%s] at position [%s]", extruder.id, self.id, position) ## Overridden from ContainerStack # From 3a46a337ff39e1138ecbf31581b81667304f9aaf Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 15 Aug 2017 14:15:38 +0200 Subject: [PATCH 2/4] In SliceInfo, use the global stack if it is a single-extrusion machine CURA-4167 Single extrusion machines don't have extruder stacks in the current architecture. --- plugins/3MFWriter/ThreeMFWorkspaceWriter.py | 2 -- plugins/SliceInfoPlugin/SliceInfo.py | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py index f805936ab5..0a915d610e 100644 --- a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py +++ b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py @@ -2,11 +2,9 @@ from UM.Workspace.WorkspaceWriter import WorkspaceWriter from UM.Application import Application from UM.Preferences import Preferences from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.ContainerStack import ContainerStack from cura.Settings.ExtruderManager import ExtruderManager import zipfile from io import StringIO -import copy import configparser diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 0af9c85607..57df84ffc4 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -76,8 +76,11 @@ class SliceInfo(Extension): data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")} data["extruders"] = [] - extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) - extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position")) + 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] From 3ebaacfa1100f02963e502297adeee0f1c2a4726 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 15 Aug 2017 14:16:33 +0200 Subject: [PATCH 3/4] Use the extruder count in the global stack in project loading CURA-4167 Custom FDM printers have multiple extruder stacks by default but not all of them may be used. The actual number of extruders depends on what's defined in the global stack. Because in the current architecture, single-extrusion machines don't have extruder stacks, in project loading, the extruder count in the global stack should be used so these cases can be handled properly. --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 85 +++++++++++---------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 3d4812a677..0377ce7655 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -674,51 +674,61 @@ 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: - container_id = self._stripFileToId(extruder_stack_file) - extruder_file_content = archive.open(extruder_stack_file, "r").read().decode("utf-8") + if extruder_count_from_global_stack > 1: + try: + for extruder_stack_file in extruder_stack_files: + container_id = self._stripFileToId(extruder_stack_file) + extruder_file_content = archive.open(extruder_stack_file, "r").read().decode("utf-8") - if self._resolve_strategies["machine"] == "override": - # deserialize new extruder stack over the current ones - stack = self._overrideExtruderStack(global_stack, extruder_file_content) + if self._resolve_strategies["machine"] == "override": + # deserialize new extruder stack over the current ones + stack = self._overrideExtruderStack(global_stack, extruder_file_content) - elif self._resolve_strategies["machine"] == "new": - new_id = extruder_stack_id_map[container_id] - stack = ExtruderStack(new_id) + elif self._resolve_strategies["machine"] == "new": + new_id = extruder_stack_id_map[container_id] + stack = ExtruderStack(new_id) - # HACK: the global stack can have a new name, so we need to make sure that this extruder stack - # references to the new name instead of the old one. Normally, this can be done after - # deserialize() by setting the metadata, but in the case of ExtruderStack, deserialize() - # also does addExtruder() to its machine stack, so we have to make sure that it's pointing - # to the right machine BEFORE deserialization. - extruder_config = configparser.ConfigParser() - extruder_config.read_string(extruder_file_content) - extruder_config.set("metadata", "machine", global_stack_id_new) - tmp_string_io = io.StringIO() - extruder_config.write(tmp_string_io) - extruder_file_content = tmp_string_io.getvalue() + # HACK: the global stack can have a new name, so we need to make sure that this extruder stack + # references to the new name instead of the old one. Normally, this can be done after + # deserialize() by setting the metadata, but in the case of ExtruderStack, deserialize() + # also does addExtruder() to its machine stack, so we have to make sure that it's pointing + # to the right machine BEFORE deserialization. + extruder_config = configparser.ConfigParser() + extruder_config.read_string(extruder_file_content) + extruder_config.set("metadata", "machine", global_stack_id_new) + tmp_string_io = io.StringIO() + extruder_config.write(tmp_string_io) + extruder_file_content = tmp_string_io.getvalue() - stack.deserialize(extruder_file_content) + stack.deserialize(extruder_file_content) - # Ensure a unique ID and name - stack._id = new_id + # Ensure a unique ID and name + stack._id = new_id - self._container_registry.addContainer(stack) - extruder_stacks_added.append(stack) - containers_added.append(stack) - else: - Logger.log("w", "Unknown resolve strategy: %s", self._resolve_strategies["machine"]) + self._container_registry.addContainer(stack) + extruder_stacks_added.append(stack) + containers_added.append(stack) + else: + Logger.log("w", "Unknown resolve strategy: %s", self._resolve_strategies["machine"]) - extruder_stacks.append(stack) - 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. - for container in containers_added: - self._container_registry.removeContainer(container.getId()) - return + extruder_stacks.append(stack) + 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. + for container in containers_added: + self._container_registry.removeContainer(container.getId()) + return # # Replacing the old containers if resolve is "new". @@ -823,9 +833,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if extruder_stacks: for stack in extruder_stacks: ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId()) - else: - # Machine has no extruders, but it needs to be registered with the extruder manager. - ExtruderManager.getInstance().registerExtruder(None, global_stack.getId()) Logger.log("d", "Workspace loading is notifying rest of the code of changes...") From da8b55cf62ab91caf24f3969b0c8ef6874d1dffe Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 15 Aug 2017 14:38:48 +0200 Subject: [PATCH 4/4] Make sure stacks will have non-empty definitionChanges in project loading CURA-4107 In old Cura, there is no definitionChanges container, so loading a project file from an old version will result in stacks with empty defnitionChanges. This will cause an unnecessary auto-slice problem when we switch between the extruder tabs for the first time. This action will trigger a piece code in MachineAction which creates a definitionChanges container for the active stack if it is empty. This eventually triggers a propertyChanged signal and results in an unncessary auto-slicing. --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 0377ce7655..8fdb120189 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -17,6 +17,7 @@ from .WorkspaceDialog import WorkspaceDialog import xml.etree.ElementTree as ET +from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.GlobalStack import GlobalStack @@ -665,6 +666,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): 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")) global_stack = stack Job.yieldThread() except: @@ -722,6 +726,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader): else: Logger.log("w", "Unknown resolve strategy: %s", 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")) + extruder_stacks.append(stack) except: Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")