mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 06:57:28 -06:00
Revert "Revert "Merge pull request #7384 from Ultimaker/CURA-7333_Fix_reloading_3mf_files_with_many_objects""
This reverts commit 4f55c8d8
This commit is contained in:
parent
be8f8a308e
commit
e43768ebde
2 changed files with 49 additions and 27 deletions
|
@ -4,7 +4,7 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any
|
from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
from PyQt5.QtCore import QObject, QTimer, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
|
from PyQt5.QtCore import QObject, QTimer, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
|
||||||
|
@ -1382,12 +1382,21 @@ class CuraApplication(QtApplication):
|
||||||
if not nodes:
|
if not nodes:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
objects_in_filename = {} # type: Dict[str, List[CuraSceneNode]]
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
mesh_data = node.getMeshData()
|
mesh_data = node.getMeshData()
|
||||||
|
|
||||||
if mesh_data:
|
if mesh_data:
|
||||||
file_name = mesh_data.getFileName()
|
file_name = mesh_data.getFileName()
|
||||||
if file_name:
|
if file_name:
|
||||||
|
if file_name not in objects_in_filename:
|
||||||
|
objects_in_filename[file_name] = []
|
||||||
|
if file_name in objects_in_filename:
|
||||||
|
objects_in_filename[file_name].append(node)
|
||||||
|
else:
|
||||||
|
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:
|
||||||
job = ReadMeshJob(file_name)
|
job = ReadMeshJob(file_name)
|
||||||
job._node = node # type: ignore
|
job._node = node # type: ignore
|
||||||
job.finished.connect(self._reloadMeshFinished)
|
job.finished.connect(self._reloadMeshFinished)
|
||||||
|
@ -1395,8 +1404,6 @@ class CuraApplication(QtApplication):
|
||||||
job.finished.connect(self.updateOriginOfMergedMeshes)
|
job.finished.connect(self.updateOriginOfMergedMeshes)
|
||||||
|
|
||||||
job.start()
|
job.start()
|
||||||
else:
|
|
||||||
Logger.log("w", "Unable to reload data because we don't have a filename.")
|
|
||||||
|
|
||||||
@pyqtSlot("QStringList")
|
@pyqtSlot("QStringList")
|
||||||
def setExpandedCategories(self, categories: List[str]) -> None:
|
def setExpandedCategories(self, categories: List[str]) -> None:
|
||||||
|
@ -1572,13 +1579,30 @@ class CuraApplication(QtApplication):
|
||||||
fileLoaded = pyqtSignal(str)
|
fileLoaded = pyqtSignal(str)
|
||||||
fileCompleted = pyqtSignal(str)
|
fileCompleted = pyqtSignal(str)
|
||||||
|
|
||||||
def _reloadMeshFinished(self, job):
|
def _reloadMeshFinished(self, job) -> None:
|
||||||
# TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh!
|
"""
|
||||||
job_result = job.getResult()
|
Function called whenever a ReadMeshJob finishes in the background. It reloads a specific node object 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.
|
||||||
|
|
||||||
|
:param job: The ReadMeshJob running in the background that reads all the meshes in a file
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
job_result = job.getResult() # nodes that exist inside the file read by this job
|
||||||
if len(job_result) == 0:
|
if len(job_result) == 0:
|
||||||
Logger.log("e", "Reloading the mesh failed.")
|
Logger.log("e", "Reloading the mesh failed.")
|
||||||
return
|
return
|
||||||
mesh_data = job_result[0].getMeshData()
|
object_found = False
|
||||||
|
mesh_data = None
|
||||||
|
# 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:
|
if not mesh_data:
|
||||||
Logger.log("w", "Could not find a mesh in reloaded node.")
|
Logger.log("w", "Could not find a mesh in reloaded node.")
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,31 +1,28 @@
|
||||||
# Copyright (c) 2019 Ultimaker B.V.
|
# Copyright (c) 2019 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from typing import List, Optional, Union, TYPE_CHECKING
|
|
||||||
import os.path
|
import os.path
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from typing import List, Optional, Union, TYPE_CHECKING
|
||||||
import numpy
|
|
||||||
|
|
||||||
import Savitar
|
import Savitar
|
||||||
|
import numpy
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Math.Matrix import Matrix
|
from UM.Math.Matrix import Matrix
|
||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Mesh.MeshReader import MeshReader
|
from UM.Mesh.MeshReader import MeshReader
|
||||||
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||||
from UM.Scene.GroupDecorator import GroupDecorator
|
from UM.Scene.GroupDecorator import GroupDecorator
|
||||||
from UM.Scene.SceneNode import SceneNode # For typing.
|
from UM.Scene.SceneNode import SceneNode # For typing.
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.Machines.ContainerTree import ContainerTree
|
from cura.Machines.ContainerTree import ContainerTree
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
|
||||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
|
||||||
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
|
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
|
||||||
|
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||||
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
|
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
|
||||||
from cura.Scene.ZOffsetDecorator import ZOffsetDecorator
|
from cura.Scene.ZOffsetDecorator import ZOffsetDecorator
|
||||||
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not TYPE_CHECKING:
|
if not TYPE_CHECKING:
|
||||||
|
@ -52,7 +49,6 @@ class ThreeMFReader(MeshReader):
|
||||||
self._root = None
|
self._root = None
|
||||||
self._base_name = ""
|
self._base_name = ""
|
||||||
self._unit = None
|
self._unit = None
|
||||||
self._object_count = 0 # Used to name objects as there is no node name yet.
|
|
||||||
|
|
||||||
def _createMatrixFromTransformationString(self, transformation: str) -> Matrix:
|
def _createMatrixFromTransformationString(self, transformation: str) -> Matrix:
|
||||||
if transformation == "":
|
if transformation == "":
|
||||||
|
@ -87,17 +83,20 @@ class ThreeMFReader(MeshReader):
|
||||||
## 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.
|
||||||
def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
||||||
self._object_count += 1
|
|
||||||
|
|
||||||
node_name = savitar_node.getName()
|
node_name = savitar_node.getName()
|
||||||
|
node_id = savitar_node.getId()
|
||||||
if node_name == "":
|
if node_name == "":
|
||||||
node_name = "Object %s" % self._object_count
|
if file_name != "":
|
||||||
|
node_name = os.path.basename(file_name)
|
||||||
|
else:
|
||||||
|
node_name = "Object {}".format(node_id)
|
||||||
|
|
||||||
active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
|
active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
|
||||||
|
|
||||||
um_node = CuraSceneNode() # This adds a SettingOverrideDecorator
|
um_node = CuraSceneNode() # This adds a SettingOverrideDecorator
|
||||||
um_node.addDecorator(BuildPlateDecorator(active_build_plate))
|
um_node.addDecorator(BuildPlateDecorator(active_build_plate))
|
||||||
um_node.setName(node_name)
|
um_node.setName(node_name)
|
||||||
|
um_node.setId(node_id)
|
||||||
transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
|
transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
|
||||||
um_node.setTransformation(transformation)
|
um_node.setTransformation(transformation)
|
||||||
mesh_builder = MeshBuilder()
|
mesh_builder = MeshBuilder()
|
||||||
|
@ -169,7 +168,6 @@ class ThreeMFReader(MeshReader):
|
||||||
|
|
||||||
def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]:
|
def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]:
|
||||||
result = []
|
result = []
|
||||||
self._object_count = 0 # Used to name objects as there is no node name yet.
|
|
||||||
# The base object of 3mf is a zipped archive.
|
# The base object of 3mf is a zipped archive.
|
||||||
try:
|
try:
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue