mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-21 20:19:32 +08:00
Generate more possible machine IDs in XML material profile
This commit is contained in:
parent
e10ba065ca
commit
e14d78b32a
@ -212,11 +212,12 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
|
|
||||||
for definition_id, container in machine_container_map.items():
|
for definition_id, container in machine_container_map.items():
|
||||||
definition = container.getDefinition()
|
definition = container.getDefinition()
|
||||||
try:
|
|
||||||
product = UM.Dictionary.findKey(product_id_map, definition_id)
|
product = definition_id
|
||||||
except ValueError:
|
for product_name, product_id_list in product_id_map.items():
|
||||||
# An unknown product id; export it anyway
|
if definition_id in product_id_list:
|
||||||
product = definition_id
|
product = product_name
|
||||||
|
break
|
||||||
|
|
||||||
builder.start("machine")
|
builder.start("machine")
|
||||||
builder.start("machine_identifier", {
|
builder.start("machine_identifier", {
|
||||||
@ -530,106 +531,110 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
|
|
||||||
identifiers = machine.iterfind("./um:machine_identifier", self.__namespaces)
|
identifiers = machine.iterfind("./um:machine_identifier", self.__namespaces)
|
||||||
for identifier in identifiers:
|
for identifier in identifiers:
|
||||||
machine_id = product_id_map.get(identifier.get("product"), None)
|
machine_id_list = product_id_map.get(identifier.get("product"), [])
|
||||||
if machine_id is None:
|
if not machine_id_list:
|
||||||
# Lets try again with some naive heuristics.
|
machine_id_list.append(identifier.get("product").replace(" ", "").lower())
|
||||||
machine_id = identifier.get("product").replace(" ", "").lower()
|
|
||||||
|
|
||||||
definitions = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
|
for machine_id in machine_id_list:
|
||||||
if not definitions:
|
definitions = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
|
||||||
Logger.log("w", "No definition found for machine ID %s", machine_id)
|
if not definitions:
|
||||||
continue
|
Logger.log("w", "No definition found for machine ID %s", machine_id)
|
||||||
|
|
||||||
definition = definitions[0]
|
|
||||||
|
|
||||||
machine_manufacturer = identifier.get("manufacturer", definition.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition.
|
|
||||||
|
|
||||||
if machine_compatibility:
|
|
||||||
new_material_id = self.getId() + "_" + machine_id
|
|
||||||
|
|
||||||
# The child or derived material container may already exist. This can happen when a material in a
|
|
||||||
# project file and the a material in Cura have the same ID.
|
|
||||||
# In the case if a derived material already exists, override that material container because if
|
|
||||||
# the data in the parent material has been changed, the derived ones should be updated too.
|
|
||||||
if ContainerRegistry.getInstance().isLoaded(new_material_id):
|
|
||||||
new_material = ContainerRegistry.getInstance().findContainers(id = new_material_id)[0]
|
|
||||||
is_new_material = False
|
|
||||||
else:
|
|
||||||
new_material = XmlMaterialProfile(new_material_id)
|
|
||||||
is_new_material = True
|
|
||||||
|
|
||||||
new_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
|
||||||
new_material.getMetaData()["id"] = new_material_id
|
|
||||||
new_material.getMetaData()["name"] = self.getName()
|
|
||||||
new_material.setDefinition(machine_id)
|
|
||||||
# Don't use setMetadata, as that overrides it for all materials with same base file
|
|
||||||
new_material.getMetaData()["compatible"] = machine_compatibility
|
|
||||||
new_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
|
||||||
new_material.getMetaData()["definition"] = machine_id
|
|
||||||
|
|
||||||
new_material.setCachedValues(cached_machine_setting_properties)
|
|
||||||
|
|
||||||
new_material._dirty = False
|
|
||||||
|
|
||||||
if is_new_material:
|
|
||||||
containers_to_add.append(new_material)
|
|
||||||
|
|
||||||
hotends = machine.iterfind("./um:hotend", self.__namespaces)
|
|
||||||
for hotend in hotends:
|
|
||||||
hotend_id = hotend.get("id")
|
|
||||||
if hotend_id is None:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
|
definition = definitions[0]
|
||||||
if not variant_containers:
|
|
||||||
# It is not really properly defined what "ID" is so also search for variants by name.
|
|
||||||
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = definition["id"], name = hotend_id)
|
|
||||||
|
|
||||||
if not variant_containers:
|
machine_manufacturer = identifier.get("manufacturer", definition.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition.
|
||||||
continue
|
|
||||||
|
|
||||||
hotend_compatibility = machine_compatibility
|
if machine_compatibility:
|
||||||
hotend_setting_values = {}
|
new_material_id = self.getId() + "_" + machine_id
|
||||||
settings = hotend.iterfind("./um:setting", self.__namespaces)
|
|
||||||
for entry in settings:
|
# The child or derived material container may already exist. This can happen when a material in a
|
||||||
key = entry.get("key")
|
# project file and the a material in Cura have the same ID.
|
||||||
if key in self.__material_settings_setting_map:
|
# In the case if a derived material already exists, override that material container because if
|
||||||
hotend_setting_values[self.__material_settings_setting_map[key]] = entry.text
|
# the data in the parent material has been changed, the derived ones should be updated too.
|
||||||
elif key in self.__unmapped_settings:
|
if ContainerRegistry.getInstance().isLoaded(new_material_id):
|
||||||
if key == "hardware compatible":
|
new_material = ContainerRegistry.getInstance().findContainers(id = new_material_id)[0]
|
||||||
hotend_compatibility = self._parseCompatibleValue(entry.text)
|
is_new_material = False
|
||||||
else:
|
else:
|
||||||
Logger.log("d", "Unsupported material setting %s", key)
|
new_material = XmlMaterialProfile(new_material_id)
|
||||||
|
is_new_material = True
|
||||||
|
|
||||||
new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
new_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
||||||
|
new_material.getMetaData()["id"] = new_material_id
|
||||||
|
new_material.getMetaData()["name"] = self.getName()
|
||||||
|
new_material.setDefinition(machine_id)
|
||||||
|
# Don't use setMetadata, as that overrides it for all materials with same base file
|
||||||
|
new_material.getMetaData()["compatible"] = machine_compatibility
|
||||||
|
new_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
||||||
|
new_material.getMetaData()["definition"] = machine_id
|
||||||
|
|
||||||
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
new_material.setCachedValues(cached_machine_setting_properties)
|
||||||
# material
|
|
||||||
if ContainerRegistry.getInstance().isLoaded(new_hotend_id):
|
|
||||||
new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0]
|
|
||||||
is_new_material = False
|
|
||||||
else:
|
|
||||||
new_hotend_material = XmlMaterialProfile(new_hotend_id)
|
|
||||||
is_new_material = True
|
|
||||||
|
|
||||||
new_hotend_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
new_material._dirty = False
|
||||||
new_hotend_material.getMetaData()["id"] = new_hotend_id
|
|
||||||
new_hotend_material.getMetaData()["name"] = self.getName()
|
|
||||||
new_hotend_material.getMetaData()["variant"] = variant_containers[0]["id"]
|
|
||||||
# Don't use setMetadata, as that overrides it for all materials with same base file
|
|
||||||
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
|
|
||||||
new_hotend_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
|
||||||
new_hotend_material.getMetaData()["definition"] = machine_id
|
|
||||||
|
|
||||||
cached_hotend_setting_properties = cached_machine_setting_properties.copy()
|
if is_new_material:
|
||||||
cached_hotend_setting_properties.update(hotend_setting_values)
|
containers_to_add.append(new_material)
|
||||||
|
|
||||||
new_hotend_material.setCachedValues(cached_hotend_setting_properties)
|
hotends = machine.iterfind("./um:hotend", self.__namespaces)
|
||||||
|
for hotend in hotends:
|
||||||
|
hotend_id = hotend.get("id")
|
||||||
|
if hotend_id is None:
|
||||||
|
continue
|
||||||
|
|
||||||
new_hotend_material._dirty = False
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
|
||||||
|
if not variant_containers:
|
||||||
|
# It is not really properly defined what "ID" is so also search for variants by name.
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = definition["id"], name = hotend_id)
|
||||||
|
|
||||||
if is_new_material:
|
if not variant_containers:
|
||||||
containers_to_add.append(new_hotend_material)
|
continue
|
||||||
|
|
||||||
|
hotend_compatibility = machine_compatibility
|
||||||
|
hotend_setting_values = {}
|
||||||
|
settings = hotend.iterfind("./um:setting", self.__namespaces)
|
||||||
|
for entry in settings:
|
||||||
|
key = entry.get("key")
|
||||||
|
if key in self.__material_settings_setting_map:
|
||||||
|
hotend_setting_values[self.__material_settings_setting_map[key]] = entry.text
|
||||||
|
elif key in self.__unmapped_settings:
|
||||||
|
if key == "hardware compatible":
|
||||||
|
hotend_compatibility = self._parseCompatibleValue(entry.text)
|
||||||
|
else:
|
||||||
|
Logger.log("d", "Unsupported material setting %s", key)
|
||||||
|
|
||||||
|
new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
||||||
|
|
||||||
|
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
||||||
|
# material
|
||||||
|
if ContainerRegistry.getInstance().isLoaded(new_hotend_id):
|
||||||
|
new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0]
|
||||||
|
is_new_material = False
|
||||||
|
else:
|
||||||
|
new_hotend_material = XmlMaterialProfile(new_hotend_id)
|
||||||
|
is_new_material = True
|
||||||
|
|
||||||
|
new_hotend_material.setMetaData(copy.deepcopy(self.getMetaData()))
|
||||||
|
new_hotend_material.getMetaData()["id"] = new_hotend_id
|
||||||
|
new_hotend_material.getMetaData()["name"] = self.getName()
|
||||||
|
new_hotend_material.getMetaData()["variant"] = variant_containers[0]["id"]
|
||||||
|
# Don't use setMetadata, as that overrides it for all materials with same base file
|
||||||
|
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
|
||||||
|
new_hotend_material.getMetaData()["machine_manufacturer"] = machine_manufacturer
|
||||||
|
new_hotend_material.getMetaData()["definition"] = machine_id
|
||||||
|
|
||||||
|
cached_hotend_setting_properties = cached_machine_setting_properties.copy()
|
||||||
|
cached_hotend_setting_properties.update(hotend_setting_values)
|
||||||
|
|
||||||
|
new_hotend_material.setCachedValues(cached_hotend_setting_properties)
|
||||||
|
|
||||||
|
new_hotend_material._dirty = False
|
||||||
|
|
||||||
|
if is_new_material:
|
||||||
|
containers_to_add.append(new_hotend_material)
|
||||||
|
|
||||||
|
# there is only one ID for a machine. Once we have reached here, it means we have already found
|
||||||
|
# a workable ID for that machine, so there is no need to continue
|
||||||
|
break
|
||||||
|
|
||||||
for container_to_add in containers_to_add:
|
for container_to_add in containers_to_add:
|
||||||
ContainerRegistry.getInstance().addContainer(container_to_add)
|
ContainerRegistry.getInstance().addContainer(container_to_add)
|
||||||
@ -720,79 +725,84 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
machine_compatibility = cls._parseCompatibleValue(entry.text)
|
machine_compatibility = cls._parseCompatibleValue(entry.text)
|
||||||
|
|
||||||
for identifier in machine.iterfind("./um:machine_identifier", cls.__namespaces):
|
for identifier in machine.iterfind("./um:machine_identifier", cls.__namespaces):
|
||||||
machine_id = product_id_map.get(identifier.get("product"), None)
|
machine_id_list = product_id_map.get(identifier.get("product"), [])
|
||||||
if machine_id is None:
|
if not machine_id_list:
|
||||||
# Lets try again with some naive heuristics.
|
machine_id_list.append(identifier.get("product").replace(" ", "").lower())
|
||||||
machine_id = identifier.get("product").replace(" ", "").lower()
|
|
||||||
definition_metadata = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
|
|
||||||
if not definition_metadata:
|
|
||||||
Logger.log("w", "No definition found for machine ID %s", machine_id)
|
|
||||||
continue
|
|
||||||
definition_metadata = definition_metadata[0]
|
|
||||||
|
|
||||||
machine_manufacturer = identifier.get("manufacturer", definition_metadata.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition.
|
for machine_id in machine_id_list:
|
||||||
|
definition_metadata = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
|
||||||
if machine_compatibility:
|
if not definition_metadata:
|
||||||
new_material_id = container_id + "_" + machine_id
|
Logger.log("w", "No definition found for machine ID %s", machine_id)
|
||||||
|
|
||||||
# The child or derived material container may already exist. This can happen when a material in a
|
|
||||||
# project file and the a material in Cura have the same ID.
|
|
||||||
# In the case if a derived material already exists, override that material container because if
|
|
||||||
# the data in the parent material has been changed, the derived ones should be updated too.
|
|
||||||
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_material_id)
|
|
||||||
if found_materials:
|
|
||||||
new_material_metadata = found_materials[0]
|
|
||||||
else:
|
|
||||||
new_material_metadata = {}
|
|
||||||
|
|
||||||
new_material_metadata.update(base_metadata)
|
|
||||||
new_material_metadata["id"] = new_material_id
|
|
||||||
new_material_metadata["compatible"] = machine_compatibility
|
|
||||||
new_material_metadata["machine_manufacturer"] = machine_manufacturer
|
|
||||||
new_material_metadata["definition"] = machine_id
|
|
||||||
|
|
||||||
if len(found_materials) == 0: #This is a new material.
|
|
||||||
result_metadata.append(new_material_metadata)
|
|
||||||
|
|
||||||
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
|
|
||||||
hotend_id = hotend.get("id")
|
|
||||||
if hotend_id is None:
|
|
||||||
continue
|
continue
|
||||||
|
definition_metadata = definition_metadata[0]
|
||||||
|
|
||||||
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
|
machine_manufacturer = identifier.get("manufacturer", definition_metadata.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition.
|
||||||
if not variant_containers:
|
|
||||||
# It is not really properly defined what "ID" is so also search for variants by name.
|
|
||||||
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id)
|
|
||||||
|
|
||||||
hotend_compatibility = machine_compatibility
|
if machine_compatibility:
|
||||||
for entry in hotend.iterfind("./um:setting", cls.__namespaces):
|
new_material_id = container_id + "_" + machine_id
|
||||||
key = entry.get("key")
|
|
||||||
if key == "hardware compatible":
|
|
||||||
hotend_compatibility = cls._parseCompatibleValue(entry.text)
|
|
||||||
|
|
||||||
new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
# The child or derived material container may already exist. This can happen when a material in a
|
||||||
|
# project file and the a material in Cura have the same ID.
|
||||||
|
# In the case if a derived material already exists, override that material container because if
|
||||||
|
# the data in the parent material has been changed, the derived ones should be updated too.
|
||||||
|
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_material_id)
|
||||||
|
if found_materials:
|
||||||
|
new_material_metadata = found_materials[0]
|
||||||
|
else:
|
||||||
|
new_material_metadata = {}
|
||||||
|
|
||||||
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
new_material_metadata.update(base_metadata)
|
||||||
# material
|
new_material_metadata["id"] = new_material_id
|
||||||
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id)
|
new_material_metadata["compatible"] = machine_compatibility
|
||||||
if found_materials:
|
new_material_metadata["machine_manufacturer"] = machine_manufacturer
|
||||||
new_hotend_material_metadata = found_materials[0]
|
new_material_metadata["definition"] = machine_id
|
||||||
else:
|
|
||||||
new_hotend_material_metadata = {}
|
|
||||||
|
|
||||||
new_hotend_material_metadata.update(base_metadata)
|
if len(found_materials) == 0: #This is a new material.
|
||||||
if variant_containers:
|
result_metadata.append(new_material_metadata)
|
||||||
new_hotend_material_metadata["variant"] = variant_containers[0]["id"]
|
|
||||||
else:
|
|
||||||
new_hotend_material_metadata["variant"] = hotend_id
|
|
||||||
_with_missing_variants.append(new_hotend_material_metadata)
|
|
||||||
new_hotend_material_metadata["compatible"] = hotend_compatibility
|
|
||||||
new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer
|
|
||||||
new_hotend_material_metadata["id"] = new_hotend_id
|
|
||||||
new_hotend_material_metadata["definition"] = machine_id
|
|
||||||
|
|
||||||
if len(found_materials) == 0:
|
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
|
||||||
result_metadata.append(new_hotend_material_metadata)
|
hotend_id = hotend.get("id")
|
||||||
|
if hotend_id is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
|
||||||
|
if not variant_containers:
|
||||||
|
# It is not really properly defined what "ID" is so also search for variants by name.
|
||||||
|
variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id)
|
||||||
|
|
||||||
|
hotend_compatibility = machine_compatibility
|
||||||
|
for entry in hotend.iterfind("./um:setting", cls.__namespaces):
|
||||||
|
key = entry.get("key")
|
||||||
|
if key == "hardware compatible":
|
||||||
|
hotend_compatibility = cls._parseCompatibleValue(entry.text)
|
||||||
|
|
||||||
|
new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
|
||||||
|
|
||||||
|
# Same as machine compatibility, keep the derived material containers consistent with the parent
|
||||||
|
# material
|
||||||
|
found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id)
|
||||||
|
if found_materials:
|
||||||
|
new_hotend_material_metadata = found_materials[0]
|
||||||
|
else:
|
||||||
|
new_hotend_material_metadata = {}
|
||||||
|
|
||||||
|
new_hotend_material_metadata.update(base_metadata)
|
||||||
|
if variant_containers:
|
||||||
|
new_hotend_material_metadata["variant"] = variant_containers[0]["id"]
|
||||||
|
else:
|
||||||
|
new_hotend_material_metadata["variant"] = hotend_id
|
||||||
|
_with_missing_variants.append(new_hotend_material_metadata)
|
||||||
|
new_hotend_material_metadata["compatible"] = hotend_compatibility
|
||||||
|
new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer
|
||||||
|
new_hotend_material_metadata["id"] = new_hotend_id
|
||||||
|
new_hotend_material_metadata["definition"] = machine_id
|
||||||
|
|
||||||
|
if len(found_materials) == 0:
|
||||||
|
result_metadata.append(new_hotend_material_metadata)
|
||||||
|
|
||||||
|
# there is only one ID for a machine. Once we have reached here, it means we have already found
|
||||||
|
# a workable ID for that machine, so there is no need to continue
|
||||||
|
break
|
||||||
|
|
||||||
return result_metadata
|
return result_metadata
|
||||||
|
|
||||||
@ -818,10 +828,32 @@ class XmlMaterialProfile(InstanceContainer):
|
|||||||
#
|
#
|
||||||
# This loads the mapping from a file.
|
# This loads the mapping from a file.
|
||||||
@classmethod
|
@classmethod
|
||||||
def getProductIdMap(cls) -> Dict[str, str]:
|
def getProductIdMap(cls) -> Dict[str, List[str]]:
|
||||||
product_to_id_file = os.path.join(os.path.dirname(sys.modules[cls.__module__].__file__), "product_to_id.json")
|
product_to_id_file = os.path.join(os.path.dirname(sys.modules[cls.__module__].__file__), "product_to_id.json")
|
||||||
with open(product_to_id_file) as f:
|
with open(product_to_id_file) as f:
|
||||||
return json.load(f)
|
product_to_id_map = json.load(f)
|
||||||
|
|
||||||
|
# generate a few more combinations so it can be smart about finding IDs
|
||||||
|
product_to_id_map = {key: [value] for key, value in product_to_id_map.items()}
|
||||||
|
for name, id_list in product_to_id_map.items():
|
||||||
|
name_parts = name.split(" ")
|
||||||
|
merged_name_parts = []
|
||||||
|
for part in name_parts:
|
||||||
|
if len(part) == 0:
|
||||||
|
continue
|
||||||
|
if len(merged_name_parts) == 0:
|
||||||
|
merged_name_parts.append(part.lower())
|
||||||
|
continue
|
||||||
|
if part.isdigit():
|
||||||
|
# for names with digit(s) such as Ultimaker 3 Extended, we generate an ID like
|
||||||
|
# "ultimaker3_extended", ignoring the space between "Ultimaker" and "3".
|
||||||
|
merged_name_parts[-1] = merged_name_parts[-1] + part.lower()
|
||||||
|
|
||||||
|
generated_id = "_".join(merged_name_parts)
|
||||||
|
if generated_id not in id_list:
|
||||||
|
id_list.append(generated_id)
|
||||||
|
|
||||||
|
return product_to_id_map
|
||||||
|
|
||||||
## Parse the value of the "material compatible" property.
|
## Parse the value of the "material compatible" property.
|
||||||
@classmethod
|
@classmethod
|
||||||
|
Loading…
x
Reference in New Issue
Block a user