diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a4d2043146..09f04d9a2d 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -86,10 +86,19 @@ class CuraApplication(QtApplication): # Need to do this before ContainerRegistry tries to load the machines SettingDefinition.addSupportedProperty("settable_per_mesh", DefinitionPropertyType.Any, default = True, read_only = True) SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True, read_only = True) + # this setting can be changed for each group in one-at-a-time mode SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True, read_only = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True, read_only = True) + + # From which stack the setting would inherit if not defined per object (handled in the engine) + # AND for settings which are not settable_per_mesh: + # which extruder is the only extruder this setting is obtained from SettingDefinition.addSupportedProperty("limit_to_extruder", DefinitionPropertyType.Function, default = "-1") + + # For settings which are not settable_per_mesh and not settable_per_extruder: + # A function which determines the glabel/meshgroup value by looking at the values of the setting in all (used) extruders SettingDefinition.addSupportedProperty("resolve", DefinitionPropertyType.Function, default = None) + SettingDefinition.addSettingType("extruder", None, str, Validator) SettingFunction.registerOperator("extruderValues", cura.Settings.ExtruderManager.getExtruderValues) @@ -112,11 +121,12 @@ class CuraApplication(QtApplication): ## Initialise the version upgrade manager with Cura's storage paths. import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies. - self._version_upgrade_manager = UM.VersionUpgradeManager.VersionUpgradeManager( + UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions( { ("quality", UM.Settings.InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), ("machine_stack", UM.Settings.ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"), - ("preferences", UM.Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences") + ("preferences", UM.Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences"), + ("user", UM.Settings.InstanceContainer.Version): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer") } ) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 9d7eac8a05..1ef79f2b86 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -83,7 +83,7 @@ class QualityManager: filter_by_material = machine_definition.getMetaDataEntry("has_materials") # Stick the material IDs in a set - if material_containers is None: + if material_containers is None or len(material_containers) == 0: filter_by_material = False else: material_ids = set() diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index a0648587c2..0ef2660549 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -587,24 +587,17 @@ class ContainerManager(QObject): def _duplicateQualityOrQualityChangesForMachineType(self, quality_name, base_name, machine_definition, material_instances): UM.Logger.log("d", "Attempting to duplicate the quality %s", quality_name) - # Try Quality + if base_name is None: + base_name = quality_name + + # Try to find a Quality with the name. containers = QualityManager.getInstance().findQualityByName(quality_name, machine_definition, material_instances) if containers: container = containers[0] - if base_name is None: - base_name = quality_name return self._duplicateQualityForMachineType(container, base_name, machine_definition) - # Try quality changes. - containers = QualityManager.getInstance().findQualityChangesByName(quality_name, machine_definition, material_instances) - if containers: - container = containers[0] - if base_name is None: - base_name = quality_name - return self._duplicateQualityChangesForMachineType(container, base_name, machine_definition) - else: - UM.Logger.log("d", "Unable to duplicate the quality %s, because it doesn't exist.", quality_name) - return "" + # Assume it is a quality changes. + return self._duplicateQualityChangesForMachineType(quality_name, base_name, machine_definition) # Duplicate a quality profile def _duplicateQualityForMachineType(self, quality_container, base_name, machine_definition): @@ -631,10 +624,10 @@ class ContainerManager(QObject): return new_change_instances # Duplicate a quality changes container - def _duplicateQualityChangesForMachineType(self, quality_changes_container, base_name, machine_definition): + def _duplicateQualityChangesForMachineType(self, quality_changes_name, base_name, machine_definition): new_change_instances = [] - for container in QualityManager.getInstance().findQualityChangesByName(quality_changes_container.getName(), - machine_definition, None): + for container in QualityManager.getInstance().findQualityChangesByName(quality_changes_name, + machine_definition, []): new_unique_id = self._createUniqueId(container.getId(), base_name) new_container = container.duplicate(new_unique_id, base_name) new_change_instances.append(new_container) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 451be66862..9dcb25e274 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -885,14 +885,13 @@ class MachineManager(QObject): def _updateVariantContainer(self, definition): if not definition.getMetaDataEntry("has_variants"): return self._empty_variant_container - + machine_definition_id = UM.Application.getInstance().getMachineManager().getQualityDefinitionId(definition) containers = [] preferred_variant = definition.getMetaDataEntry("preferred_variant") if preferred_variant: - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id, id = preferred_variant) - + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id, id = preferred_variant) if not containers: - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id) + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id) if containers: return containers[0] diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index d5407f22c8..4eab500f0a 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -13,7 +13,7 @@ message Slice repeated ObjectList object_lists = 1; // The meshgroups to be printed one after another SettingList global_settings = 2; // The global settings used for the whole print job repeated Extruder extruders = 3; // The settings sent to each extruder object - repeated SettingExtruder limit_to_extruder = 4; //From which stack the setting would inherit if not defined in a stack. + repeated SettingExtruder limit_to_extruder = 4; // From which stack the setting would inherit if not defined per object } message Extruder diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py b/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py index 6510d34cb1..222af84d3a 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py @@ -2,9 +2,13 @@ # Cura is released under the terms of the AGPLv3 or higher. import UM.VersionUpgrade #To indicate that a file is of incorrect format. +import UM.VersionUpgradeManager #To schedule more files to be upgraded. +import UM.Resources #To get the config storage path. import configparser #To read config files. import io #To write config files to strings as if they were files. +import os.path #To get the path to write new user profiles to. +import urllib #To serialise the user container file name properly. ## Creates a new machine instance instance by parsing a serialised machine # instance in version 1 of the file format. @@ -92,8 +96,30 @@ class MachineInstance: if has_machine_qualities: #This machine now has machine-quality profiles. active_material += "_" + variant_materials #That means that the profile was split into multiple. + #Create a new user profile and schedule it to be upgraded. + user_profile = configparser.ConfigParser(interpolation = None) + user_profile["general"] = { + "version": "2", + "name": "Current settings", + "definition": type_name + } + user_profile["metadata"] = { + "type": "user", + "machine": self._name + } + user_profile["values"] = {} + + version_upgrade_manager = UM.VersionUpgradeManager.VersionUpgradeManager.getInstance() + user_storage = os.path.join(UM.Resources.getDataStoragePath(), next(iter(version_upgrade_manager.getStoragePaths("user")))) + user_profile_file = os.path.join(user_storage, urllib.parse.quote_plus(self._name) + "_current_settings.inst.cfg") + if not os.path.exists(user_storage): + os.makedirs(user_storage) + with open(user_profile_file, "w") as file_handle: + user_profile.write(file_handle) + version_upgrade_manager.upgradeExtraFile(user_storage, urllib.parse.quote_plus(self._name), "user") + containers = [ - "", #The current profile doesn't know the definition ID when it was upgraded, only the instance ID, so it will be invalid. Sorry, your current settings are lost now. + self._name + "_current_settings", #The current profile doesn't know the definition ID when it was upgraded, only the instance ID, so it will be invalid. Sorry, your current settings are lost now. active_quality_changes, active_quality, active_material, diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py b/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py index 86cfda6b90..f2803ca62f 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py @@ -35,6 +35,10 @@ def getMetaData(): "preferences": { "get_version": upgrade.getCfgVersion, "location": {"."} + }, + "user": { + "get_version": upgrade.getCfgVersion, + "location": {"./user"} } } } diff --git a/plugins/X3DReader/X3DReader.py b/plugins/X3DReader/X3DReader.py index f1c217da9d..4ce21f3f8c 100644 --- a/plugins/X3DReader/X3DReader.py +++ b/plugins/X3DReader/X3DReader.py @@ -78,12 +78,17 @@ class X3DReader(MeshReader): builder.setIndices(numpy.concatenate([shape.faces for shape in self.shapes])) builder.calculateNormals() builder.setFileName(file_name) - - scene = SceneNode() - scene.setMeshData(builder.build()) - scene.setSelectable(True) - scene.setName(file_name) - scene.getBoundingBox() + mesh_data = builder.build() + + # Manually try and get the extents of the mesh_data. This should prevent nasty NaN issues from + # leaving the reader. + mesh_data.getExtents() + + node = SceneNode() + node.setMeshData(mesh_data) + node.setSelectable(True) + node.setName(file_name) + else: return None @@ -91,7 +96,7 @@ class X3DReader(MeshReader): Logger.logException("e", "Exception in X3D reader") return None - return scene + return node # ------------------------- XML tree traversal diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index f377690219..44f8cc8c85 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -52,7 +52,7 @@ Menu filter: { "type": "variant", - "definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine + "definition": Cura.MachineManager.activeQualityDefinitionId //Only show variants of this machine } } MenuItem {