Skip to content

Commit

Permalink
Merge pull request #16610 from pietchaki/object-reload-refactor
Browse files Browse the repository at this point in the history
Refactor object reload to handle 3mf files
  • Loading branch information
saumyaj3 authored Nov 1, 2023
2 parents 3561b12 + f31980d commit 3121766
Showing 1 changed file with 42 additions and 25 deletions.
67 changes: 42 additions & 25 deletions cura/CuraApplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -1555,15 +1555,14 @@ def reloadAll(self) -> None:
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:
Expand Down Expand Up @@ -1735,9 +1734,10 @@ def _onActiveMachineChanged(self):

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
Expand All @@ -1747,21 +1747,37 @@ def _reloadMeshFinished(self, job) -> None:
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))
Expand Down Expand Up @@ -1948,7 +1964,8 @@ def _readMeshFinished(self, job):
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
Expand Down

0 comments on commit 3121766

Please sign in to comment.