From e69edae9aa269405dc9bf9d84a9cd8bbf22fa37e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 23 Dec 2020 13:32:27 +0100 Subject: [PATCH 1/7] Store application name when saving 3MF file CURA-7615 --- plugins/3MFWriter/ThreeMFWriter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 6c02935080..7b74bee22e 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -145,6 +145,7 @@ 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") savitar_scene = Savitar.Scene() + savitar_scene.setMetaDataEntry("Application", CuraApplication.getInstance().getApplicationDisplayName()) transformation_matrix = Matrix() transformation_matrix._data[1, 1] = 0 transformation_matrix._data[1, 2] = -1 From f9d0da7a1286ce250fcfacd6ac866c7de5386684 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 23 Dec 2020 13:42:40 +0100 Subject: [PATCH 2/7] Store creation & Modification date CURA-7615 --- plugins/3MFWriter/ThreeMFWriter.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 7b74bee22e..741b82a422 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -14,6 +14,7 @@ from cura.CuraApplication import CuraApplication import Savitar import numpy +import datetime MYPY = False try: @@ -145,7 +146,18 @@ 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") savitar_scene = Savitar.Scene() - savitar_scene.setMetaDataEntry("Application", CuraApplication.getInstance().getApplicationDisplayName()) + + metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData() + 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._data[1, 1] = 0 transformation_matrix._data[1, 2] = -1 From f338acd4f33f8ead0d8de20965c2705274b04b5c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 23 Dec 2020 13:49:52 +0100 Subject: [PATCH 3/7] Read & write all generic metadata items from 3mf CURA-7615 --- plugins/3MFReader/ThreeMFReader.py | 4 ++++ plugins/3MFWriter/ThreeMFWriter.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 2e3f5630c1..68d0aee81b 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -201,6 +201,10 @@ class ThreeMFReader(MeshReader): parser = Savitar.ThreeMFParser() scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read()) 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(): um_node = self._convertSavitarNodeToUMNode(node, file_name) if um_node is None: diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 741b82a422..99659817a5 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -148,6 +148,10 @@ class ThreeMFWriter(MeshWriter): 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 From 7f27ff543202978f2176e125ae5e0bfb46a2cc2a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 23 Dec 2020 14:08:59 +0100 Subject: [PATCH 4/7] Reset scene metadata if the buildplate was cleared CURA-7615 --- cura/UI/PrintInformation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/UI/PrintInformation.py b/cura/UI/PrintInformation.py index 22710165b3..10318b3a8b 100644 --- a/cura/UI/PrintInformation.py +++ b/cura/UI/PrintInformation.py @@ -301,6 +301,7 @@ class PrintInformation(QObject): if self._base_name == "": self._job_name = self.UNTITLED_JOB_NAME self._is_user_specified_job_name = False + self._application.getController().getScene().clearMetaData() self.jobNameChanged.emit() return From f442417ac6a5c5acbb2210ece649bab6c8840d84 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 23 Dec 2020 16:31:25 +0100 Subject: [PATCH 5/7] Dont try to set unknown settings as per object settings when loading 3mf CURA-7615 --- plugins/3MFReader/ThreeMFReader.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 68d0aee81b..ff69e0f1a3 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -159,7 +159,7 @@ class ThreeMFReader(MeshReader): um_node.callDecoration("getStack").getTop().setDefinition(definition_id) setting_container = um_node.callDecoration("getStack").getTop() - + known_setting_keys = um_node.callDecoration("getStack").getAllKeys() for key in settings: setting_value = settings[key] @@ -171,7 +171,10 @@ class ThreeMFReader(MeshReader): else: Logger.log("w", "Unable to find extruder in position %s", setting_value) continue - setting_container.setProperty(key, "value", setting_value) + if key in known_setting_keys: + setting_container.setProperty(key, "value", setting_value) + else: + Logger.log("w", "Unable to set setting %s", key) if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None: if len(um_node.getAllChildren()) == 1: From 06086dfaaf9f039175e9b94f8a939c8eeec77f16 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 8 Feb 2021 15:07:33 +0100 Subject: [PATCH 6/7] Fix reading per-object settings from 3MF object resources This metadata has been changed to contain other information. Readers of information from 3MF need to adjust their stance too to filter out the information they need from the metadata of the metadata. Contributes to issue CURA-7615. --- plugins/3MFReader/ThreeMFReader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index ff69e0f1a3..7a063467d8 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -161,7 +161,7 @@ class ThreeMFReader(MeshReader): setting_container = um_node.callDecoration("getStack").getTop() known_setting_keys = um_node.callDecoration("getStack").getAllKeys() for key in settings: - setting_value = settings[key] + setting_value = settings[key].value # Extruder_nr is a special case. if key == "extruder_nr": From b815d63096b5c10740a3d79b63df14dd89ec1111 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 8 Feb 2021 17:37:38 +0100 Subject: [PATCH 7/7] Add cura: namespace before setting keys, and store the rest in um_node.metadata This retains per-node metadata entries. Contributes to issue CURA-7615. --- plugins/3MFReader/ThreeMFReader.py | 4 ++-- plugins/3MFWriter/ThreeMFWriter.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 669bee8f40..37ca1e98aa 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/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. import os.path @@ -178,7 +178,7 @@ class ThreeMFReader(MeshReader): if key in known_setting_keys: setting_container.setProperty(key, "value", setting_value) else: - Logger.log("w", "Unable to set setting %s", key) + um_node.metadata[key] = settings[key] if len(um_node.getChildren()) > 0 and um_node.getMeshData() is None: if len(um_node.getAllChildren()) == 1: diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 99659817a5..c85eca88bf 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -109,7 +109,11 @@ class ThreeMFWriter(MeshWriter): # Get values for all changed settings & save them. 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(): # only save the nodes on the active build plate