From 8082c092e5d9fb6aff930a5dfa02f8bd4b528686 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 27 Nov 2017 09:54:10 +0100 Subject: [PATCH 1/6] Fix setting extruder definition in user changes container --- cura/Settings/CuraStackBuilder.py | 2 +- cura/Settings/MachineManager.py | 1 - plugins/3MFReader/ThreeMFWorkspaceReader.py | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index a661237722..7a260e2145 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -108,7 +108,7 @@ class CuraStackBuilder: user_container.addMetaDataEntry("extruder", new_stack_id) from cura.CuraApplication import CuraApplication user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_container.setDefinition(machine_definition) + user_container.setDefinition(definition) stack.setUserChanges(user_container) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6b03916fdf..6bacae11a0 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -772,7 +772,6 @@ class MachineManager(QObject): quality_manager.getWholeMachineDefinition(material_container.getDefinition()), [material_container]) - if not candidate_quality or isinstance(candidate_quality, type(self._empty_quality_changes_container)): Logger.log("d", "Attempting to find fallback quality") # Fall back to a quality (which must be compatible with all other extruders) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index dfb16b91e1..4300d8605d 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -768,6 +768,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._container_registry.removeContainer(container.getId()) return + # Check quality profiles to make sure that if one stack has the "not supported" quality profile, # all others should have the same. # From 4a4f01f9eb27db31bbf16cb1a3f5c6cae8cc1881 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Nov 2017 10:50:30 +0100 Subject: [PATCH 2/6] Fix resetting not supported profiles for project loading CURA-4617 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 87 +++++++++++++++------ 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 4300d8605d..0b5193eb60 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -13,6 +13,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.MimeTypeDatabase import MimeTypeDatabase from UM.Job import Job from UM.Preferences import Preferences +from UM.Util import parseBool from .WorkspaceDialog import WorkspaceDialog import xml.etree.ElementTree as ET @@ -793,6 +794,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] for stack in [global_stack] + extruder_stacks: stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container) + empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + for stack in [global_stack] + extruder_stacks: + stack.replaceContainer(_ContainerIndexes.QualityChanges, empty_quality_changes_container) # Fix quality: # The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal" @@ -800,39 +804,70 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the # fix for that quality = global_stack.quality + has_empty_quality = True + project_quality_is_not_supported = True if quality.getId() not in ("empty", "empty_quality"): + has_empty_quality = False quality_type = quality.getMetaDataEntry("quality_type") - quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(), - type = "quality", - quality_type = quality_type) + search_criteria = {"type": "quality", + "quality_type": quality_type} + if parseBool(global_stack.definition.getMetaDataEntry("has_machine_quality", "False")): + search_criteria["definition"] = global_stack.definition.getId() + else: + search_criteria["definition"] = "fdmprinter" + + quality_containers = self._container_registry.findInstanceContainers(**search_criteria) quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] if quality_containers: global_stack.quality = quality_containers[0] + project_quality_is_not_supported = False else: - # look for "fdmprinter" qualities if the machine-specific qualities cannot be found - quality_containers = self._container_registry.findInstanceContainers(definition = "fdmprinter", - type = "quality", - quality_type = quality_type) + # the quality_type of the quality profile cannot be found. + # this can happen if a quality_type has been removed in a newer version, for example: + # "extra_coarse" is removed from 2.7 to 3.0 + # in this case, the quality will be reset to "normal" + quality_containers = self._container_registry.findInstanceContainers( + definition = global_stack.definition.getId(), + type = "quality", + quality_type = "normal") quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] if quality_containers: global_stack.quality = quality_containers[0] - else: - # the quality_type of the quality profile cannot be found. - # this can happen if a quality_type has been removed in a newer version, for example: - # "extra_coarse" is removed from 2.7 to 3.0 - # in this case, the quality will be reset to "normal" - quality_containers = self._container_registry.findInstanceContainers( - definition = global_stack.definition.getId(), - type = "quality", - quality_type = "normal") - quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] - if quality_containers: - global_stack.quality = quality_containers[0] + + if not quality_containers: + # This should not happen! + Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", + global_stack.getId(), global_stack.definition.getId()) + has_empty_quality = True + + if project_quality_is_not_supported: + empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + + if has_empty_quality: + for stack in [global_stack] + extruder_stacks: + stack.quality = empty_quality_container + stack.qualityChanges = empty_quality_changes_container + else: + for stack in [global_stack] + extruder_stacks: + stack.qualityChanges = empty_quality_changes_container + # for extruder stacks, the quality containers also need to be switched + for stack in extruder_stacks: + search_criteria = {"type": "quality", + "quality_type": "normal"} + if parseBool(global_stack.definition.getMetaDataEntry("has_machine_quality", "False")): + search_criteria["definition"] = global_stack.definition.getId() else: - # This should not happen! - Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", - global_stack.getId(), global_stack.definition.getId()) - global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + search_criteria["definition"] = "fdmprinter" + + if parseBool(global_stack.getMetaDataEntry("has_machine_material")): + search_criteria["material"] = stack.material.getId() + + quality_containers = self._container_registry.findInstanceContainers(**search_criteria) + if quality_containers: + stack.quality = quality_containers[0] + else: + Logger.log("e", "Cannot find quality container for extruder stack [%s]", stack.getId()) # 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 @@ -856,7 +891,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader): global_stack.userChanges = container continue - for changes_container_type in ("quality_changes", "definition_changes"): + changes_container_types = ("quality_changes", "definition_changes") + if project_quality_is_not_supported: + # DO NOT replace quality_changes if the current quality_type is not supported + changes_container_types = ("definition_changes",) + for changes_container_type in changes_container_types: if self._resolve_strategies[changes_container_type] == "new": # Quality changes needs to get a new ID, added to registry and to the right stacks for each_changes_container in quality_and_definition_changes_instance_containers: From 46c6c6aa9b146f60fa270a932d9ccf031bfc40df Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Nov 2017 11:19:37 +0100 Subject: [PATCH 3/6] Fix quality profile in project loading CURA-4617 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 23 ++++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 0b5193eb60..e49cfa33a9 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -822,17 +822,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader): global_stack.quality = quality_containers[0] project_quality_is_not_supported = False else: - # the quality_type of the quality profile cannot be found. - # this can happen if a quality_type has been removed in a newer version, for example: - # "extra_coarse" is removed from 2.7 to 3.0 - # in this case, the quality will be reset to "normal" - quality_containers = self._container_registry.findInstanceContainers( - definition = global_stack.definition.getId(), - type = "quality", - quality_type = "normal") + search_criteria["definition"] = "fdmprinter" + quality_containers = self._container_registry.findInstanceContainers(**search_criteria) quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] if quality_containers: global_stack.quality = quality_containers[0] + project_quality_is_not_supported = False + else: + # the quality_type of the quality profile cannot be found. + # this can happen if a quality_type has been removed in a newer version, for example: + # "extra_coarse" is removed from 2.7 to 3.0 + # in this case, the quality will be reset to "normal" + quality_containers = self._container_registry.findInstanceContainers( + definition = global_stack.definition.getId(), + type = "quality", + quality_type = "normal") + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] + if quality_containers: + global_stack.quality = quality_containers[0] if not quality_containers: # This should not happen! From 828fff5ee5ebcc48049fda21445ea06248688639 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Nov 2017 12:04:21 +0100 Subject: [PATCH 4/6] Fix quality check in project loading CURA-4617 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 120 ++++++++------------ 1 file changed, 45 insertions(+), 75 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index e49cfa33a9..e7a47561ce 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -784,12 +784,16 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # has_not_supported = False for stack in [global_stack] + extruder_stacks: - if stack.quality.getId() == "empty_quality": + if stack.quality.getId() in ("empty", "empty_quality"): has_not_supported = True break + available_quality = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_stack, + extruder_stacks) if not has_not_supported: - available_quality = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_stack, extruder_stacks) has_not_supported = not available_quality + + quality_has_been_changed = False + if has_not_supported: empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] for stack in [global_stack] + extruder_stacks: @@ -797,84 +801,50 @@ class ThreeMFWorkspaceReader(WorkspaceReader): empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] for stack in [global_stack] + extruder_stacks: stack.replaceContainer(_ContainerIndexes.QualityChanges, empty_quality_changes_container) + quality_has_been_changed = True - # Fix quality: - # The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal" - # but instead it was "normal". This should be fixed by setting it to the correct quality. - # Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the - # fix for that - quality = global_stack.quality - has_empty_quality = True - project_quality_is_not_supported = True - if quality.getId() not in ("empty", "empty_quality"): - has_empty_quality = False - quality_type = quality.getMetaDataEntry("quality_type") - search_criteria = {"type": "quality", - "quality_type": quality_type} - if parseBool(global_stack.definition.getMetaDataEntry("has_machine_quality", "False")): - search_criteria["definition"] = global_stack.definition.getId() - else: - search_criteria["definition"] = "fdmprinter" + else: + empty_quality_changes_container = self._container_registry.findInstanceContainers(id="empty_quality_changes")[0] - quality_containers = self._container_registry.findInstanceContainers(**search_criteria) - quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] - if quality_containers: - global_stack.quality = quality_containers[0] - project_quality_is_not_supported = False - else: - search_criteria["definition"] = "fdmprinter" - quality_containers = self._container_registry.findInstanceContainers(**search_criteria) - quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] - if quality_containers: - global_stack.quality = quality_containers[0] - project_quality_is_not_supported = False - else: - # the quality_type of the quality profile cannot be found. - # this can happen if a quality_type has been removed in a newer version, for example: - # "extra_coarse" is removed from 2.7 to 3.0 - # in this case, the quality will be reset to "normal" - quality_containers = self._container_registry.findInstanceContainers( - definition = global_stack.definition.getId(), - type = "quality", - quality_type = "normal") - quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] - if quality_containers: - global_stack.quality = quality_containers[0] + # The machine in the project has non-empty quality and there are usable qualities for this machine. + # We need to check if the current quality_type is still usable for this machine, if not, then the quality + # will be reset to the "preferred quality" if present, otherwise "normal". + available_quality_types = [q.getMetaDataEntry("quality_type") for q in available_quality] - if not quality_containers: - # This should not happen! - Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", - global_stack.getId(), global_stack.definition.getId()) - has_empty_quality = True + if global_stack.quality.getMetaDataEntry("quality_type") not in available_quality_types: + quality_has_been_changed = True - if project_quality_is_not_supported: - empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] - empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + # find the preferred quality + preferred_quality_id = global_stack.getMetaDataEntry("preferred_quality", None) + if preferred_quality_id is not None: + definition_id = global_stack.definition.getId() + if not parseBool(global_stack.getMetaDataEntry("has_machine_quality", "False")): + definition_id = "fdmprinter" + + containers = self._container_registry.findInstanceContainers(id = preferred_quality_id, + type = "quality", + definition = definition_id) + containers = [c for c in containers if not c.getMetaDataEntry("material", "")] + if containers: + global_stack.quality = containers[0] + global_stack.qualityChanges = empty_quality_changes_container + # also find the quality containers for the extruders + for extruder_stack in extruder_stacks: + search_criteria = {"id": preferred_quality_id, + "type": "quality", + "definition": definition_id} + if global_stack.getMetaDataEntry("has_machine_materials") and extruder_stack.material.getId() not in ("empty", "empty_material"): + search_criteria["material"] = extruder_stack.material.getId() + containers = self._container_registry.findInstanceContainers(**search_criteria) + if containers: + extruder_stack.quality = containers[0] + extruder_stack.qualityChanges = empty_quality_changes_container + else: + Logger.log("e", "Cannot find preferred quality for extruder [%s].", extruder_stack.getId()) - if has_empty_quality: - for stack in [global_stack] + extruder_stacks: - stack.quality = empty_quality_container - stack.qualityChanges = empty_quality_changes_container - else: - for stack in [global_stack] + extruder_stacks: - stack.qualityChanges = empty_quality_changes_container - # for extruder stacks, the quality containers also need to be switched - for stack in extruder_stacks: - search_criteria = {"type": "quality", - "quality_type": "normal"} - if parseBool(global_stack.definition.getMetaDataEntry("has_machine_quality", "False")): - search_criteria["definition"] = global_stack.definition.getId() else: - search_criteria["definition"] = "fdmprinter" - - if parseBool(global_stack.getMetaDataEntry("has_machine_material")): - search_criteria["material"] = stack.material.getId() - - quality_containers = self._container_registry.findInstanceContainers(**search_criteria) - if quality_containers: - stack.quality = quality_containers[0] - else: - Logger.log("e", "Cannot find quality container for extruder stack [%s]", stack.getId()) + # we cannot find the preferred quality. THIS SHOULD NOT HAPPEN + Logger.log("e", "Cannot find the preferred quality for machine [%s]", global_stack.getId()) # 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 @@ -899,7 +869,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): continue changes_container_types = ("quality_changes", "definition_changes") - if project_quality_is_not_supported: + if quality_has_been_changed: # DO NOT replace quality_changes if the current quality_type is not supported changes_container_types = ("definition_changes",) for changes_container_type in changes_container_types: From 1866c4ee66de8d726fc5b1d37ffad373bdaaffd6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Nov 2017 12:56:53 +0100 Subject: [PATCH 5/6] Split user settings for single extrusion machines CURA-4617 --- cura/Settings/CuraContainerRegistry.py | 30 +++++++++++++++----------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 3590d70602..1975458548 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -431,19 +431,25 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) extruder_stack.setNextStack(machine) + # 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) + 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) + # for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes + # container to the extruder stack. + for user_setting_key in machine.userChanges.getAllKeys(): + settable_per_extruder = machine.getProperty(user_setting_key, "settable_per_extruder") + if settable_per_extruder: + user_container.addInstance(machine.userChanges.getInstance(user_setting_key)) + machine.userChanges.removeInstance(user_setting_key, postpone_emit = True) + + extruder_stack.setUserChanges(user_container) + self.addContainer(user_container) variant_id = "default" if machine.variant.getId() not in ("empty", "empty_variant"): From 13124ae983e6e3fadb9e438445c9cecc659995c3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Nov 2017 13:54:09 +0100 Subject: [PATCH 6/6] Don't make filter_out_tiny_gaps a child setting of fill_perimeter_gaps Parent settings are not used by the engine. Or they shouldn't be, because the parent settings are disabled by the front-end when all of their child settings are overwritten. Then you'd have a parent setting that is used by the engine but you can't modify it. Also, the command-line slicing doesn't load parent settings since it can't parse categories and such. --- resources/definitions/fdmprinter.def.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index be2c5d9757..be15450db6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1208,7 +1208,8 @@ } } }, - "fill_perimeter_gaps": { + "fill_perimeter_gaps": + { "label": "Fill Gaps Between Walls", "description": "Fills the gaps between walls where no walls fit.", "type": "enum", @@ -1220,6 +1221,15 @@ "limit_to_extruder": "wall_0_extruder_nr", "settable_per_mesh": true }, + "filter_out_tiny_gaps": + { + "label": "Filter Out Tiny Gaps", + "description": "Filter out tiny gaps to reduce blobs on outside of model.", + "type": "bool", + "default_value": true, + "limit_to_extruder": "wall_0_extruder_nr", + "settable_per_mesh": true + }, "fill_outline_gaps": { "label": "Print Thin Walls", "description": "Print pieces of the model which are horizontally thinner than the nozzle size.",