Merge pull request #16610 from pietchaki/object-reload-refactor

Refactor object reload to handle 3mf files
This commit is contained in:
Saumya Jain 2023-11-01 14:53:56 +01:00 committed by GitHub
commit 3121766fb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1555,15 +1555,14 @@ class CuraApplication(QtApplication):
Logger.log("w", "Unable to reload data because we don't have a filename.")
for file_name, nodes in objects_in_filename.items():
for node in nodes:
file_path = os.path.normpath(os.path.dirname(file_name))
job = ReadMeshJob(file_name, add_to_recent_files = file_path != tempfile.gettempdir()) # Don't add temp files to the recent files list
job._node = node # type: ignore
job.finished.connect(self._reloadMeshFinished)
if has_merged_nodes:
job.finished.connect(self.updateOriginOfMergedMeshes)
job.start()
file_path = os.path.normpath(os.path.dirname(file_name))
job = ReadMeshJob(file_name,
add_to_recent_files=file_path != tempfile.gettempdir()) # Don't add temp files to the recent files list
job._nodes = nodes # type: ignore
job.finished.connect(self._reloadMeshFinished)
if has_merged_nodes:
job.finished.connect(self.updateOriginOfMergedMeshes)
job.start()
@pyqtSlot("QStringList")
def setExpandedCategories(self, categories: List[str]) -> None:
@ -1735,9 +1734,10 @@ class CuraApplication(QtApplication):
def _reloadMeshFinished(self, job) -> None:
"""
Function called whenever a ReadMeshJob finishes in the background. It reloads a specific node object in the
Function called when ReadMeshJob finishes reloading a file in the background, then update node objects in the
scene from its source file. The function gets all the nodes that exist in the file through the job result, and
then finds the scene node that it wants to refresh by its object id. Each job refreshes only one node.
then finds the scene nodes that need to be refreshed by their name. Each job refreshes all nodes of a file.
Nodes that are not present in the updated file are kept in the scene.
:param job: The :py:class:`Uranium.UM.ReadMeshJob.ReadMeshJob` running in the background that reads all the
meshes in a file
@ -1747,21 +1747,37 @@ class CuraApplication(QtApplication):
if len(job_result) == 0:
Logger.log("e", "Reloading the mesh failed.")
return
object_found = False
mesh_data = None
renamed_nodes = {} # type: Dict[str, int]
# Find the node to be refreshed based on its id
for job_result_node in job_result:
if job_result_node.getId() == job._node.getId():
mesh_data = job_result_node.getMeshData()
object_found = True
break
if not object_found:
Logger.warning("The object with id {} no longer exists! Keeping the old version in the scene.".format(job_result_node.getId()))
return
if not mesh_data:
Logger.log("w", "Could not find a mesh in reloaded node.")
return
job._node.setMeshData(mesh_data)
mesh_data = job_result_node.getMeshData()
if not mesh_data:
Logger.log("w", "Could not find a mesh in reloaded node.")
continue
# Solves issues with object naming
result_node_name = job_result_node.getName()
if not result_node_name:
result_node_name = os.path.basename(mesh_data.getFileName())
if result_node_name in renamed_nodes: # objects may get renamed by ObjectsModel._renameNodes() when loaded
renamed_nodes[result_node_name] += 1
result_node_name = "{0}({1})".format(result_node_name, renamed_nodes[result_node_name])
else:
renamed_nodes[job_result_node.getName()] = 0
# Find the matching scene node to replace
scene_node = None
for replaced_node in job._nodes:
if replaced_node.getName() == result_node_name:
scene_node = replaced_node
break
if scene_node:
scene_node.setMeshData(mesh_data)
else:
# Current node is a new one in the file, or it's name has changed
# TODO: Load this mesh into the scene. Also alter the "_reloadJobFinished" action in UM.Scene
Logger.log("w", "Could not find matching node for object '{0}' in the scene.".format(result_node_name))
def _openFile(self, filename):
self.readLocalFile(QUrl.fromLocalFile(filename))
@ -1948,7 +1964,8 @@ class CuraApplication(QtApplication):
node.scale(original_node.getScale())
node.setSelectable(True)
node.setName(os.path.basename(file_name))
if not node.getName():
node.setName(os.path.basename(file_name))
self.getBuildVolume().checkBoundsAndUpdate(node)
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions