Browse Source

Merge pull request #9232 from Ultimaker/CURA-7615_store_metadata

Retain metadata from 3MF files through save/load loops
Remco Burema 4 years ago
parent
commit
929149bf4e

+ 1 - 0
cura/UI/PrintInformation.py

@@ -301,6 +301,7 @@ class PrintInformation(QObject):
         if self._base_name == "":
         if self._base_name == "":
             self._job_name = self.UNTITLED_JOB_NAME
             self._job_name = self.UNTITLED_JOB_NAME
             self._is_user_specified_job_name = False
             self._is_user_specified_job_name = False
+            self._application.getController().getScene().clearMetaData()
             self.jobNameChanged.emit()
             self.jobNameChanged.emit()
             return
             return
 
 

+ 11 - 4
plugins/3MFReader/ThreeMFReader.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Ultimaker B.V.
+# Copyright (c) 2021 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.path
 import os.path
@@ -163,9 +163,9 @@ class ThreeMFReader(MeshReader):
                 um_node.callDecoration("getStack").getTop().setDefinition(definition_id)
                 um_node.callDecoration("getStack").getTop().setDefinition(definition_id)
 
 
             setting_container = um_node.callDecoration("getStack").getTop()
             setting_container = um_node.callDecoration("getStack").getTop()
-
+            known_setting_keys = um_node.callDecoration("getStack").getAllKeys()
             for key in settings:
             for key in settings:
-                setting_value = settings[key]
+                setting_value = settings[key].value
 
 
                 # Extruder_nr is a special case.
                 # Extruder_nr is a special case.
                 if key == "extruder_nr":
                 if key == "extruder_nr":
@@ -175,7 +175,10 @@ class ThreeMFReader(MeshReader):
                     else:
                     else:
                         Logger.log("w", "Unable to find extruder in position %s", setting_value)
                         Logger.log("w", "Unable to find extruder in position %s", setting_value)
                     continue
                     continue
-                setting_container.setProperty(key, "value", setting_value)
+                if key in known_setting_keys:
+                    setting_container.setProperty(key, "value", setting_value)
+                else:
+                    um_node.metadata[key] = settings[key]
 
 
         if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None:
         if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None:
             if len(um_node.getAllChildren()) == 1:
             if len(um_node.getAllChildren()) == 1:
@@ -206,6 +209,10 @@ class ThreeMFReader(MeshReader):
             parser = Savitar.ThreeMFParser()
             parser = Savitar.ThreeMFParser()
             scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read())
             scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read())
             self._unit = scene_3mf.getUnit()
             self._unit = scene_3mf.getUnit()
+
+            for key, value in scene_3mf.getMetadata().items():
+                CuraApplication.getInstance().getController().getScene().setMetaDataEntry(key, value)
+
             for node in scene_3mf.getSceneNodes():
             for node in scene_3mf.getSceneNodes():
                 um_node = self._convertSavitarNodeToUMNode(node, file_name)
                 um_node = self._convertSavitarNodeToUMNode(node, file_name)
                 if um_node is None:
                 if um_node is None:

+ 22 - 1
plugins/3MFWriter/ThreeMFWriter.py

@@ -14,6 +14,7 @@ from cura.CuraApplication import CuraApplication
 import Savitar
 import Savitar
 
 
 import numpy
 import numpy
+import datetime
 
 
 MYPY = False
 MYPY = False
 try:
 try:
@@ -108,7 +109,11 @@ class ThreeMFWriter(MeshWriter):
 
 
             # Get values for all changed settings & save them.
             # Get values for all changed settings & save them.
             for key in changed_setting_keys:
             for key in changed_setting_keys:
-                savitar_node.setSetting(key, str(stack.getProperty(key, "value")))
+                savitar_node.setSetting("cura:" + key, str(stack.getProperty(key, "value")))
+
+        # Store the metadata.
+        for key, value in um_node.metadata.items():
+            savitar_node.setSetting(key, value)
 
 
         for child_node in um_node.getChildren():
         for child_node in um_node.getChildren():
             # only save the nodes on the active build plate
             # only save the nodes on the active build plate
@@ -145,6 +150,22 @@ class ThreeMFWriter(MeshWriter):
             model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel")
             model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel")
 
 
             savitar_scene = Savitar.Scene()
             savitar_scene = Savitar.Scene()
+
+            metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData()
+
+            for key, value in metadata_to_store.items():
+                savitar_scene.setMetaDataEntry(key, value)
+
+            current_time_string = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+            if "Application" not in metadata_to_store:
+                # This might sound a bit strange, but this field should store the original application that created
+                # the 3mf. So if it was already set, leave it to whatever it was.
+                savitar_scene.setMetaDataEntry("Application", CuraApplication.getInstance().getApplicationDisplayName())
+            if "CreationDate" not in metadata_to_store:
+                savitar_scene.setMetaDataEntry("CreationDate", current_time_string)
+
+            savitar_scene.setMetaDataEntry("ModificationDate", current_time_string)
+
             transformation_matrix = Matrix()
             transformation_matrix = Matrix()
             transformation_matrix._data[1, 1] = 0
             transformation_matrix._data[1, 1] = 0
             transformation_matrix._data[1, 2] = -1
             transformation_matrix._data[1, 2] = -1