diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 85835db89f..51f524d0a1 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -2,10 +2,9 @@ # Cura is released under the terms of the LGPLv3 or higher. import os -import re import sys import time -from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict +from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any import numpy from PyQt5.QtCore import QObject, QTimer, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS @@ -1383,29 +1382,22 @@ class CuraApplication(QtApplication): if not nodes: return - objects_in_filename = {} # type: Dict[str, List[CuraSceneNode]] for node in nodes: mesh_data = node.getMeshData() + if mesh_data: file_name = mesh_data.getFileName() 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) + job = ReadMeshJob(file_name) + job._node = node # type: ignore + job.finished.connect(self._reloadMeshFinished) + if has_merged_nodes: + job.finished.connect(self.updateOriginOfMergedMeshes) + + job.start() 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._node = node # 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: categories = list(set(categories)) @@ -1580,30 +1572,13 @@ class CuraApplication(QtApplication): fileLoaded = pyqtSignal(str) fileCompleted = pyqtSignal(str) - def _reloadMeshFinished(self, job) -> None: - """ - 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 + def _reloadMeshFinished(self, job): + # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! + job_result = job.getResult() if len(job_result) == 0: Logger.log("e", "Reloading the mesh failed.") return - 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 + mesh_data = job_result[0].getMeshData() if not mesh_data: Logger.log("w", "Could not find a mesh in reloaded node.") return diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index a368cedd75..670049802d 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -52,6 +52,7 @@ class ThreeMFReader(MeshReader): self._root = None self._base_name = "" self._unit = None + self._object_count = 0 # Used to name objects as there is no node name yet. def _createMatrixFromTransformationString(self, transformation: str) -> Matrix: if transformation == "": @@ -86,20 +87,17 @@ class ThreeMFReader(MeshReader): ## 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]: + self._object_count += 1 + node_name = savitar_node.getName() - node_id = savitar_node.getId() if node_name == "": - if file_name != "": - node_name = os.path.basename(file_name) - else: - node_name = "Object {}".format(node_id) + node_name = "Object %s" % self._object_count active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate um_node = CuraSceneNode() # This adds a SettingOverrideDecorator um_node.addDecorator(BuildPlateDecorator(active_build_plate)) um_node.setName(node_name) - um_node.setId(node_id) transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation()) um_node.setTransformation(transformation) mesh_builder = MeshBuilder() @@ -171,6 +169,7 @@ class ThreeMFReader(MeshReader): def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: 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. try: archive = zipfile.ZipFile(file_name, "r") diff --git a/resources/definitions/geeetech_A10M.def.json b/resources/definitions/geeetech_A10M.def.json index 6a25e4c407..1b0f46ad98 100644 --- a/resources/definitions/geeetech_A10M.def.json +++ b/resources/definitions/geeetech_A10M.def.json @@ -45,7 +45,7 @@ "machine_max_jerk_e": { "default_value": 2.5 }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": ";GeeeTech A10M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" + "default_value": ";GeeeTech A10M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM109 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" }, "machine_end_gcode": { "default_value": "G91\nG1 E-1\nG0 X0 Y200\nM104 S0\nG90\nG92 E0\nM140 S0\nM84\nM104 S0\nM140 S0\nM84" diff --git a/resources/definitions/geeetech_A20M.def.json b/resources/definitions/geeetech_A20M.def.json index 476741c7fe..d06cf9565f 100644 --- a/resources/definitions/geeetech_A20M.def.json +++ b/resources/definitions/geeetech_A20M.def.json @@ -45,7 +45,7 @@ "machine_max_jerk_e": { "default_value": 2.5 }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": ";GeeeTech A20M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" + "default_value": ";GeeeTech A20M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM109 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" }, "machine_end_gcode": { "default_value": "G91\nG1 E-1\nG0 X0 Y200\nM104 S0\nG90\nG92 E0\nM140 S0\nM84\nM104 S0\nM140 S0\nM84" diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index d17114e3a1..aebf21985b 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -42,7 +42,7 @@ Fixed a bug where comments were removed from Start/End G-codes when opening from Values in the print monitor preheat fields were broken in previous versions, they have now been fixed by fieldOfview. * Stepper motor disarming during pause at height. -Some printers automatically disable their steppers after a pause after a certain time. Now it's possible to set that in the pause at height script instead of relying on default behavior of the firmware. +Some printers (like the Ultimaker S5) have a very heavy build platform. When the pause at height script was enabled, it would disarm the Z stepper motor at pause height. The weight of the build platform would cause the Z axis to lower by gravity and lose the Z position. ilyko96 has contributed a fix to the pause at height script so that the Z stepper motor now remains armed during a pause, locking the build plate in position. * Flying Bear printers. oducceu has contributed a machine definition for the Flying Bear Ghost 4S Printer.