From ea935024cfae2cc6b376d1caa0a832d589bfb429 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 24 Aug 2018 13:02:06 +0200 Subject: [PATCH 1/5] Add materil xml file to UFP file CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index ceb9d79087..7c8b43a018 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -60,5 +60,43 @@ class UFPWriter(MeshWriter): else: Logger.log("d", "Thumbnail not created, cannot save it") + #Store the material. + application = Application.getInstance() + machine_manager = application.getMachineManager() + global_stack = machine_manager.activeMachine + container_registry = application.getContainerRegistry() + + archive.addContentType(extension="xml.fdm_material", mime_type="application/x-ultimaker-material-profile") + + added_materials = [] + for extruder_stack in global_stack.extruders.values(): + material = extruder_stack.material + material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" + material_file_name = "/Cura/" + material_file_name + + #Same material cannot be added + if material_file_name in added_materials: + continue + + material_file = archive.getStream(material_file_name) + material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) + + if not material_containers: + Logger.log("e", "Cannot find material container with id: %s", material.id) + return False + + material_container = material_containers[0] + try: + serialized_material = material_container.serialize() + except NotImplementedError: + Logger.log("e", "Unable serialize material container with id: %s", material.id) + return False + + material_file.write(serialized_material.encode("UTF-8")) + archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") + + + added_materials.append(material_file_name) + archive.close() - return True + return True \ No newline at end of file From 423f1210b013b268086c2edd4acf121bdde64710 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 27 Aug 2018 11:10:41 +0200 Subject: [PATCH 2/5] Catch erros and open the write stream only if the material cointaner is found CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 7c8b43a018..841d61a000 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -24,6 +24,8 @@ class UFPWriter(MeshWriter): self._snapshot = None Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot) + self._default_data_path ="/Cura/" + def _createSnapshot(self, *args): # must be called from the main thread because of OpenGL Logger.log("d", "Creating thumbnail image...") @@ -66,19 +68,24 @@ class UFPWriter(MeshWriter): global_stack = machine_manager.activeMachine container_registry = application.getContainerRegistry() - archive.addContentType(extension="xml.fdm_material", mime_type="application/x-ultimaker-material-profile") + material_extension = "xml.fdm_material" + material_mime_type = "application/x-ultimaker-material-profile" + + try: + archive.addContentType(extension=material_extension, mime_type=material_mime_type) + except: + Logger.log("w", "The material extension: %s was already added", material_extension) added_materials = [] for extruder_stack in global_stack.extruders.values(): material = extruder_stack.material material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" - material_file_name = "/Cura/" + material_file_name + material_file_name = self._default_data_path + material_file_name #Same material cannot be added if material_file_name in added_materials: continue - material_file = archive.getStream(material_file_name) material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) if not material_containers: @@ -92,10 +99,10 @@ class UFPWriter(MeshWriter): Logger.log("e", "Unable serialize material container with id: %s", material.id) return False + material_file = archive.getStream(material_file_name) material_file.write(serialized_material.encode("UTF-8")) archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") - added_materials.append(material_file_name) archive.close() From 939484bc9181f2b08a0c0f093c3ed7f4539a5364 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:25:34 +0200 Subject: [PATCH 3/5] Fix adding materials in UFP CURA-5555 - Store materials in virtual path "/Materials" - Correct material relationship type - Add origin for material relationship - Use MaterialManager instead of ContainerRegistry to get materials - Other minor changes --- plugins/UFPWriter/UFPWriter.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 841d61a000..49a6a36d68 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -24,8 +24,6 @@ class UFPWriter(MeshWriter): self._snapshot = None Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot) - self._default_data_path ="/Cura/" - def _createSnapshot(self, *args): # must be called from the main thread because of OpenGL Logger.log("d", "Creating thumbnail image...") @@ -62,17 +60,17 @@ class UFPWriter(MeshWriter): else: Logger.log("d", "Thumbnail not created, cannot save it") - #Store the material. + # Store the material. application = Application.getInstance() machine_manager = application.getMachineManager() + material_manager = application.getMaterialManager() global_stack = machine_manager.activeMachine - container_registry = application.getContainerRegistry() material_extension = "xml.fdm_material" material_mime_type = "application/x-ultimaker-material-profile" try: - archive.addContentType(extension=material_extension, mime_type=material_mime_type) + archive.addContentType(extension = material_extension, mime_type = material_mime_type) except: Logger.log("w", "The material extension: %s was already added", material_extension) @@ -80,30 +78,32 @@ class UFPWriter(MeshWriter): for extruder_stack in global_stack.extruders.values(): material = extruder_stack.material material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" - material_file_name = self._default_data_path + material_file_name + material_file_name = "/Materials/" + material_file_name #Same material cannot be added if material_file_name in added_materials: continue - material_containers = container_registry.findContainers(id=material.getMetaDataEntry("base_file")) - - if not material_containers: - Logger.log("e", "Cannot find material container with id: %s", material.id) + material_root_id = material.getMetaDataEntry("base_file") + material_group = material_manager.getMaterialGroup(material_root_id) + if material_group is None: + Logger.log("e", "Cannot find material container with root id [%s]", material_root_id) return False - material_container = material_containers[0] + material_container = material_group.root_material_node try: serialized_material = material_container.serialize() except NotImplementedError: - Logger.log("e", "Unable serialize material container with id: %s", material.id) + Logger.log("e", "Unable serialize material container with root id: %s", material_root_id) return False material_file = archive.getStream(material_file_name) material_file.write(serialized_material.encode("UTF-8")) - archive.addRelation(virtual_path=material_file_name,relation_type="http://schemas.ultimaker.org/package/2018/relationships/xml.fdm_material") + archive.addRelation(virtual_path = material_file_name, + relation_type = "http://schemas.ultimaker.org/package/2018/relationships/material", + origin = "/3D/model.gcode") added_materials.append(material_file_name) archive.close() - return True \ No newline at end of file + return True From 8f5aa82bdb98e8df2cb6c89f061545f3f0396afc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:33:18 +0200 Subject: [PATCH 4/5] Fix adding materials in UFP CURA-5555 Need to use getContainer() for a MaterialNode. --- plugins/UFPWriter/UFPWriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 49a6a36d68..d838aaef36 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -90,7 +90,7 @@ class UFPWriter(MeshWriter): Logger.log("e", "Cannot find material container with root id [%s]", material_root_id) return False - material_container = material_group.root_material_node + material_container = material_group.root_material_node.getContainer() try: serialized_material = material_container.serialize() except NotImplementedError: From 570d0715eda45a1ec4caf05f143171cdd208cb9c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 29 Aug 2018 17:33:51 +0200 Subject: [PATCH 5/5] Add call_on_qt_thread to UFPWriter.write() CURA-5555 --- plugins/UFPWriter/UFPWriter.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index d838aaef36..a85ee489cb 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -13,6 +13,7 @@ from UM.PluginRegistry import PluginRegistry #To get the g-code writer. from PyQt5.QtCore import QBuffer from cura.Snapshot import Snapshot +from cura.Utils.Threading import call_on_qt_thread from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -29,6 +30,11 @@ class UFPWriter(MeshWriter): Logger.log("d", "Creating thumbnail image...") self._snapshot = Snapshot.snapshot(width = 300, height = 300) + # This needs to be called on the main thread (Qt thread) because the serialization of material containers can + # trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the + # Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled + # by the Job class. + @call_on_qt_thread def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode): archive = VirtualFile() archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)