mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Write active material metadata to ufp when saving.
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
This commit is contained in:
parent
596c24657d
commit
21d59e9349
3 changed files with 69 additions and 19 deletions
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# 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
|
from typing import Any, cast, Dict, List, Set, Tuple, TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
@ -51,6 +52,25 @@ class CuraPackageManager(PackageManager):
|
||||||
|
|
||||||
super().initialize()
|
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]]]:
|
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
|
"""Returns a list of where the package is used
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,14 @@ from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||||
from UM.PluginRegistry import PluginRegistry # To get the g-code writer.
|
from UM.PluginRegistry import PluginRegistry # To get the g-code writer.
|
||||||
|
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Scene.SceneNode import SceneNode
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.CuraPackageManager import CuraPackageManager
|
||||||
from cura.Utils.Threading import call_on_qt_thread
|
from cura.Utils.Threading import call_on_qt_thread
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
METADATA_OBJECTS_PATH = "metadata/objects"
|
METADATA_OBJECTS_PATH = "metadata/objects"
|
||||||
|
METADATA_MATERIALS_PATH = "metadata/packages"
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ class UFPWriter(MeshWriter):
|
||||||
archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)
|
archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._writeObjectList(archive)
|
self._writeMetadata(archive)
|
||||||
|
|
||||||
# Store the g-code from the scene.
|
# Store the g-code from the scene.
|
||||||
archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
|
archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
|
||||||
|
@ -163,30 +164,56 @@ class UFPWriter(MeshWriter):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _writeObjectList(archive):
|
def _writeMetadata(archive: VirtualFile):
|
||||||
"""Write a json list of object names to the METADATA_OBJECTS_PATH metadata field
|
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}
|
||||||
|
|
||||||
objects_model = CuraApplication.getInstance().getObjectsModel()
|
|
||||||
object_metas = []
|
|
||||||
|
|
||||||
for item in objects_model.items:
|
|
||||||
object_metas.extend(UFPWriter._getObjectMetadata(item["node"]))
|
|
||||||
|
|
||||||
data = {METADATA_OBJECTS_PATH: object_metas}
|
|
||||||
archive.setMetadata(data)
|
archive.setMetadata(data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _getObjectMetadata(node: SceneNode) -> List[Dict[str, str]]:
|
def _getObjectMetadata() -> List[Dict[str, str]]:
|
||||||
"""Get object metadata to write for a Node.
|
"""Get object metadata to write for a Node.
|
||||||
|
|
||||||
:return: List of object metadata dictionaries.
|
:return: List of object metadata dictionaries.
|
||||||
Might contain > 1 element in case of a group node.
|
|
||||||
Might be empty in case of nonPrintingMesh
|
|
||||||
"""
|
"""
|
||||||
|
metadata = []
|
||||||
|
|
||||||
|
objects_model = CuraApplication.getInstance().getObjectsModel()
|
||||||
|
|
||||||
|
for item in objects_model.items:
|
||||||
|
for node in DepthFirstIterator(item["node"]):
|
||||||
|
if node.getMeshData() is not None and not node.callDecoration("isNonPrintingMesh"):
|
||||||
|
metadata.extend({"name": node.getName()})
|
||||||
|
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _getMaterialPackageMetadata() -> List[Dict[str, str]]:
|
||||||
|
"""Get metadata for installed materials in active extruder stack, this does not include bundled materials.
|
||||||
|
|
||||||
|
: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")]
|
|
||||||
|
|
|
@ -343,6 +343,9 @@ class XmlMaterialProfile(InstanceContainer):
|
||||||
|
|
||||||
return stream.getvalue().decode("utf-8")
|
return stream.getvalue().decode("utf-8")
|
||||||
|
|
||||||
|
def getFileName(self):
|
||||||
|
return self.getMetaDataEntry("base_file") + ".xml.fdm_material"
|
||||||
|
|
||||||
# Recursively resolve loading inherited files
|
# Recursively resolve loading inherited files
|
||||||
def _resolveInheritance(self, file_name):
|
def _resolveInheritance(self, file_name):
|
||||||
xml = self._loadFile(file_name)
|
xml = self._loadFile(file_name)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue