Skip to content

Commit

Permalink
Fix duplicated file reloading
Browse files Browse the repository at this point in the history
CURA-11905

Instead of using the object name for reloading meshes inside a 3MF file, use a dedicated mesh ID property that is only stored internally, doesn't have to be unique (because the combination filename+ID will be) and can't be changed by the user. This should improve 3MF file reloading, and also fixes reloading of duplicated instances, because multiple meshes can now have the same mesh ID.
  • Loading branch information
wawanbreton committed Oct 7, 2024
1 parent 30d1f94 commit 84f772d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
9 changes: 8 additions & 1 deletion UM/Mesh/MeshBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(self) -> None:
self._face_count = 0
self._type = MeshType.faces
self._file_name = None # type: Optional[str]
self._mesh_id: Optional[str] = None
# original center position
self._center_position = None # type: Optional[Vector]

Expand All @@ -48,7 +49,7 @@ def build(self) -> MeshData:

return MeshData(vertices = self.getVertices(), normals = self.getNormals(), indices = self.getIndices(),
colors = self.getColors(), uvs = self.getUVCoordinates(), file_name = self.getFileName(),
center_position = self.getCenterPosition())
center_position = self.getCenterPosition(), mesh_id = self.getMeshId())

def setCenterPosition(self, position: Optional[Vector]) -> None:
self._center_position = position
Expand Down Expand Up @@ -166,6 +167,12 @@ def getFileName(self) -> Optional[str]:
def setFileName(self, file_name: Optional[str]) -> None:
self._file_name = file_name

def getMeshId(self) -> Optional[str]:
return self._mesh_id

def setMeshId(self, mesh_id: Optional[str]) -> None:
self._mesh_id = mesh_id

def reserveFaceCount(self, num_faces: int) -> None:
"""Set the amount of faces before loading data to the mesh.
Expand Down
12 changes: 9 additions & 3 deletions UM/Mesh/MeshData.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class MeshData:
"""

def __init__(self, vertices=None, normals=None, indices=None, colors=None, uvs=None, file_name=None,
center_position=None, zero_position=None, type = MeshType.faces, attributes=None) -> None:
center_position=None, zero_position=None, type = MeshType.faces, attributes=None, mesh_id=None) -> None:
self._application = None # Initialize this later otherwise unit tests break

self._vertices = NumPyUtil.immutableNDArray(vertices)
Expand All @@ -60,6 +60,7 @@ def __init__(self, vertices=None, normals=None, indices=None, colors=None, uvs=N
self._face_count = len(self._indices) if self._indices is not None else 0
self._type = type
self._file_name = file_name # type: Optional[str]
self._mesh_id: Optional[str] = mesh_id
# original center position
self._center_position = center_position
# original zero position, is changed after transformation
Expand Down Expand Up @@ -93,7 +94,7 @@ def __del__(self):
self._application.getController().getScene().removeWatchedFile(self._file_name)

def set(self, vertices=Reuse, normals=Reuse, indices=Reuse, colors=Reuse, uvs=Reuse, file_name=Reuse,
center_position=Reuse, zero_position=Reuse, attributes=Reuse) -> "MeshData":
center_position=Reuse, zero_position=Reuse, attributes=Reuse, mesh_id=Reuse) -> "MeshData":
"""Create a new MeshData with specified changes
:return: :type{MeshData}
Expand All @@ -105,12 +106,14 @@ def set(self, vertices=Reuse, normals=Reuse, indices=Reuse, colors=Reuse, uvs=Re
colors = colors if colors is not Reuse else self._colors
uvs = uvs if uvs is not Reuse else self._uvs
file_name = file_name if file_name is not Reuse else self._file_name
mesh_id = mesh_id if mesh_id is not Reuse else self._mesh_id
center_position = center_position if center_position is not Reuse else self._center_position
zero_position = zero_position if zero_position is not Reuse else self._zero_position
attributes = attributes if attributes is not Reuse else self._attributes

return MeshData(vertices=vertices, normals=normals, indices=indices, colors=colors, uvs=uvs,
file_name=file_name, center_position=center_position, zero_position=zero_position, attributes=attributes)
file_name=file_name, center_position=center_position, zero_position=zero_position,
attributes=attributes, mesh_id=mesh_id)

def getHash(self):
m = hashlib.sha256()
Expand Down Expand Up @@ -184,6 +187,9 @@ def hasUVCoordinates(self) -> bool:
def getFileName(self) -> Optional[str]:
return self._file_name

def getMeshId(self) -> Optional[str]:
return self._mesh_id

def getTransformed(self, transformation: Matrix) -> "MeshData":
"""Transform the meshdata, center and zero position by given Matrix
Expand Down
15 changes: 7 additions & 8 deletions UM/Scene/Scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,14 @@ def _reloadJobFinished(self, replaced_nodes: [SceneNode], job: ReadMeshJob) -> N
renamed_nodes[node.getName()] = 0

# Find the matching scene node to replace
scene_node = None
mesh_replaced = False
for replaced_node in replaced_nodes:
if replaced_node.getName() == node_name:
scene_node = replaced_node
break
mesh_id = replaced_node.getMeshData().getMeshId()
if mesh_id is None or mesh_id == mesh_data.getMeshId():
replaced_node.setMeshData(mesh_data)
mesh_replaced = True

if scene_node:
scene_node.setMeshData(mesh_data)
else:
# Current node is a new one in the file, or it's name has changed
if not mesh_replaced:
# Current node is a new one in the file, or it's ID has changed
# TODO: Load this mesh into the scene. Also alter the "ReloadAll" action in CuraApplication.
Logger.log("w", "Could not find matching node for object '{0}' in the scene.", node_name)

0 comments on commit 84f772d

Please sign in to comment.