diff --git a/cura/Machines/Models/ExtrudersModel.py b/cura/Machines/Models/ExtrudersModel.py index 2677894bff..f31f7c8717 100644 --- a/cura/Machines/Models/ExtrudersModel.py +++ b/cura/Machines/Models/ExtrudersModel.py @@ -227,7 +227,7 @@ class ExtrudersModel(ListModel): "material_brand": "", "color_name": "", "material_type": "", - "material_label": "" + "material_name": "" } items.append(item) if self._items != items: diff --git a/cura_app.py b/cura_app.py index 905d8f4ee0..bcea032789 100755 --- a/cura_app.py +++ b/cura_app.py @@ -15,6 +15,10 @@ if "" in sys.path: import argparse import faulthandler import os + +# set the environment variable QT_QUICK_FLICKABLE_WHEEL_DECELERATION to 5000 as mentioned in qt6.6 update log to overcome scroll related issues +os.environ["QT_QUICK_FLICKABLE_WHEEL_DECELERATION"] = str(int(os.environ.get("QT_QUICK_FLICKABLE_WHEEL_DECELERATION", "5000"))) + if sys.platform != "linux": # Turns out the Linux build _does_ use this, but we're not making an Enterprise release for that system anyway. os.environ["QT_PLUGIN_PATH"] = "" # Security workaround: Don't need it, and introduces an attack vector, so set to nul. os.environ["QML2_IMPORT_PATH"] = "" # Security workaround: Don't need it, and introduces an attack vector, so set to nul. diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 633352d616..3a1d7ce431 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023 UltiMaker +# Copyright (c) 2024 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. import uuid @@ -63,13 +63,12 @@ class GcodeStartEndFormatter(Formatter): # will be used. Alternatively, if the expression is formatted as "{[expression], [extruder_nr]}", # then the expression will be evaluated with the extruder stack of the specified extruder_nr. - _extruder_regex = re.compile(r"^\s*(?P.*)\s*,\s*(?P\d+)\s*$") + _extruder_regex = re.compile(r"^\s*(?P.*)\s*,\s*(?P.*)\s*$") - def __init__(self, default_extruder_nr: int = -1, *, - additional_per_extruder_settings: Optional[Dict[str, Dict[str, any]]] = None) -> None: + def __init__(self, all_extruder_settings: Dict[str, Any], default_extruder_nr: int = -1) -> None: super().__init__() + self._all_extruder_settings: Dict[str, Any] = all_extruder_settings self._default_extruder_nr: int = default_extruder_nr - self._additional_per_extruder_settings: Optional[Dict[str, Dict[str, any]]] = additional_per_extruder_settings def get_field(self, field_name, args: [str], kwargs: dict) -> Tuple[str, str]: # get_field method parses all fields in the format-string and parses them individually to the get_value method. @@ -88,22 +87,32 @@ class GcodeStartEndFormatter(Formatter): if expression in post_slice_data_variables: return f"{{{expression}}}" - extruder_nr = self._default_extruder_nr + extruder_nr = str(self._default_extruder_nr) # The settings may specify a specific extruder to use. This is done by - # formatting the expression as "{expression}, {extruder_nr}". If the + # formatting the expression as "{expression}, {extruder_nr_expr}". If the # expression is formatted like this, we extract the extruder_nr and use # it to get the value from the correct extruder stack. match = self._extruder_regex.match(expression) if match: expression = match.group("expression") - extruder_nr = int(match.group("extruder_nr")) + extruder_nr_expr = match.group("extruder_nr_expr") - if self._additional_per_extruder_settings is not None and str( - extruder_nr) in self._additional_per_extruder_settings: - additional_variables = self._additional_per_extruder_settings[str(extruder_nr)] + if extruder_nr_expr.isdigit(): + extruder_nr = extruder_nr_expr + else: + # We get the value of the extruder_nr_expr from `_all_extruder_settings` dictionary + # rather than the global container stack. The `_all_extruder_settings["-1"]` is a + # dict-representation of the global container stack, with additional properties such + # as `initial_extruder_nr`. As users may enter such expressions we can't use the + # global container stack. + extruder_nr = str(self._all_extruder_settings["-1"].get(extruder_nr_expr, "-1")) + + if extruder_nr in self._all_extruder_settings: + additional_variables = self._all_extruder_settings[extruder_nr].copy() else: - additional_variables = dict() + Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings") + additional_variables = self._all_extruder_settings["-1"].copy() # Add the arguments and keyword arguments to the additional settings. These # are currently _not_ used, but they are added for consistency with the @@ -113,15 +122,17 @@ class GcodeStartEndFormatter(Formatter): for key, value in kwargs.items(): additional_variables[key] = value - if extruder_nr == -1: + if extruder_nr == "-1": container_stack = CuraApplication.getInstance().getGlobalContainerStack() else: container_stack = ExtruderManager.getInstance().getExtruderStack(extruder_nr) + if not container_stack: + Logger.warning(f"Extruder {extruder_nr} does not exist, using global settings") + container_stack = CuraApplication.getInstance().getGlobalContainerStack() setting_function = SettingFunction(expression) value = setting_function(container_stack, additional_variables=additional_variables) - return value @@ -131,12 +142,13 @@ class StartSliceJob(Job): def __init__(self, slice_message: Arcus.PythonMessage) -> None: super().__init__() - self._scene = CuraApplication.getInstance().getController().getScene() #type: Scene + self._scene: Scene = CuraApplication.getInstance().getController().getScene() self._slice_message: Arcus.PythonMessage = slice_message - self._is_cancelled = False #type: bool - self._build_plate_number = None #type: Optional[int] + self._is_cancelled: bool = False + self._build_plate_number: Optional[int] = None - self._all_extruders_settings = None #type: Optional[Dict[str, Any]] # cache for all setting values from all stacks (global & extruder) for the current machine + # cache for all setting values from all stacks (global & extruder) for the current machine + self._all_extruders_settings: Optional[Dict[str, Any]] = None def getSliceMessage(self) -> Arcus.PythonMessage: return self._slice_message @@ -477,10 +489,7 @@ class StartSliceJob(Job): # Get "replacement-keys" for the extruders. In the formatter the settings stack is used to get the # replacement values for the setting-keys. However, the values for `material_id`, `material_type`, # etc are not in the settings stack. - additional_per_extruder_settings = self._all_extruders_settings.copy() - additional_per_extruder_settings["default_extruder_nr"] = default_extruder_nr - fmt = GcodeStartEndFormatter(default_extruder_nr=default_extruder_nr, - additional_per_extruder_settings=additional_per_extruder_settings) + fmt = GcodeStartEndFormatter(self._all_extruders_settings, default_extruder_nr=default_extruder_nr) return str(fmt.format(value)) except: Logger.logException("w", "Unable to do token replacement on start/end g-code") diff --git a/resources/definitions/ultimaker_method_base.def.json b/resources/definitions/ultimaker_method_base.def.json index 4f03a8dbe1..972d69e0d3 100644 --- a/resources/definitions/ultimaker_method_base.def.json +++ b/resources/definitions/ultimaker_method_base.def.json @@ -99,7 +99,7 @@ "acceleration_print": { "enabled": false, - "value": 300 + "value": 800 }, "acceleration_print_layer_0": { @@ -234,7 +234,7 @@ "jerk_print": { "enabled": false, - "value": 12.5 + "value": 6.25 }, "jerk_print_layer_0": { @@ -279,7 +279,7 @@ "jerk_travel": { "enabled": false, - "value": 12.5 + "value": "jerk_print" }, "jerk_travel_enabled": { diff --git a/resources/extruders/ultimaker_methodx_extruder_left.def.json b/resources/extruders/ultimaker_methodx_extruder_left.def.json index 97e8a1f2c3..7051f056f3 100644 --- a/resources/extruders/ultimaker_methodx_extruder_left.def.json +++ b/resources/extruders/ultimaker_methodx_extruder_left.def.json @@ -16,6 +16,7 @@ }, "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_start_code_duration": { "default_value": 8 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.4 }, diff --git a/resources/extruders/ultimaker_methodx_extruder_right.def.json b/resources/extruders/ultimaker_methodx_extruder_right.def.json index 8a4ef33404..1fea854877 100644 --- a/resources/extruders/ultimaker_methodx_extruder_right.def.json +++ b/resources/extruders/ultimaker_methodx_extruder_right.def.json @@ -16,6 +16,7 @@ }, "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_start_code_duration": { "default_value": 8 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.4 }, diff --git a/resources/extruders/ultimaker_methodxl_extruder_left.def.json b/resources/extruders/ultimaker_methodxl_extruder_left.def.json index 2bedf9a62c..66670fe994 100644 --- a/resources/extruders/ultimaker_methodxl_extruder_left.def.json +++ b/resources/extruders/ultimaker_methodxl_extruder_left.def.json @@ -16,6 +16,7 @@ }, "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_start_code_duration": { "default_value": 10 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.4 }, diff --git a/resources/extruders/ultimaker_methodxl_extruder_right.def.json b/resources/extruders/ultimaker_methodxl_extruder_right.def.json index 2fd5b37663..9f483e39bc 100644 --- a/resources/extruders/ultimaker_methodxl_extruder_right.def.json +++ b/resources/extruders/ultimaker_methodxl_extruder_right.def.json @@ -16,6 +16,7 @@ }, "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_start_code_duration": { "default_value": 10 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, "machine_nozzle_size": { "default_value": 0.4 },