mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Move parse/write responsibility of copy/paste to 3MFWriter/3MFReader
CURA-7913
This commit is contained in:
parent
cc1b42e2fa
commit
f8b3fb3d67
3 changed files with 48 additions and 34 deletions
|
@ -7,8 +7,6 @@ from PyQt6.QtCore import QObject, QUrl, QMimeData
|
||||||
from PyQt6.QtGui import QDesktopServices
|
from PyQt6.QtGui import QDesktopServices
|
||||||
from PyQt6.QtWidgets import QApplication
|
from PyQt6.QtWidgets import QApplication
|
||||||
|
|
||||||
import pySavitar as Savitar
|
|
||||||
|
|
||||||
from UM.Event import CallFunctionEvent
|
from UM.Event import CallFunctionEvent
|
||||||
from UM.FlameProfiler import pyqtSlot
|
from UM.FlameProfiler import pyqtSlot
|
||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
|
@ -194,18 +192,13 @@ class CuraActions(QObject):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def copy(self) -> None:
|
def copy(self) -> None:
|
||||||
# Convert all selected objects to a Savitar scene
|
|
||||||
savitar_scene = Savitar.Scene()
|
|
||||||
mesh_writer = cura.CuraApplication.CuraApplication.getInstance().getMeshFileHandler().getWriter("3MFWriter")
|
mesh_writer = cura.CuraApplication.CuraApplication.getInstance().getMeshFileHandler().getWriter("3MFWriter")
|
||||||
for scene_node in Selection.getAllSelectedObjects():
|
|
||||||
savitar_node = mesh_writer._convertUMNodeToSavitarNode(scene_node)
|
|
||||||
savitar_scene.addSceneNode(savitar_node)
|
|
||||||
|
|
||||||
# Convert the scene to a string
|
# Get the selected nodes
|
||||||
parser = Savitar.ThreeMFParser()
|
selected_objects = Selection.getAllSelectedObjects()
|
||||||
scene_string = parser.sceneToString(savitar_scene)
|
# Serialize the nodes to a string
|
||||||
|
scene_string = mesh_writer.sceneNodesToString(selected_objects)
|
||||||
# Copy the scene to the clipboard
|
# Put the string on the clipboard
|
||||||
QApplication.clipboard().setText(scene_string)
|
QApplication.clipboard().setText(scene_string)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -214,17 +207,9 @@ class CuraActions(QObject):
|
||||||
|
|
||||||
# Parse the scene from the clipboard
|
# Parse the scene from the clipboard
|
||||||
scene_string = QApplication.clipboard().text()
|
scene_string = QApplication.clipboard().text()
|
||||||
parser = Savitar.ThreeMFParser()
|
|
||||||
scene = parser.parse(scene_string)
|
|
||||||
|
|
||||||
# Convert the scene to scene nodes
|
|
||||||
nodes = []
|
|
||||||
mesh_reader = application.getMeshFileHandler().getReaderForFile(".3mf")
|
mesh_reader = application.getMeshFileHandler().getReaderForFile(".3mf")
|
||||||
for savitar_node in scene.getSceneNodes():
|
nodes = mesh_reader.stringToSceneNodes(scene_string)
|
||||||
scene_node = mesh_reader._convertSavitarNodeToUMNode(savitar_node, "file_name")
|
|
||||||
if scene_node is None:
|
|
||||||
continue
|
|
||||||
nodes.append(scene_node)
|
|
||||||
|
|
||||||
# Find all fixed nodes, these are the nodes that should be avoided when arranging
|
# Find all fixed nodes, these are the nodes that should be avoided when arranging
|
||||||
fixed_nodes = []
|
fixed_nodes = []
|
||||||
|
|
|
@ -56,7 +56,8 @@ class ThreeMFReader(MeshReader):
|
||||||
def emptyFileHintSet(self) -> bool:
|
def emptyFileHintSet(self) -> bool:
|
||||||
return self._empty_project
|
return self._empty_project
|
||||||
|
|
||||||
def _createMatrixFromTransformationString(self, transformation: str) -> Matrix:
|
@staticmethod
|
||||||
|
def _createMatrixFromTransformationString(transformation: str) -> Matrix:
|
||||||
if transformation == "":
|
if transformation == "":
|
||||||
return Matrix()
|
return Matrix()
|
||||||
|
|
||||||
|
@ -90,7 +91,8 @@ class ThreeMFReader(MeshReader):
|
||||||
|
|
||||||
return temp_mat
|
return temp_mat
|
||||||
|
|
||||||
def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
@staticmethod
|
||||||
|
def _convertSavitarNodeToUMNode(savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
||||||
"""Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
|
"""Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
|
||||||
|
|
||||||
:returns: Scene node.
|
:returns: Scene node.
|
||||||
|
@ -119,7 +121,7 @@ class ThreeMFReader(MeshReader):
|
||||||
pass
|
pass
|
||||||
um_node.setName(node_name)
|
um_node.setName(node_name)
|
||||||
um_node.setId(node_id)
|
um_node.setId(node_id)
|
||||||
transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
|
transformation = ThreeMFReader._createMatrixFromTransformationString(savitar_node.getTransformation())
|
||||||
um_node.setTransformation(transformation)
|
um_node.setTransformation(transformation)
|
||||||
mesh_builder = MeshBuilder()
|
mesh_builder = MeshBuilder()
|
||||||
|
|
||||||
|
@ -138,7 +140,7 @@ class ThreeMFReader(MeshReader):
|
||||||
um_node.setMeshData(mesh_data)
|
um_node.setMeshData(mesh_data)
|
||||||
|
|
||||||
for child in savitar_node.getChildren():
|
for child in savitar_node.getChildren():
|
||||||
child_node = self._convertSavitarNodeToUMNode(child)
|
child_node = ThreeMFReader._convertSavitarNodeToUMNode(child)
|
||||||
if child_node:
|
if child_node:
|
||||||
um_node.addChild(child_node)
|
um_node.addChild(child_node)
|
||||||
|
|
||||||
|
@ -214,7 +216,7 @@ class ThreeMFReader(MeshReader):
|
||||||
CuraApplication.getInstance().getController().getScene().setMetaDataEntry(key, value)
|
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 = ThreeMFReader._convertSavitarNodeToUMNode(node, file_name)
|
||||||
if um_node is None:
|
if um_node is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -305,3 +307,18 @@ class ThreeMFReader(MeshReader):
|
||||||
|
|
||||||
scale = conversion_to_mm[unit]
|
scale = conversion_to_mm[unit]
|
||||||
return Vector(scale, scale, scale)
|
return Vector(scale, scale, scale)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def stringToSceneNodes(scene_string: str) -> List[SceneNode]:
|
||||||
|
parser = Savitar.ThreeMFParser()
|
||||||
|
scene = parser.parse(scene_string)
|
||||||
|
|
||||||
|
# Convert the scene to scene nodes
|
||||||
|
nodes = []
|
||||||
|
for savitar_node in scene.getSceneNodes():
|
||||||
|
scene_node = ThreeMFReader._convertSavitarNodeToUMNode(savitar_node, "file_name")
|
||||||
|
if scene_node is None:
|
||||||
|
continue
|
||||||
|
nodes.append(scene_node)
|
||||||
|
|
||||||
|
return nodes
|
||||||
|
|
|
@ -55,11 +55,12 @@ class ThreeMFWriter(MeshWriter):
|
||||||
"cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
|
"cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
|
||||||
}
|
}
|
||||||
|
|
||||||
self._unit_matrix_string = self._convertMatrixToString(Matrix())
|
self._unit_matrix_string = ThreeMFWriter._convertMatrixToString(Matrix())
|
||||||
self._archive: Optional[zipfile.ZipFile] = None
|
self._archive: Optional[zipfile.ZipFile] = None
|
||||||
self._store_archive = False
|
self._store_archive = False
|
||||||
|
|
||||||
def _convertMatrixToString(self, matrix):
|
@staticmethod
|
||||||
|
def _convertMatrixToString(matrix):
|
||||||
result = ""
|
result = ""
|
||||||
result += str(matrix._data[0, 0]) + " "
|
result += str(matrix._data[0, 0]) + " "
|
||||||
result += str(matrix._data[1, 0]) + " "
|
result += str(matrix._data[1, 0]) + " "
|
||||||
|
@ -83,7 +84,8 @@ class ThreeMFWriter(MeshWriter):
|
||||||
"""
|
"""
|
||||||
self._store_archive = store_archive
|
self._store_archive = store_archive
|
||||||
|
|
||||||
def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()):
|
@staticmethod
|
||||||
|
def _convertUMNodeToSavitarNode(um_node, transformation=Matrix()):
|
||||||
"""Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
"""Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
||||||
|
|
||||||
:returns: Uranium Scene node.
|
:returns: Uranium Scene node.
|
||||||
|
@ -100,7 +102,7 @@ class ThreeMFWriter(MeshWriter):
|
||||||
|
|
||||||
node_matrix = um_node.getLocalTransformation()
|
node_matrix = um_node.getLocalTransformation()
|
||||||
|
|
||||||
matrix_string = self._convertMatrixToString(node_matrix.preMultiply(transformation))
|
matrix_string = ThreeMFWriter._convertMatrixToString(node_matrix.preMultiply(transformation))
|
||||||
|
|
||||||
savitar_node.setTransformation(matrix_string)
|
savitar_node.setTransformation(matrix_string)
|
||||||
mesh_data = um_node.getMeshData()
|
mesh_data = um_node.getMeshData()
|
||||||
|
@ -133,7 +135,7 @@ class ThreeMFWriter(MeshWriter):
|
||||||
# only save the nodes on the active build plate
|
# only save the nodes on the active build plate
|
||||||
if child_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr:
|
if child_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr:
|
||||||
continue
|
continue
|
||||||
savitar_child_node = self._convertUMNodeToSavitarNode(child_node)
|
savitar_child_node = ThreeMFWriter._convertUMNodeToSavitarNode(child_node)
|
||||||
if savitar_child_node is not None:
|
if savitar_child_node is not None:
|
||||||
savitar_node.addChild(savitar_child_node)
|
savitar_node.addChild(savitar_child_node)
|
||||||
|
|
||||||
|
@ -221,7 +223,7 @@ class ThreeMFWriter(MeshWriter):
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if node == root_node:
|
if node == root_node:
|
||||||
for root_child in node.getChildren():
|
for root_child in node.getChildren():
|
||||||
savitar_node = self._convertUMNodeToSavitarNode(root_child, transformation_matrix)
|
savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(root_child, transformation_matrix)
|
||||||
if savitar_node:
|
if savitar_node:
|
||||||
savitar_scene.addSceneNode(savitar_node)
|
savitar_scene.addSceneNode(savitar_node)
|
||||||
else:
|
else:
|
||||||
|
@ -309,3 +311,13 @@ class ThreeMFWriter(MeshWriter):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sceneNodesToString(scene_nodes: [SceneNode]) -> str:
|
||||||
|
savitar_scene = Savitar.Scene()
|
||||||
|
for scene_node in scene_nodes:
|
||||||
|
savitar_node = ThreeMFWriter._convertUMNodeToSavitarNode(scene_node)
|
||||||
|
savitar_scene.addSceneNode(savitar_node)
|
||||||
|
parser = Savitar.ThreeMFParser()
|
||||||
|
scene_string = parser.sceneToString(savitar_scene)
|
||||||
|
return scene_string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue