mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 14:37:29 -06:00
Convert doxygen to rst for 3MFReader/Writer and AMFReader
This commit is contained in:
parent
679739d09d
commit
8f3827d5ae
6 changed files with 95 additions and 64 deletions
|
@ -32,8 +32,9 @@ except ImportError:
|
|||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
|
||||
class ThreeMFReader(MeshReader):
|
||||
"""Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
@ -55,13 +56,17 @@ class ThreeMFReader(MeshReader):
|
|||
return Matrix()
|
||||
|
||||
split_transformation = transformation.split()
|
||||
## Transformation is saved as:
|
||||
## M00 M01 M02 0.0
|
||||
## M10 M11 M12 0.0
|
||||
## M20 M21 M22 0.0
|
||||
## M30 M31 M32 1.0
|
||||
## We switch the row & cols as that is how everyone else uses matrices!
|
||||
temp_mat = Matrix()
|
||||
"""Transformation is saved as:
|
||||
M00 M01 M02 0.0
|
||||
|
||||
M10 M11 M12 0.0
|
||||
|
||||
M20 M21 M22 0.0
|
||||
|
||||
M30 M31 M32 1.0
|
||||
We switch the row & cols as that is how everyone else uses matrices!
|
||||
"""
|
||||
# Rotation & Scale
|
||||
temp_mat._data[0, 0] = split_transformation[0]
|
||||
temp_mat._data[1, 0] = split_transformation[1]
|
||||
|
@ -80,9 +85,11 @@ class ThreeMFReader(MeshReader):
|
|||
|
||||
return temp_mat
|
||||
|
||||
## Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
|
||||
# \returns Scene node.
|
||||
def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
||||
"""Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
|
||||
|
||||
:returns: Scene node.
|
||||
"""
|
||||
try:
|
||||
node_name = savitar_node.getName()
|
||||
node_id = savitar_node.getId()
|
||||
|
@ -243,15 +250,17 @@ class ThreeMFReader(MeshReader):
|
|||
|
||||
return result
|
||||
|
||||
## Create a scale vector based on a unit string.
|
||||
# The core spec defines the following:
|
||||
# * micron
|
||||
# * millimeter (default)
|
||||
# * centimeter
|
||||
# * inch
|
||||
# * foot
|
||||
# * meter
|
||||
def _getScaleFromUnit(self, unit: Optional[str]) -> Vector:
|
||||
"""Create a scale vector based on a unit string.
|
||||
|
||||
.. The core spec defines the following:
|
||||
* micron
|
||||
* millimeter (default)
|
||||
* centimeter
|
||||
* inch
|
||||
* foot
|
||||
* meter
|
||||
"""
|
||||
conversion_to_mm = {
|
||||
"micron": 0.001,
|
||||
"millimeter": 1,
|
||||
|
|
|
@ -89,8 +89,9 @@ class ExtruderInfo:
|
|||
self.intent_info = None
|
||||
|
||||
|
||||
## Base implementation for reading 3MF workspace files.
|
||||
class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
"""Base implementation for reading 3MF workspace files."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
@ -130,18 +131,21 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
self._old_new_materials = {}
|
||||
self._machine_info = None
|
||||
|
||||
## Get a unique name based on the old_id. This is different from directly calling the registry in that it caches results.
|
||||
# This has nothing to do with speed, but with getting consistent new naming for instances & objects.
|
||||
def getNewId(self, old_id: str):
|
||||
"""Get a unique name based on the old_id. This is different from directly calling the registry in that it caches results.
|
||||
|
||||
This has nothing to do with speed, but with getting consistent new naming for instances & objects.
|
||||
"""
|
||||
if old_id not in self._id_mapping:
|
||||
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
||||
return self._id_mapping[old_id]
|
||||
|
||||
## Separates the given file list into a list of GlobalStack files and a list of ExtruderStack files.
|
||||
#
|
||||
# In old versions, extruder stack files have the same suffix as container stack files ".stack.cfg".
|
||||
#
|
||||
def _determineGlobalAndExtruderStackFiles(self, project_file_name: str, file_list: List[str]) -> Tuple[str, List[str]]:
|
||||
"""Separates the given file list into a list of GlobalStack files and a list of ExtruderStack files.
|
||||
|
||||
In old versions, extruder stack files have the same suffix as container stack files ".stack.cfg".
|
||||
"""
|
||||
|
||||
archive = zipfile.ZipFile(project_file_name, "r")
|
||||
|
||||
global_stack_file_list = [name for name in file_list if name.endswith(self._global_stack_suffix)]
|
||||
|
@ -181,10 +185,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
return global_stack_file_list[0], extruder_stack_file_list
|
||||
|
||||
## read some info so we can make decisions
|
||||
# \param file_name
|
||||
# \param show_dialog In case we use preRead() to check if a file is a valid project file, we don't want to show a dialog.
|
||||
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
||||
"""Read some info so we can make decisions
|
||||
|
||||
:param file_name:
|
||||
:param show_dialog: In case we use preRead() to check if a file is a valid project file,
|
||||
we don't want to show a dialog.
|
||||
"""
|
||||
self._clearState()
|
||||
|
||||
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
||||
|
@ -578,15 +585,17 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
return WorkspaceReader.PreReadResult.accepted
|
||||
|
||||
## Read the project file
|
||||
# Add all the definitions / materials / quality changes that do not exist yet. Then it loads
|
||||
# all the stacks into the container registry. In some cases it will reuse the container for the global stack.
|
||||
# It handles old style project files containing .stack.cfg as well as new style project files
|
||||
# containing global.cfg / extruder.cfg
|
||||
#
|
||||
# \param file_name
|
||||
@call_on_qt_thread
|
||||
def read(self, file_name):
|
||||
"""Read the project file
|
||||
|
||||
Add all the definitions / materials / quality changes that do not exist yet. Then it loads
|
||||
all the stacks into the container registry. In some cases it will reuse the container for the global stack.
|
||||
It handles old style project files containing .stack.cfg as well as new style project files
|
||||
containing global.cfg / extruder.cfg
|
||||
|
||||
:param file_name:
|
||||
"""
|
||||
application = CuraApplication.getInstance()
|
||||
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
|
@ -856,19 +865,22 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
self._machine_info.quality_changes_info.name = quality_changes_name
|
||||
|
||||
## Helper class to create a new quality changes profile.
|
||||
#
|
||||
# This will then later be filled with the appropriate data.
|
||||
# \param quality_type The quality type of the new profile.
|
||||
# \param intent_category The intent category of the new profile.
|
||||
# \param name The name for the profile. This will later be made unique so
|
||||
# it doesn't need to be unique yet.
|
||||
# \param global_stack The global stack showing the configuration that the
|
||||
# profile should be created for.
|
||||
# \param extruder_stack The extruder stack showing the configuration that
|
||||
# the profile should be created for. If this is None, it will be created
|
||||
# for the global stack.
|
||||
def _createNewQualityChanges(self, quality_type: str, intent_category: Optional[str], name: str, global_stack: GlobalStack, extruder_stack: Optional[ExtruderStack]) -> InstanceContainer:
|
||||
"""Helper class to create a new quality changes profile.
|
||||
|
||||
This will then later be filled with the appropriate data.
|
||||
|
||||
:param quality_type: The quality type of the new profile.
|
||||
:param intent_category: The intent category of the new profile.
|
||||
:param name: The name for the profile. This will later be made unique so
|
||||
it doesn't need to be unique yet.
|
||||
:param global_stack: The global stack showing the configuration that the
|
||||
profile should be created for.
|
||||
:param extruder_stack: The extruder stack showing the configuration that
|
||||
the profile should be created for. If this is None, it will be created
|
||||
for the global stack.
|
||||
"""
|
||||
|
||||
container_registry = CuraApplication.getInstance().getContainerRegistry()
|
||||
base_id = global_stack.definition.getId() if extruder_stack is None else extruder_stack.getId()
|
||||
new_id = base_id + "_" + name
|
||||
|
@ -1077,9 +1089,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
def _getXmlProfileClass(self):
|
||||
return self._container_registry.getContainerForMimeType(MimeTypeDatabase.getMimeType("application/x-ultimaker-material-profile"))
|
||||
|
||||
## Get the list of ID's of all containers in a container stack by partially parsing it's serialized data.
|
||||
@staticmethod
|
||||
def _getContainerIdListFromSerialized(serialized):
|
||||
"""Get the list of ID's of all containers in a container stack by partially parsing it's serialized data."""
|
||||
|
||||
parser = ConfigParser(interpolation = None, empty_lines_in_values = False)
|
||||
parser.read_string(serialized)
|
||||
|
||||
|
|
|
@ -229,9 +229,10 @@ class WorkspaceDialog(QObject):
|
|||
if key in self._result:
|
||||
self._result[key] = strategy
|
||||
|
||||
## Close the backend: otherwise one could end up with "Slicing..."
|
||||
@pyqtSlot()
|
||||
def closeBackend(self):
|
||||
"""Close the backend: otherwise one could end up with "Slicing..."""
|
||||
|
||||
Application.getInstance().getBackend().close()
|
||||
|
||||
def setMaterialConflict(self, material_conflict):
|
||||
|
@ -283,8 +284,9 @@ class WorkspaceDialog(QObject):
|
|||
self.showDialogSignal.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
## Used to notify the dialog so the lock can be released.
|
||||
def notifyClosed(self):
|
||||
"""Used to notify the dialog so the lock can be released."""
|
||||
|
||||
self._result = {} # The result should be cleared before hide, because after it is released the main thread lock
|
||||
self._visible = False
|
||||
try:
|
||||
|
@ -319,8 +321,9 @@ class WorkspaceDialog(QObject):
|
|||
self._view.hide()
|
||||
self.hide()
|
||||
|
||||
## Block thread until the dialog is closed.
|
||||
def waitForClose(self):
|
||||
"""Block thread until the dialog is closed."""
|
||||
|
||||
if self._visible:
|
||||
if threading.current_thread() != threading.main_thread():
|
||||
self._lock.acquire()
|
||||
|
|
|
@ -107,11 +107,13 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
import json
|
||||
archive.writestr(file_in_archive, json.dumps(metadata, separators = (", ", ": "), indent = 4, skipkeys = True))
|
||||
|
||||
## Helper function that writes ContainerStacks, InstanceContainers and DefinitionContainers to the archive.
|
||||
# \param container That follows the \type{ContainerInterface} to archive.
|
||||
# \param archive The archive to write to.
|
||||
@staticmethod
|
||||
def _writeContainerToArchive(container, archive):
|
||||
"""Helper function that writes ContainerStacks, InstanceContainers and DefinitionContainers to the archive.
|
||||
|
||||
:param container: That follows the :type{ContainerInterface} to archive.
|
||||
:param archive: The archive to write to.
|
||||
"""
|
||||
if isinstance(container, type(ContainerRegistry.getInstance().getEmptyInstanceContainer())):
|
||||
return # Empty file, do nothing.
|
||||
|
||||
|
|
|
@ -60,15 +60,19 @@ class ThreeMFWriter(MeshWriter):
|
|||
result += str(matrix._data[2, 3])
|
||||
return result
|
||||
|
||||
## Should we store the archive
|
||||
# Note that if this is true, the archive will not be closed.
|
||||
# The object that set this parameter is then responsible for closing it correctly!
|
||||
def setStoreArchive(self, store_archive):
|
||||
"""Should we store the archive
|
||||
|
||||
Note that if this is true, the archive will not be closed.
|
||||
The object that set this parameter is then responsible for closing it correctly!
|
||||
"""
|
||||
self._store_archive = store_archive
|
||||
|
||||
## Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
||||
# \returns Uranium Scene node.
|
||||
def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()):
|
||||
"""Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
||||
|
||||
:returns: Uranium Scene node.
|
||||
"""
|
||||
if not isinstance(um_node, SceneNode):
|
||||
return None
|
||||
|
||||
|
|
|
@ -147,13 +147,13 @@ class AMFReader(MeshReader):
|
|||
|
||||
return group_node
|
||||
|
||||
## Converts a Trimesh to Uranium's MeshData.
|
||||
# \param tri_node A Trimesh containing the contents of a file that was
|
||||
# just read.
|
||||
# \param file_name The full original filename used to watch for changes
|
||||
# \return Mesh data from the Trimesh in a way that Uranium can understand
|
||||
# it.
|
||||
def _toMeshData(self, tri_node: trimesh.base.Trimesh, file_name: str = "") -> MeshData:
|
||||
"""Converts a Trimesh to Uranium's MeshData.
|
||||
|
||||
:param tri_node: A Trimesh containing the contents of a file that was just read.
|
||||
:param file_name: The full original filename used to watch for changes
|
||||
:return: Mesh data from the Trimesh in a way that Uranium can understand it.
|
||||
"""
|
||||
tri_faces = tri_node.faces
|
||||
tri_vertices = tri_node.vertices
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue