Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorj.delarago <joeydelarago@gmail.com>2022-05-30 18:29:59 +0300
committerj.delarago <joeydelarago@gmail.com>2022-05-30 18:29:59 +0300
commit21d59e93492dc66198312bdd8dd17d91bc44d252 (patch)
treef5544f4323eebfd3423d068d9253d5574d26ffa5
parent596c24657d39804c8bc94e6e8f99436115d7e411 (diff)
Write active material metadata to ufp when saving.CURA-8610_save_package_metadata
Add function to fetch package_id using only information from XmlMaterialProfile material container. The only piece of information associating the material container and the package together is the file_name. To find the package that owns a material we have to search each of the material package paths. It would be great to find a cleaner solution (preferable one that doesn't require invalidating the cached containers). CURA-8610
-rw-r--r--cura/CuraPackageManager.py20
-rw-r--r--plugins/UFPWriter/UFPWriter.py61
-rw-r--r--plugins/XmlMaterialProfile/XmlMaterialProfile.py3
3 files changed, 67 insertions, 17 deletions
diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py
index 17d6832ac6..b23422fbbd 100644
--- a/cura/CuraPackageManager.py
+++ b/cura/CuraPackageManager.py
@@ -1,5 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+import os
from typing import Any, cast, Dict, List, Set, Tuple, TYPE_CHECKING, Optional
@@ -51,6 +52,25 @@ class CuraPackageManager(PackageManager):
super().initialize()
+ def getMaterialFilePackageId(self, file_name: str, guid: str) -> str:
+ """Get the id of the material package that contains file_name"""
+ for material_package in [f for f in os.scandir(self._installation_dirs_dict["materials"]) if f.is_dir()]:
+ package_id = material_package.name
+
+ for root, _, file_names in os.walk(material_package.path):
+ if file_name not in file_names:
+ #File with the name we are looking for is not in this directory
+ continue
+
+ with open(root + "/" + file_name, encoding="utf-8") as f:
+ # Make sure the file we found has the same guid as our material
+ # Parsing this xml would be better but the namespace is needed to search it.
+ if guid in f.read():
+ return package_id
+ continue
+
+
+
def getMachinesUsingPackage(self, package_id: str) -> Tuple[List[Tuple[GlobalStack, str, str]], List[Tuple[GlobalStack, str, str]]]:
"""Returns a list of where the package is used
diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py
index 52dab1efc7..59067b1932 100644
--- a/plugins/UFPWriter/UFPWriter.py
+++ b/plugins/UFPWriter/UFPWriter.py
@@ -16,13 +16,14 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
from UM.PluginRegistry import PluginRegistry # To get the g-code writer.
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
-from UM.Scene.SceneNode import SceneNode
from cura.CuraApplication import CuraApplication
+from cura.CuraPackageManager import CuraPackageManager
from cura.Utils.Threading import call_on_qt_thread
from UM.i18n import i18nCatalog
METADATA_OBJECTS_PATH = "metadata/objects"
+METADATA_MATERIALS_PATH = "metadata/packages"
catalog = i18nCatalog("cura")
@@ -49,7 +50,7 @@ class UFPWriter(MeshWriter):
archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)
try:
- self._writeObjectList(archive)
+ self._writeMetadata(archive)
# Store the g-code from the scene.
archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
@@ -163,30 +164,56 @@ class UFPWriter(MeshWriter):
return True
@staticmethod
- def _writeObjectList(archive):
- """Write a json list of object names to the METADATA_OBJECTS_PATH metadata field
+ def _writeMetadata(archive: VirtualFile):
+ material_metadata = UFPWriter._getMaterialPackageMetadata()
+ object_metadata = UFPWriter._getObjectMetadata()
- To retrieve, use: `archive.getMetadata(METADATA_OBJECTS_PATH)`
+ data = {METADATA_MATERIALS_PATH: material_metadata,
+ METADATA_OBJECTS_PATH: object_metadata}
+
+ archive.setMetadata(data)
+
+ @staticmethod
+ def _getObjectMetadata() -> List[Dict[str, str]]:
+ """Get object metadata to write for a Node.
+
+ :return: List of object metadata dictionaries.
"""
+ metadata = []
objects_model = CuraApplication.getInstance().getObjectsModel()
- object_metas = []
for item in objects_model.items:
- object_metas.extend(UFPWriter._getObjectMetadata(item["node"]))
+ for node in DepthFirstIterator(item["node"]):
+ if node.getMeshData() is not None and not node.callDecoration("isNonPrintingMesh"):
+ metadata.extend({"name": node.getName()})
- data = {METADATA_OBJECTS_PATH: object_metas}
- archive.setMetadata(data)
+ return metadata
@staticmethod
- def _getObjectMetadata(node: SceneNode) -> List[Dict[str, str]]:
- """Get object metadata to write for a Node.
+ def _getMaterialPackageMetadata() -> List[Dict[str, str]]:
+ """Get metadata for installed materials in active extruder stack, this does not include bundled materials.
- :return: List of object metadata dictionaries.
- Might contain > 1 element in case of a group node.
- Might be empty in case of nonPrintingMesh
+ :return: List of material metadata dictionaries.
"""
+ metadata = []
+
+ package_manager = cast(CuraPackageManager, CuraApplication.getInstance().getPackageManager())
+
+ for extruder in CuraApplication.getInstance().getExtruderManager().getActiveExtruderStacks():
+ package_id = package_manager.getMaterialFilePackageId(extruder.material.getFileName(), extruder.material.getMetaDataEntry("GUID"))
+ package_data = package_manager.getInstalledPackageInfo(package_id)
+
+ if package_data.get("is_bundled"):
+ continue
+
+ material_metadata = {"id": package_id,
+ "display_name": package_data.get("display_name"),
+ "website": package_data.get("website"),
+ "package_version": package_data.get("package_version"),
+ "sdk_version_semver": package_data.get("package_version_semver")}
+
+ metadata.append(material_metadata)
+
+ return metadata
- return [{"name": item.getName()}
- for item in DepthFirstIterator(node)
- if item.getMeshData() is not None and not item.callDecoration("isNonPrintingMesh")]
diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
index 1b88272d49..d1da10399a 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
@@ -343,6 +343,9 @@ class XmlMaterialProfile(InstanceContainer):
return stream.getvalue().decode("utf-8")
+ def getFileName(self):
+ return self.getMetaDataEntry("base_file") + ".xml.fdm_material"
+
# Recursively resolve loading inherited files
def _resolveInheritance(self, file_name):
xml = self._loadFile(file_name)