diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 986f28a826..da872f1723 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import Optional, Dict, Any, Set, List -from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal +from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal, QTimer import cura.CuraApplication from UM.Qt.ListModel import ListModel @@ -32,9 +32,14 @@ class IntentModel(ListModel): self._intent_category = "engineering" + self._update_timer = QTimer() + self._update_timer.setInterval(100) + self._update_timer.setSingleShot(True) + self._update_timer.timeout.connect(self._update) + machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager() - machine_manager.globalContainerChanged.connect(self._update) - machine_manager.extruderChanged.connect(self._update) # We also need to update if an extruder gets disabled + machine_manager.globalContainerChanged.connect(self._updateDelayed) + machine_manager.extruderChanged.connect(self._updateDelayed) # We also need to update if an extruder gets disabled ContainerRegistry.getInstance().containerAdded.connect(self._onChanged) ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged) self._layer_height_unit = "" # This is cached @@ -52,9 +57,12 @@ class IntentModel(ListModel): def intentCategory(self) -> str: return self._intent_category + def _updateDelayed(self): + self._update_timer.start() + def _onChanged(self, container): if container.getMetaDataEntry("type") == "intent": - self._update() + self._updateDelayed() def _update(self) -> None: new_items = [] # type: List[Dict[str, Any]] diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index 91ff26cadc..36d9e68c8f 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -1,6 +1,6 @@ from UM.Logger import Logger -from PyQt5.QtCore import Qt, pyqtSlot, QObject +from PyQt5.QtCore import Qt, pyqtSlot, QObject, QTimer from PyQt5.QtWidgets import QApplication from UM.Scene.Camera import Camera @@ -26,16 +26,23 @@ class CuraSceneController(QObject): self._last_selected_index = 0 self._max_build_plate = 1 # default + self._change_timer = QTimer() + self._change_timer.setInterval(100) + self._change_timer.setSingleShot(True) + self._change_timer.timeout.connect(self.updateMaxBuildPlate) + Application.getInstance().getController().getScene().sceneChanged.connect(self.updateMaxBuildPlateDelayed) - Application.getInstance().getController().getScene().sceneChanged.connect(self.updateMaxBuildPlate) # it may be a bit inefficient when changing a lot simultaneously - - def updateMaxBuildPlate(self, *args): + def updateMaxBuildPlateDelayed(self, *args): if args: source = args[0] else: source = None + if not isinstance(source, SceneNode) or isinstance(source, Camera): return + self._change_timer.start() + + def updateMaxBuildPlate(self, *args): max_build_plate = self._calcMaxBuildPlate() changed = False if max_build_plate != self._max_build_plate: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 2a9b2e8f83..14d0401af4 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -82,13 +82,9 @@ class MachineManager(QObject): self._stacks_have_errors = None # type: Optional[bool] - self._onGlobalContainerChanged() - extruder_manager = self._application.getExtruderManager() extruder_manager.activeExtruderChanged.connect(self._onActiveExtruderStackChanged) - self._onActiveExtruderStackChanged() - extruder_manager.activeExtruderChanged.connect(self.activeMaterialChanged) extruder_manager.activeExtruderChanged.connect(self.activeVariantChanged) extruder_manager.activeExtruderChanged.connect(self.activeQualityChanged) diff --git a/cura/UI/PrintInformation.py b/cura/UI/PrintInformation.py index e33ab13b69..c39314dc02 100644 --- a/cura/UI/PrintInformation.py +++ b/cura/UI/PrintInformation.py @@ -7,7 +7,7 @@ import os import unicodedata from typing import Dict, List, Optional, TYPE_CHECKING -from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot +from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot, QTimer from UM.Logger import Logger from UM.Qt.Duration import Duration @@ -47,7 +47,12 @@ class PrintInformation(QObject): if self._backend: self._backend.printDurationMessage.connect(self._onPrintDurationMessage) - self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged) + self._application.getController().getScene().sceneChanged.connect(self._onSceneChangedDelayed) + + self._change_timer = QTimer() + self._change_timer.setInterval(100) + self._change_timer.setSingleShot(True) + self._change_timer.timeout.connect(self._onSceneChanged) self._is_user_specified_job_name = False self._base_name = "" @@ -418,12 +423,14 @@ class PrintInformation(QObject): self._onPrintDurationMessage(build_plate, temp_message, temp_material_amounts) - ## Listen to scene changes to check if we need to reset the print information - def _onSceneChanged(self, scene_node: SceneNode) -> None: + def _onSceneChangedDelayed(self, scene_node: SceneNode) -> None: # Ignore any changes that are not related to sliceable objects - if not isinstance(scene_node, SceneNode)\ - or not scene_node.callDecoration("isSliceable")\ + if not isinstance(scene_node, SceneNode) \ + or not scene_node.callDecoration("isSliceable") \ or not scene_node.callDecoration("getBuildPlateNumber") == self._active_build_plate: return + self._change_timer.start() + ## Listen to scene changes to check if we need to reset the print information + def _onSceneChanged(self) -> None: self.setToZeroPrintInformation(self._active_build_plate) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index cd0eda2929..4e4f1e49df 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -46,19 +46,10 @@ class SimulationPass(RenderPass): self._layer_view = layerview self._compatibility_mode = layerview.getCompatibilityMode() - def render(self): - if not self._layer_shader: - if self._compatibility_mode: - shader_filename = "layers.shader" - shadow_shader_filename = "layers_shadow.shader" - else: - shader_filename = "layers3d.shader" - shadow_shader_filename = "layers3d_shadow.shader" - self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shader_filename)) - self._layer_shadow_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shadow_shader_filename)) - self._current_shader = self._layer_shader + def _updateLayerShaderValues(self): # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) - self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) + self._layer_shader.setUniformValue("u_active_extruder", + float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate()) self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate()) @@ -71,7 +62,7 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) else: - #defaults + # defaults self._layer_shader.setUniformValue("u_max_feedrate", 1) self._layer_shader.setUniformValue("u_min_feedrate", 0) self._layer_shader.setUniformValue("u_max_thickness", 1) @@ -83,6 +74,20 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) + def render(self): + if not self._layer_shader: + if self._compatibility_mode: + shader_filename = "layers.shader" + shadow_shader_filename = "layers_shadow.shader" + else: + shader_filename = "layers3d.shader" + shadow_shader_filename = "layers3d_shadow.shader" + self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shader_filename)) + self._layer_shadow_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shadow_shader_filename)) + self._current_shader = self._layer_shader + + self._updateLayerShaderValues() + if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) @@ -93,12 +98,10 @@ class SimulationPass(RenderPass): self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True) - active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate head_position = None # Indicates the current position of the print head nozzle_node = None for node in DepthFirstIterator(self._scene.getRoot()): - if isinstance(node, ToolHandle): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) @@ -113,29 +116,24 @@ class SimulationPass(RenderPass): # Render all layers below a certain number as line mesh instead of vertices. if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): - start = 0 - end = 0 - element_counts = layer_data.getElementCounts() - for layer in sorted(element_counts.keys()): - # In the current layer, we show just the indicated paths - if layer == self._layer_view._current_layer_num: - # We look for the position of the head, searching the point of the current path - index = self._layer_view._current_path_num - offset = 0 - for polygon in layer_data.getLayer(layer).polygons: - # The size indicates all values in the two-dimension array, and the second dimension is - # always size 3 because we have 3D points. - if index >= polygon.data.size // 3 - offset: - index -= polygon.data.size // 3 - offset - offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon - continue - # The head position is calculated and translated - head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition() - break - break - if self._layer_view._minimum_layer_num > layer: - start += element_counts[layer] - end += element_counts[layer] + start = self._layer_view.start_elements_index + end = self._layer_view.end_elements_index + index = self._layer_view._current_path_num + offset = 0 + layer = layer_data.getLayer(self._layer_view._current_layer_num) + if layer is None: + continue + for polygon in layer.polygons: + # The size indicates all values in the two-dimension array, and the second dimension is + # always size 3 because we have 3D points. + if index >= polygon.data.size // 3 - offset: + index -= polygon.data.size // 3 - offset + offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon + continue + # The head position is calculated and translated + head_position = Vector(polygon.data[index + offset][0], polygon.data[index + offset][1], + polygon.data[index + offset][2]) + node.getWorldPosition() + break # Calculate the range of paths in the last layer current_layer_start = end diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 4282806ff5..3a860a3055 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -71,6 +71,8 @@ class SimulationView(CuraView): self._max_paths = 0 self._current_path_num = 0 self._minimum_path_num = 0 + self.start_elements_index = 0 + self.end_elements_index = 0 self.currentLayerNumChanged.connect(self._onCurrentLayerNumChanged) self._busy = False @@ -243,6 +245,7 @@ class SimulationView(CuraView): self._minimum_layer_num = self._current_layer_num self._startUpdateTopLayers() + self.recalculateStartEndElements() self.currentLayerNumChanged.emit() @@ -257,7 +260,7 @@ class SimulationView(CuraView): self._current_layer_num = self._minimum_layer_num self._startUpdateTopLayers() - + self.recalculateStartEndElements() self.currentLayerNumChanged.emit() def setPath(self, value: int) -> None: @@ -271,7 +274,7 @@ class SimulationView(CuraView): self._minimum_path_num = self._current_path_num self._startUpdateTopLayers() - + self.recalculateStartEndElements() self.currentPathNumChanged.emit() def setMinimumPath(self, value: int) -> None: @@ -359,6 +362,24 @@ class SimulationView(CuraView): return 0.0 # If it's still max-float, there are no measurements. Use 0 then. return self._min_thickness + def recalculateStartEndElements(self): + self.start_elements_index = 0 + self.end_elements_index = 0 + scene = self.getController().getScene() + for node in DepthFirstIterator(scene.getRoot()): # type: ignore + layer_data = node.callDecoration("getLayerData") + if not layer_data: + continue + + # Found a the layer data! + element_counts = layer_data.getElementCounts() + for layer in sorted(element_counts.keys()): + if layer == self._current_layer_num: + break + if self._minimum_layer_num > layer: + self.start_elements_index += element_counts[layer] + self.end_elements_index += element_counts[layer] + def getMaxThickness(self) -> float: return self._max_thickness @@ -578,7 +599,7 @@ class SimulationView(CuraView): def _startUpdateTopLayers(self) -> None: if not self._compatibility_mode: return - + self.recalculateStartEndElements() if self._top_layers_job: self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) self._top_layers_job.cancel() diff --git a/resources/definitions/beamup_s.def.json b/resources/definitions/beamup_s.def.json new file mode 100644 index 0000000000..07e0458db3 --- /dev/null +++ b/resources/definitions/beamup_s.def.json @@ -0,0 +1,58 @@ +{ + "version": 2, + "name": "BeamUp S", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "BeamUp", + "manufacturer": "BeamUp", + "file_formats": "text/x-gcode", + "platform": "beamup_s.stl", + "platform_offset": [0, -5, -10], + "has_machine_quality": true, + "has_materials": true, + "machine_extruder_trains": + { + "0": "beamup_s_extruder_0" + } + }, + + "overrides": { + "machine_name": { + "default_value": "BeamUp S" + }, + "machine_width": { + "default_value": 200 + }, + "machine_depth": { + "default_value": 180 + }, + "machine_height": { + "default_value": 130 + }, + "machine_heated_bed": { + "default_value": false + }, + "machine_center_is_zero": { + "default_value": false + }, + "machine_nozzle_heat_up_speed": { + "default_value": 2 + }, + "machine_nozzle_cool_down_speed": { + "default_value": 2 + }, + "gantry_height": { + "value": "0" + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + }, + "machine_start_gcode": { + "default_value": "G28 ; home\nG29 ; level\nM80 ; led\nG1 Z15.0 F6000\nT0\nG92 E0.0000\nG1 E-1.4500 F1800\nG1 X5 Y0 Z0.300 F6000\nM300 S3000 P300\nG1 E1.0000 F1800\nG92 E0.0000\nG1 X180 Y0 E15 F662" + }, + "machine_end_gcode": { + "default_value": "G28 ; home\nM104 S0 ; turn off\n M140 S0 ; turn off\nM84 ; disable motors\nM107 ; fan off" + } + } +} diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 46d194c6a0..2c71492bda 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2681,150 +2681,6 @@ "maximum_value_warning": "150", "settable_per_mesh": true }, - "retraction_enable": - { - "label": "Enable Retraction", - "description": "Retract the filament when the nozzle is moving over a non-printed area. ", - "type": "bool", - "default_value": true, - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retract_at_layer_change": - { - "label": "Retract at Layer Change", - "description": "Retract the filament when the nozzle is moving to the next layer.", - "type": "bool", - "default_value": false, - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_amount": - { - "label": "Retraction Distance", - "description": "The length of material retracted during a retraction move.", - "unit": "mm", - "type": "float", - "default_value": 6.5, - "minimum_value_warning": "-0.0001", - "maximum_value_warning": "10.0", - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_speed": - { - "label": "Retraction Speed", - "description": "The speed at which the filament is retracted and primed during a retraction move.", - "unit": "mm/s", - "type": "float", - "default_value": 25, - "minimum_value": "0.0001", - "minimum_value_warning": "1", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "maximum_value_warning": "70", - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", - "settable_per_mesh": false, - "settable_per_extruder": true, - "children": - { - "retraction_retract_speed": - { - "label": "Retraction Retract Speed", - "description": "The speed at which the filament is retracted during a retraction move.", - "unit": "mm/s", - "type": "float", - "default_value": 25, - "minimum_value": "0.0001", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "minimum_value_warning": "1", - "maximum_value_warning": "70", - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", - "value": "retraction_speed", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_prime_speed": - { - "label": "Retraction Prime Speed", - "description": "The speed at which the filament is primed during a retraction move.", - "unit": "mm/s", - "type": "float", - "default_value": 25, - "minimum_value": "0.0001", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "minimum_value_warning": "1", - "maximum_value_warning": "70", - "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", - "value": "retraction_speed", - "settable_per_mesh": false, - "settable_per_extruder": true - } - } - }, - "retraction_extra_prime_amount": - { - "label": "Retraction Extra Prime Amount", - "description": "Some material can ooze away during a travel move, which can be compensated for here.", - "unit": "mm³", - "type": "float", - "default_value": 0, - "minimum_value_warning": "-0.0001", - "maximum_value_warning": "5.0", - "enabled": "retraction_enable", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_min_travel": - { - "label": "Retraction Minimum Travel", - "description": "The minimum distance of travel needed for a retraction to happen at all. This helps to get fewer retractions in a small area.", - "unit": "mm", - "type": "float", - "default_value": 1.5, - "value": "line_width * 2", - "minimum_value": "0", - "minimum_value_warning": "line_width * 1.5", - "maximum_value_warning": "10", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_count_max": - { - "label": "Maximum Retraction Count", - "description": "This setting limits the number of retractions occurring within the minimum extrusion distance window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament, as that can flatten the filament and cause grinding issues.", - "default_value": 90, - "minimum_value": "0", - "maximum_value_warning": "100", - "type": "int", - "enabled": "retraction_enable", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "retraction_extrusion_window": - { - "label": "Minimum Extrusion Distance Window", - "description": "The window in which the maximum retraction count is enforced. This value should be approximately the same as the retraction distance, so that effectively the number of times a retraction passes the same patch of material is limited.", - "unit": "mm", - "type": "float", - "default_value": 4.5, - "minimum_value": "0", - "maximum_value_warning": "retraction_amount * 2", - "value": "retraction_amount", - "enabled": "retraction_enable", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "limit_support_retractions": - { - "label": "Limit Support Retractions", - "description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure.", - "type": "bool", - "default_value": true, - "enabled": "retraction_enable and (support_enable or support_tree_enable)", - "settable_per_mesh": false, - "settable_per_extruder": true - }, "material_standby_temperature": { "label": "Standby Temperature", @@ -2838,83 +2694,6 @@ "enabled": "extruders_enabled_count > 1 and machine_nozzle_temp_enabled", "settable_per_mesh": false, "settable_per_extruder": true - }, - "switch_extruder_retraction_amount": - { - "label": "Nozzle Switch Retraction Distance", - "description": "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone.", - "type": "float", - "unit": "mm", - "enabled": "retraction_enable", - "default_value": 20, - "value": "machine_heat_zone_length", - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "switch_extruder_retraction_speeds": - { - "label": "Nozzle Switch Retraction Speed", - "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", - "type": "float", - "unit": "mm/s", - "enabled": "retraction_enable", - "default_value": 20, - "minimum_value": "0.1", - "minimum_value_warning": "1", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "maximum_value_warning": "70", - "settable_per_mesh": false, - "settable_per_extruder": true, - "children": - { - "switch_extruder_retraction_speed": - { - "label": "Nozzle Switch Retract Speed", - "description": "The speed at which the filament is retracted during a nozzle switch retract.", - "type": "float", - "unit": "mm/s", - "enabled": "retraction_enable", - "default_value": 20, - "value": "switch_extruder_retraction_speeds", - "minimum_value": "0.1", - "minimum_value_warning": "1", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "maximum_value_warning": "70", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "switch_extruder_prime_speed": - { - "label": "Nozzle Switch Prime Speed", - "description": "The speed at which the filament is pushed back after a nozzle switch retraction.", - "type": "float", - "unit": "mm/s", - "enabled": "retraction_enable", - "default_value": 20, - "value": "switch_extruder_retraction_speeds", - "minimum_value": "0.1", - "minimum_value_warning": "1", - "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", - "maximum_value_warning": "70", - "settable_per_mesh": false, - "settable_per_extruder": true - } - } - }, - "switch_extruder_extra_prime_amount": - { - "label": "Nozzle Switch Extra Prime Amount", - "description": "Extra material to prime after nozzle switching.", - "type": "float", - "unit": "mm³", - "default_value": 0, - "minimum_value_warning": "0", - "maximum_value_warning": "100", - "enabled": "retraction_enable", - "settable_per_mesh": false, - "settable_per_extruder": true } } }, @@ -3830,6 +3609,150 @@ "type": "category", "children": { + "retraction_enable": + { + "label": "Enable Retraction", + "description": "Retract the filament when the nozzle is moving over a non-printed area. ", + "type": "bool", + "default_value": true, + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retract_at_layer_change": + { + "label": "Retract at Layer Change", + "description": "Retract the filament when the nozzle is moving to the next layer.", + "type": "bool", + "default_value": false, + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_amount": + { + "label": "Retraction Distance", + "description": "The length of material retracted during a retraction move.", + "unit": "mm", + "type": "float", + "default_value": 6.5, + "minimum_value_warning": "-0.0001", + "maximum_value_warning": "10.0", + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_speed": + { + "label": "Retraction Speed", + "description": "The speed at which the filament is retracted and primed during a retraction move.", + "unit": "mm/s", + "type": "float", + "default_value": 25, + "minimum_value": "0.0001", + "minimum_value_warning": "1", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "maximum_value_warning": "70", + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "settable_per_mesh": false, + "settable_per_extruder": true, + "children": + { + "retraction_retract_speed": + { + "label": "Retraction Retract Speed", + "description": "The speed at which the filament is retracted during a retraction move.", + "unit": "mm/s", + "type": "float", + "default_value": 25, + "minimum_value": "0.0001", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "minimum_value_warning": "1", + "maximum_value_warning": "70", + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "value": "retraction_speed", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_prime_speed": + { + "label": "Retraction Prime Speed", + "description": "The speed at which the filament is primed during a retraction move.", + "unit": "mm/s", + "type": "float", + "default_value": 25, + "minimum_value": "0.0001", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "minimum_value_warning": "1", + "maximum_value_warning": "70", + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"", + "value": "retraction_speed", + "settable_per_mesh": false, + "settable_per_extruder": true + } + } + }, + "retraction_extra_prime_amount": + { + "label": "Retraction Extra Prime Amount", + "description": "Some material can ooze away during a travel move, which can be compensated for here.", + "unit": "mm³", + "type": "float", + "default_value": 0, + "minimum_value_warning": "-0.0001", + "maximum_value_warning": "5.0", + "enabled": "retraction_enable", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_min_travel": + { + "label": "Retraction Minimum Travel", + "description": "The minimum distance of travel needed for a retraction to happen at all. This helps to get fewer retractions in a small area.", + "unit": "mm", + "type": "float", + "default_value": 1.5, + "value": "line_width * 2", + "minimum_value": "0", + "minimum_value_warning": "line_width * 1.5", + "maximum_value_warning": "10", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_count_max": + { + "label": "Maximum Retraction Count", + "description": "This setting limits the number of retractions occurring within the minimum extrusion distance window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament, as that can flatten the filament and cause grinding issues.", + "default_value": 90, + "minimum_value": "0", + "maximum_value_warning": "100", + "type": "int", + "enabled": "retraction_enable", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "retraction_extrusion_window": + { + "label": "Minimum Extrusion Distance Window", + "description": "The window in which the maximum retraction count is enforced. This value should be approximately the same as the retraction distance, so that effectively the number of times a retraction passes the same patch of material is limited.", + "unit": "mm", + "type": "float", + "default_value": 4.5, + "minimum_value": "0", + "maximum_value_warning": "retraction_amount * 2", + "value": "retraction_amount", + "enabled": "retraction_enable", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "limit_support_retractions": + { + "label": "Limit Support Retractions", + "description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure.", + "type": "bool", + "default_value": true, + "enabled": "retraction_enable and (support_enable or support_tree_enable)", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "retraction_combing": { "label": "Combing Mode", @@ -5843,6 +5766,83 @@ "maximum_value_warning": "20", "settable_per_mesh": false, "settable_per_extruder": false + }, + "switch_extruder_retraction_amount": + { + "label": "Nozzle Switch Retraction Distance", + "description": "The amount of retraction when switching extruders. Set to 0 for no retraction at all. This should generally be the same as the length of the heat zone.", + "type": "float", + "unit": "mm", + "enabled": "retraction_enable and extruders_enabled_count > 1", + "default_value": 20, + "value": "machine_heat_zone_length", + "minimum_value_warning": "0", + "maximum_value_warning": "100", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "switch_extruder_retraction_speeds": + { + "label": "Nozzle Switch Retraction Speed", + "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", + "type": "float", + "unit": "mm/s", + "enabled": "retraction_enable and extruders_enabled_count > 1", + "default_value": 20, + "minimum_value": "0.1", + "minimum_value_warning": "1", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "maximum_value_warning": "70", + "settable_per_mesh": false, + "settable_per_extruder": true, + "children": + { + "switch_extruder_retraction_speed": + { + "label": "Nozzle Switch Retract Speed", + "description": "The speed at which the filament is retracted during a nozzle switch retract.", + "type": "float", + "unit": "mm/s", + "enabled": "retraction_enable and extruders_enabled_count > 1", + "default_value": 20, + "value": "switch_extruder_retraction_speeds", + "minimum_value": "0.1", + "minimum_value_warning": "1", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "maximum_value_warning": "70", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "switch_extruder_prime_speed": + { + "label": "Nozzle Switch Prime Speed", + "description": "The speed at which the filament is pushed back after a nozzle switch retraction.", + "type": "float", + "unit": "mm/s", + "enabled": "retraction_enable and extruders_enabled_count > 1", + "default_value": 20, + "value": "switch_extruder_retraction_speeds", + "minimum_value": "0.1", + "minimum_value_warning": "1", + "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')", + "maximum_value_warning": "70", + "settable_per_mesh": false, + "settable_per_extruder": true + } + } + }, + "switch_extruder_extra_prime_amount": + { + "label": "Nozzle Switch Extra Prime Amount", + "description": "Extra material to prime after nozzle switching.", + "type": "float", + "unit": "mm³", + "default_value": 0, + "minimum_value_warning": "0", + "maximum_value_warning": "100", + "enabled": "retraction_enable and extruders_enabled_count > 1", + "settable_per_mesh": false, + "settable_per_extruder": true } } }, diff --git a/resources/extruders/beamup_s_extruder_0.def.json b/resources/extruders/beamup_s_extruder_0.def.json new file mode 100644 index 0000000000..1df9068198 --- /dev/null +++ b/resources/extruders/beamup_s_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "beamup_s", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/meshes/beamup_s.stl b/resources/meshes/beamup_s.stl new file mode 100644 index 0000000000..bfdb5eb74c Binary files /dev/null and b/resources/meshes/beamup_s.stl differ diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index edc5ee1e0d..73c1baf2c0 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -14,11 +14,11 @@ Menu property int extruderIndex: 0 property string currentRootMaterialId: Cura.MachineManager.currentRootMaterialId[extruderIndex] - property string activeMaterialId: - { - var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex] - return (extruder === undefined) ? "" : extruder.material.id - } + property var activeExtruder: Cura.MachineManager.activeMachine.extruderList[extruderIndex] + property bool isActiveExtruderEnabled: activeExtruder === undefined ? false : activeExtruder.isEnabled + + property string activeMaterialId: activeExtruder === undefined ? false : activeExtruder.material.id + property bool updateModels: true Cura.FavoriteMaterialsModel { @@ -54,7 +54,7 @@ Menu { text: model.brand + " " + model.name checkable: true - enabled: Cura.MachineManager.activeMachine.extruderList[extruderIndex].isEnabled + enabled: isActiveExtruderEnabled checked: model.root_material_id === menu.currentRootMaterialId onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) exclusiveGroup: favoriteGroup // One favorite and one item from the others can be active at the same time. @@ -77,11 +77,7 @@ Menu { text: model.name checkable: true - enabled: - { - var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex] - return (extruder === undefined) ? false : extruder.isEnabled - } + enabled: isActiveExtruderEnabled checked: model.root_material_id === menu.currentRootMaterialId exclusiveGroup: group onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) @@ -120,11 +116,7 @@ Menu { text: model.name checkable: true - enabled: - { - var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex] - return (extruder === undefined) ? false : extruder.isEnabled - } + enabled: isActiveExtruderEnabled checked: model.id === menu.activeMaterialId exclusiveGroup: group onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 096f320a7c..c0c7772104 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -33,7 +33,7 @@ SettingItem anchors.fill: parent radius: UM.Theme.getSize("setting_control_radius").width - border.width: Math.round(UM.Theme.getSize("default_lining").width) + border.width: UM.Theme.getSize("default_lining").width border.color: { if(!enabled) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index eefcefeadf..4557bd2019 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -25,7 +25,7 @@ Item visible: true radius: UM.Theme.getSize("setting_control_radius").width - border.width: Math.round(UM.Theme.getSize("default_lining").width) + border.width: UM.Theme.getSize("default_lining").width border.color: { if (hoverMouseArea.containsMouse || clearFilterButton.containsMouse) diff --git a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml index 5a4f5ec7b7..b9bd9c4a65 100644 --- a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml +++ b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml @@ -66,7 +66,7 @@ Item { id: networkPrinterListView anchors.fill: parent - model: CuraApplication.getDiscoveredPrintersModel().discoveredPrinters + model: contentLoader.enabled ? CuraApplication.getDiscoveredPrintersModel().discoveredPrinters: undefined section.property: "modelData.sectionName" section.criteria: ViewSection.FullString diff --git a/resources/qml/WelcomePages/WizardPanel.qml b/resources/qml/WelcomePages/WizardPanel.qml index d4ec116d65..418f4848fb 100644 --- a/resources/qml/WelcomePages/WizardPanel.qml +++ b/resources/qml/WelcomePages/WizardPanel.qml @@ -71,6 +71,7 @@ Item right: parent.right } source: base.pageUrl + enabled: base.visible } } } diff --git a/resources/quality/beamup_s/beamup_s_coarse.inst.cfg b/resources/quality/beamup_s/beamup_s_coarse.inst.cfg new file mode 100644 index 0000000000..9f82b7b138 --- /dev/null +++ b/resources/quality/beamup_s/beamup_s_coarse.inst.cfg @@ -0,0 +1,40 @@ +[general] +version = 4 +name = BeamUp S Coarse +definition = beamup_s + +[metadata] +setting_version = 10 +type = quality +quality_type = coarse +weight = -3 +material = generic_pla + +[values] +layer_height = 0.30 +adhesion_type = brim +brim_line_count = 5 +infill_before_walls = False +initial_layer_line_width_factor = 120.0 +material_print_temperature = 215 +material_print_temperature_layer_0 = 230 +retraction_amount = 1.5 +retraction_speed = 30 +speed_infill = 50 +speed_layer_0 = 25 +speed_print = 50 +speed_support_interface = 50 +speed_topbottom = 50 +speed_wall_0 = 35 +speed_wall_x = 50 +support_enable = True +support_angle = 60 +support_infill_rate = 20 +support_interface_enable = True +support_interface_height = 0.60 +support_interface_pattern = zigzag +support_interface_skip_height = 0.30 +support_offset = 0.8 +support_z_distance = 0.2 +wall_thickness = 0.8 +zig_zaggify_infill = True diff --git a/resources/quality/beamup_s/beamup_s_draft.inst.cfg b/resources/quality/beamup_s/beamup_s_draft.inst.cfg new file mode 100644 index 0000000000..a696fafd2b --- /dev/null +++ b/resources/quality/beamup_s/beamup_s_draft.inst.cfg @@ -0,0 +1,40 @@ +[general] +version = 4 +name = BeamUp S Draft +definition = beamup_s + +[metadata] +setting_version = 10 +type = quality +quality_type = draft +weight = -2 +material = generic_pla + +[values] +layer_height = 0.2 +adhesion_type = brim +brim_line_count = 5 +infill_before_walls = False +initial_layer_line_width_factor = 120.0 +material_print_temperature = 210 +material_print_temperature_layer_0 = 230 +retraction_amount = 1.5 +retraction_speed = 30 +speed_infill = 45 +speed_layer_0 = 25 +speed_print = 45 +speed_support_interface = 45 +speed_topbottom = 45 +speed_wall_0 = 35 +speed_wall_x = 45 +support_enable = True +support_angle = 60 +support_infill_rate = 20 +support_interface_enable = True +support_interface_height = 0.40 +support_interface_pattern = zigzag +support_interface_skip_height = 0.20 +support_offset = 0.8 +support_z_distance = 0.2 +wall_thickness = 0.8 +zig_zaggify_infill = True diff --git a/resources/quality/beamup_s/beamup_s_extra_fine.inst.cfg b/resources/quality/beamup_s/beamup_s_extra_fine.inst.cfg new file mode 100644 index 0000000000..ee1a1cb6a7 --- /dev/null +++ b/resources/quality/beamup_s/beamup_s_extra_fine.inst.cfg @@ -0,0 +1,40 @@ +[general] +version = 4 +name = BeamUp S Extra Fine +definition = beamup_s + +[metadata] +setting_version = 10 +type = quality +quality_type = high +weight = 1 +material = generic_pla + +[values] +layer_height = 0.06 +adhesion_type = brim +brim_line_count = 5 +infill_before_walls = False +initial_layer_line_width_factor = 120.0 +material_print_temperature = 195 +material_print_temperature_layer_0 = 230 +retraction_amount = 1.5 +retraction_speed = 30 +speed_infill = 40 +speed_layer_0 = 25 +speed_print = 40 +speed_support_interface = 40 +speed_topbottom = 40 +speed_wall_0 = 30 +speed_wall_x = 40 +support_enable = True +support_angle = 60 +support_infill_rate = 20 +support_interface_enable = True +support_interface_height = 0.30 +support_interface_pattern = zigzag +support_interface_skip_height = 0.06 +support_offset = 0.8 +support_z_distance = 0.2 +wall_thickness = 0.8 +zig_zaggify_infill = True diff --git a/resources/quality/beamup_s/beamup_s_fine.inst.cfg b/resources/quality/beamup_s/beamup_s_fine.inst.cfg new file mode 100644 index 0000000000..c68f854536 --- /dev/null +++ b/resources/quality/beamup_s/beamup_s_fine.inst.cfg @@ -0,0 +1,40 @@ +[general] +version = 4 +name = BeamUp S Fine +definition = beamup_s + +[metadata] +setting_version = 10 +type = quality +quality_type = normal +weight = 0 +material = generic_pla + +[values] +layer_height = 0.1 +adhesion_type = brim +brim_line_count = 5 +infill_before_walls = False +initial_layer_line_width_factor = 120.0 +material_print_temperature = 200 +material_print_temperature_layer_0 = 230 +retraction_amount = 1.5 +retraction_speed = 30 +speed_infill = 40 +speed_layer_0 = 25 +speed_print = 40 +speed_support_interface = 40 +speed_topbottom = 40 +speed_wall_0 = 30 +speed_wall_x = 40 +support_enable = True +support_angle = 60 +support_infill_rate = 20 +support_interface_enable = True +support_interface_height = 0.30 +support_interface_pattern = zigzag +support_interface_skip_height = 0.10 +support_offset = 0.8 +support_z_distance = 0.2 +wall_thickness = 0.8 +zig_zaggify_infill = True diff --git a/resources/quality/beamup_s/beamup_s_normal.inst.cfg b/resources/quality/beamup_s/beamup_s_normal.inst.cfg new file mode 100644 index 0000000000..7b692d2cb3 --- /dev/null +++ b/resources/quality/beamup_s/beamup_s_normal.inst.cfg @@ -0,0 +1,40 @@ +[general] +version = 4 +name = BeamUp S Normal +definition = beamup_s + +[metadata] +setting_version = 10 +type = quality +quality_type = fast +weight = -1 +material = generic_pla + +[values] +layer_height = 0.15 +adhesion_type = brim +brim_line_count = 5 +infill_before_walls = False +initial_layer_line_width_factor = 120.0 +material_print_temperature = 205 +material_print_temperature_layer_0 = 230 +retraction_amount = 1.5 +retraction_speed = 30 +speed_infill = 45 +speed_layer_0 = 25 +speed_print = 45 +speed_support_interface = 45 +speed_topbottom = 45 +speed_wall_0 = 35 +speed_wall_x = 45 +support_enable = True +support_angle = 60 +support_infill_rate = 20 +support_interface_enable = True +support_interface_height = 0.45 +support_interface_pattern = zigzag +support_interface_skip_height = 0.15 +support_offset = 0.8 +support_z_distance = 0.2 +wall_thickness = 0.8 +zig_zaggify_infill = True diff --git a/run_mypy.py b/run_mypy.py index d93e1cafc8..df715bf10d 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -76,9 +76,9 @@ def main(): print("\nCommand %s failed checking. :(" % commands[i]) success_code = 1 if success_code: - print("MYPY check was compleded, but did not pass") + print("MYPY check was completed, but did not pass") else: - print("MYPY check was compleded and passed with flying colors") + print("MYPY check was completed and passed with flying colors") return success_code if __name__ == "__main__": diff --git a/tests/TestMachineManager.py b/tests/TestMachineManager.py index a5d9d314cd..64a7891197 100644 --- a/tests/TestMachineManager.py +++ b/tests/TestMachineManager.py @@ -15,6 +15,7 @@ def machine_manager(application, extruder_manager, container_registry, global_st application.getGlobalContainerStack = MagicMock(return_value = global_stack) with patch("cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance", MagicMock(return_value=container_registry)): manager = MachineManager(application) + manager._onGlobalContainerChanged() return manager