From a8f1061a02561aac9658a88910d0c475c705919d Mon Sep 17 00:00:00 2001 From: Eric McCann Date: Wed, 23 Sep 2026 08:05:01 -0400 Subject: [PATCH 1/6] Add Sovol Zero nozzle profiles and filament profiles (#15756) * Add Sovol Zero nozzle profiles and filament updates Preserve inherited tuning with Zero-only overrides so shared Sovol defaults and other printers remain unchanged. Retain migration aliases while using canonical names in compatibility references. Co-authored-by: Codex * Fix Sovol Zero bed model reference and ignored settings Point the Zero model at the shipped bed mesh. Remove unsupported filament and process keys that the loader silently discards, preserving effective tuning and the existing preset names and IDs. Bump the Sovol bundle version. Co-authored-by: Codex * Fix Sovol Zero filament identity and vector formatting Add hardened-steel nozzle variants with disjoint filament compatibility, retain generic product IDs and preserve renamed preset aliases. Convert 43 scalar vector fields to arrays without changing tuning values and bump the Sovol bundle version. Co-authored-by: Codex * Keep only shipped names in the Sovol Zero profile renames The Zero machines, processes, machine model and SPEEDBENCHY filament carried renamed_from entries for names that only ever existed inside this branch (Sovol ZERO ..., " - Brass", " - Hardened Steel"). Drop those, and keep only the redirects that matter to existing users: the historical Sovol Zero material names and the three deleted hardened-steel presets. The Sovol Zero machine model also sheds the setting_id, instantiation and from keys the model loader ignores. --------- Co-authored-by: Codex Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com> Co-authored-by: Codex Co-authored-by: SoftFever --- resources/profiles/Sovol.json | 138 ++++++++++++++-- .../filament/Generic ABS @Sovol Zero.json | 38 ++++- .../filament/Generic PC @Sovol Zero.json | 39 ++++- ...ETG @Sovol Zero Hardened Steel nozzle.json | 116 ++++++++++++++ .../filament/Generic PETG @Sovol Zero.json | 55 ++++++- ...PLA @Sovol Zero Hardened Steel nozzle.json | 110 +++++++++++++ .../filament/Generic PLA @Sovol Zero.json | 66 +++++--- .../Generic PLA SPEEDBENCHY @Sovol Zero.json | 118 ++++++++++++++ ...ilk @Sovol Zero Hardened Steel nozzle.json | 110 +++++++++++++ .../Generic PLA Silk @Sovol Zero.json | 72 +++++++-- .../filament/Generic TPU @Sovol Zero.json | 59 ++++++- .../filament/Sovol Zero PETG HS Nozzle.json | 77 --------- .../Sovol Zero PLA Basic HS Nozzle.json | 70 -------- .../Sovol Zero PLA Silk HS Nozzle.json | 70 -------- .../Sovol Zero 0.2 Hardened Steel nozzle.json | 19 +++ .../Sovol/machine/Sovol Zero 0.2 nozzle.json | 118 ++++++++++++++ .../Sovol Zero 0.4 Hardened Steel nozzle.json | 19 +++ .../Sovol/machine/Sovol Zero 0.4 nozzle.json | 22 ++- .../Sovol Zero 0.6 Hardened Steel nozzle.json | 19 +++ .../Sovol/machine/Sovol Zero 0.6 nozzle.json | 118 ++++++++++++++ .../Sovol Zero 0.8 Hardened Steel nozzle.json | 19 +++ .../Sovol/machine/Sovol Zero 0.8 nozzle.json | 118 ++++++++++++++ .../Sovol Zero 1.0 Hardened Steel nozzle.json | 19 +++ .../Sovol/machine/Sovol Zero 1.0 nozzle.json | 118 ++++++++++++++ .../profiles/Sovol/machine/Sovol Zero.json | 4 +- ...0.06mm Quality @Sovol Zero 0.2 nozzle.json | 36 +++++ ....10mm Standard @Sovol Zero 0.2 nozzle.json | 36 +++++ ...0.12mm Quality @Sovol Zero 0.4 nozzle.json | 35 ++++ .../0.14mm Fast @Sovol Zero 0.2 nozzle.json | 36 +++++ ...0.15mm Quality @Sovol Zero 0.6 nozzle.json | 34 ++++ ...0.20mm Quality @Sovol Zero 0.8 nozzle.json | 42 +++++ ....20mm Standard @Sovol Zero 0.4 nozzle.json | 149 +++--------------- ...0.25mm Quality @Sovol Zero 1.0 nozzle.json | 79 ++++++++++ ...mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json | 85 ++++++++++ .../0.28mm Fast @Sovol Zero 0.4 nozzle.json | 39 +++++ ....30mm Standard @Sovol Zero 0.6 nozzle.json | 35 ++++ ....40mm Standard @Sovol Zero 0.8 nozzle.json | 42 +++++ .../0.42mm Fast @Sovol Zero 0.6 nozzle.json | 39 +++++ ....50mm Standard @Sovol Zero 1.0 nozzle.json | 87 ++++++++++ .../0.56mm Fast @Sovol Zero 0.8 nozzle.json | 40 +++++ .../0.70mm Fast @Sovol Zero 1.0 nozzle.json | 33 ++++ .../Sovol/process/fdm_process_zero.json | 73 +++++++++ 42 files changed, 2220 insertions(+), 431 deletions(-) create mode 100644 resources/profiles/Sovol/filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/filament/Generic PLA SPEEDBENCHY @Sovol Zero.json create mode 100644 resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json delete mode 100644 resources/profiles/Sovol/filament/Sovol Zero PETG HS Nozzle.json delete mode 100644 resources/profiles/Sovol/filament/Sovol Zero PLA Basic HS Nozzle.json delete mode 100644 resources/profiles/Sovol/filament/Sovol Zero PLA Silk HS Nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.2 Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.2 nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.4 Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.6 Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.6 nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.8 Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 0.8 nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 1.0 Hardened Steel nozzle.json create mode 100644 resources/profiles/Sovol/machine/Sovol Zero 1.0 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.06mm Quality @Sovol Zero 0.2 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.10mm Standard @Sovol Zero 0.2 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.12mm Quality @Sovol Zero 0.4 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.14mm Fast @Sovol Zero 0.2 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.15mm Quality @Sovol Zero 0.6 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.20mm Quality @Sovol Zero 0.8 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.25mm Quality @Sovol Zero 1.0 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.28mm Fast @Sovol Zero 0.4 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.30mm Standard @Sovol Zero 0.6 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.40mm Standard @Sovol Zero 0.8 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.42mm Fast @Sovol Zero 0.6 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.50mm Standard @Sovol Zero 1.0 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.56mm Fast @Sovol Zero 0.8 nozzle.json create mode 100644 resources/profiles/Sovol/process/0.70mm Fast @Sovol Zero 1.0 nozzle.json create mode 100644 resources/profiles/Sovol/process/fdm_process_zero.json diff --git a/resources/profiles/Sovol.json b/resources/profiles/Sovol.json index 7f08417ed7..81dab20239 100644 --- a/resources/profiles/Sovol.json +++ b/resources/profiles/Sovol.json @@ -1,7 +1,7 @@ { "name": "Sovol", "url": "", - "version": "02.04.00.04", + "version": "02.04.00.07", "force_update": "0", "description": "Sovol configurations", "machine_model_list": [ @@ -167,10 +167,6 @@ "name": "0.20mm Standard @Sovol SV08 MAX 0.4 nozzle", "sub_path": "process/0.20mm Standard @Sovol SV08 MAX 0.4 nozzle.json" }, - { - "name": "0.20mm Standard @Sovol Zero 0.4 nozzle", - "sub_path": "process/0.20mm Standard @Sovol Zero 0.4 nozzle.json" - }, { "name": "0.28mm Fast @Sovol SV06 ACE", "sub_path": "process/0.28mm Fast @Sovol SV06 ACE 0.4 nozzle.json" @@ -198,6 +194,74 @@ { "name": "0.40mm Standard @Sovol SV08 MAX 0.8 nozzle", "sub_path": "process/0.40mm Standard @Sovol SV08 MAX 0.8 nozzle.json" + }, + { + "name": "fdm_process_zero", + "sub_path": "process/fdm_process_zero.json" + }, + { + "name": "0.06mm Quality @Sovol Zero 0.2 nozzle", + "sub_path": "process/0.06mm Quality @Sovol Zero 0.2 nozzle.json" + }, + { + "name": "0.10mm Standard @Sovol Zero 0.2 nozzle", + "sub_path": "process/0.10mm Standard @Sovol Zero 0.2 nozzle.json" + }, + { + "name": "0.12mm Quality @Sovol Zero 0.4 nozzle", + "sub_path": "process/0.12mm Quality @Sovol Zero 0.4 nozzle.json" + }, + { + "name": "0.14mm Fast @Sovol Zero 0.2 nozzle", + "sub_path": "process/0.14mm Fast @Sovol Zero 0.2 nozzle.json" + }, + { + "name": "0.15mm Quality @Sovol Zero 0.6 nozzle", + "sub_path": "process/0.15mm Quality @Sovol Zero 0.6 nozzle.json" + }, + { + "name": "0.20mm Quality @Sovol Zero 0.8 nozzle", + "sub_path": "process/0.20mm Quality @Sovol Zero 0.8 nozzle.json" + }, + { + "name": "0.20mm Standard @Sovol Zero 0.4 nozzle", + "sub_path": "process/0.20mm Standard @Sovol Zero 0.4 nozzle.json" + }, + { + "name": "0.25mm Quality @Sovol Zero 1.0 nozzle", + "sub_path": "process/0.25mm Quality @Sovol Zero 1.0 nozzle.json" + }, + { + "name": "0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle", + "sub_path": "process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json" + }, + { + "name": "0.28mm Fast @Sovol Zero 0.4 nozzle", + "sub_path": "process/0.28mm Fast @Sovol Zero 0.4 nozzle.json" + }, + { + "name": "0.30mm Standard @Sovol Zero 0.6 nozzle", + "sub_path": "process/0.30mm Standard @Sovol Zero 0.6 nozzle.json" + }, + { + "name": "0.40mm Standard @Sovol Zero 0.8 nozzle", + "sub_path": "process/0.40mm Standard @Sovol Zero 0.8 nozzle.json" + }, + { + "name": "0.42mm Fast @Sovol Zero 0.6 nozzle", + "sub_path": "process/0.42mm Fast @Sovol Zero 0.6 nozzle.json" + }, + { + "name": "0.50mm Standard @Sovol Zero 1.0 nozzle", + "sub_path": "process/0.50mm Standard @Sovol Zero 1.0 nozzle.json" + }, + { + "name": "0.56mm Fast @Sovol Zero 0.8 nozzle", + "sub_path": "process/0.56mm Fast @Sovol Zero 0.8 nozzle.json" + }, + { + "name": "0.70mm Fast @Sovol Zero 1.0 nozzle", + "sub_path": "process/0.70mm Fast @Sovol Zero 1.0 nozzle.json" } ], "filament_list": [ @@ -249,6 +313,10 @@ "name": "Generic PETG @Sovol Zero", "sub_path": "filament/Generic PETG @Sovol Zero.json" }, + { + "name": "Generic PETG @Sovol Zero Hardened Steel nozzle", + "sub_path": "filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json" + }, { "name": "Generic PLA @Sovol SV06 ACE", "sub_path": "filament/Generic PLA @Sovol SV06 ACE.json" @@ -277,6 +345,14 @@ "name": "Generic PLA @Sovol Zero", "sub_path": "filament/Generic PLA @Sovol Zero.json" }, + { + "name": "Generic PLA @Sovol Zero Hardened Steel nozzle", + "sub_path": "filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json" + }, + { + "name": "Generic PLA SPEEDBENCHY @Sovol Zero", + "sub_path": "filament/Generic PLA SPEEDBENCHY @Sovol Zero.json" + }, { "name": "Generic PLA Silk @Sovol SV08 MAX", "sub_path": "filament/Generic PLA Silk @Sovol SV08 MAX.json" @@ -285,6 +361,10 @@ "name": "Generic PLA Silk @Sovol Zero", "sub_path": "filament/Generic PLA Silk @Sovol Zero.json" }, + { + "name": "Generic PLA Silk @Sovol Zero Hardened Steel nozzle", + "sub_path": "filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json" + }, { "name": "Generic TPU @Sovol SV06 ACE", "sub_path": "filament/Generic TPU @Sovol SV06 ACE.json" @@ -312,18 +392,6 @@ { "name": "SUNLU PETG @Sovol SV08 MAX", "sub_path": "filament/SUNLU PETG @Sovol SV08 MAX.json" - }, - { - "name": "Sovol Zero PETG HS Nozzle", - "sub_path": "filament/Sovol Zero PETG HS Nozzle.json" - }, - { - "name": "Sovol Zero PLA Basic HS Nozzle", - "sub_path": "filament/Sovol Zero PLA Basic HS Nozzle.json" - }, - { - "name": "Sovol Zero PLA Silk HS Nozzle", - "sub_path": "filament/Sovol Zero PLA Silk HS Nozzle.json" } ], "machine_list": [ @@ -415,9 +483,45 @@ "name": "Sovol SV08 MAX 0.8 nozzle", "sub_path": "machine/Sovol SV08 MAX 0.8 nozzle.json" }, + { + "name": "Sovol Zero 0.2 nozzle", + "sub_path": "machine/Sovol Zero 0.2 nozzle.json" + }, { "name": "Sovol Zero 0.4 nozzle", "sub_path": "machine/Sovol Zero 0.4 nozzle.json" + }, + { + "name": "Sovol Zero 0.6 nozzle", + "sub_path": "machine/Sovol Zero 0.6 nozzle.json" + }, + { + "name": "Sovol Zero 0.8 nozzle", + "sub_path": "machine/Sovol Zero 0.8 nozzle.json" + }, + { + "name": "Sovol Zero 1.0 nozzle", + "sub_path": "machine/Sovol Zero 1.0 nozzle.json" + }, + { + "name": "Sovol Zero 0.2 Hardened Steel nozzle", + "sub_path": "machine/Sovol Zero 0.2 Hardened Steel nozzle.json" + }, + { + "name": "Sovol Zero 0.4 Hardened Steel nozzle", + "sub_path": "machine/Sovol Zero 0.4 Hardened Steel nozzle.json" + }, + { + "name": "Sovol Zero 0.6 Hardened Steel nozzle", + "sub_path": "machine/Sovol Zero 0.6 Hardened Steel nozzle.json" + }, + { + "name": "Sovol Zero 0.8 Hardened Steel nozzle", + "sub_path": "machine/Sovol Zero 0.8 Hardened Steel nozzle.json" + }, + { + "name": "Sovol Zero 1.0 Hardened Steel nozzle", + "sub_path": "machine/Sovol Zero 1.0 Hardened Steel nozzle.json" } ] } diff --git a/resources/profiles/Sovol/filament/Generic ABS @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic ABS @Sovol Zero.json index 3b737e2a18..7c24b7a0aa 100644 --- a/resources/profiles/Sovol/filament/Generic ABS @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic ABS @Sovol Zero.json @@ -1,10 +1,11 @@ { "type": "filament", "name": "Generic ABS @Sovol Zero", - "inherits": "Generic ABS @System", "renamed_from": "Sovol Zero ABS", + "inherits": "fdm_filament_abs", "from": "system", "setting_id": "g6sSyyIFYJUzlXsp", + "filament_id": "OFY9muEs", "instantiation": "true", "filament_flow_ratio": [ "0.98" @@ -73,6 +74,39 @@ "0" ], "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ], + "cool_plate_temp": [ + "80" + ], + "eng_plate_temp": [ + "80" + ], + "textured_plate_temp": [ + "80" + ], + "cool_plate_temp_initial_layer": [ + "80" + ], + "eng_plate_temp_initial_layer": [ + "80" + ], + "textured_plate_temp_initial_layer": [ + "80" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_density": [ + "1.10" ] } diff --git a/resources/profiles/Sovol/filament/Generic PC @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic PC @Sovol Zero.json index dd0eb60594..832deb1368 100644 --- a/resources/profiles/Sovol/filament/Generic PC @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic PC @Sovol Zero.json @@ -1,11 +1,12 @@ { "type": "filament", + "filament_id": "OFLakOUI", + "setting_id": "yRKCiPMN6fxibcyg", "name": "Generic PC @Sovol Zero", - "inherits": "Generic PC @System", "renamed_from": "Sovol Zero PC", "from": "system", - "setting_id": "yRKCiPMN6fxibcyg", "instantiation": "true", + "inherits": "fdm_filament_pc", "filament_flow_ratio": [ "0.98" ], @@ -13,7 +14,16 @@ "21" ], "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" ], "nozzle_temperature_initial_layer": [ "290" @@ -51,7 +61,9 @@ "slow_down_min_speed": [ "10" ], - "dont_slow_down_outer_wall": "0", + "dont_slow_down_outer_wall": [ + "0" + ], "overhang_fan_speed": [ "20" ], @@ -61,8 +73,19 @@ "temperature_vitrification": [ "60" ], - "additional_cooling_fan_speed": "0", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "50", - "complete_print_exhaust_fan_speed": "50" + "additional_cooling_fan_speed": [ + "0" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "50" + ], + "complete_print_exhaust_fan_speed": [ + "50" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ] } diff --git a/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json b/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json new file mode 100644 index 0000000000..ef6a6324e3 --- /dev/null +++ b/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json @@ -0,0 +1,116 @@ +{ + "type": "filament", + "filament_id": "OFYPdQJh", + "setting_id": "d9QbCESNz3ZLU6eu", + "name": "Generic PETG @Sovol Zero Hardened Steel nozzle", + "renamed_from": "Sovol Zero PETG HS Nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_filament_pet", + "filament_flow_ratio": [ + "0.98" + ], + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.048" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "nozzle_temperature_initial_layer": [ + "265" + ], + "nozzle_temperature": [ + "250" + ], + "nozzle_temperature_range_low": [ + "230" + ], + "nozzle_temperature_range_high": [ + "280" + ], + "hot_plate_temp": [ + "85" + ], + "hot_plate_temp_initial_layer": [ + "85" + ], + "fan_min_speed": [ + "10" + ], + "fan_max_speed": [ + "40" + ], + "fan_cooling_layer_time": [ + "50" + ], + "full_fan_speed_layer": [ + "3" + ], + "slow_down_layer_time": [ + "10" + ], + "slow_down_min_speed": [ + "10" + ], + "overhang_fan_speed": [ + "70" + ], + "overhang_fan_threshold": [ + "10%" + ], + "temperature_vitrification": [ + "60" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "filament_retraction_length": [ + "0.5" + ], + "filament_z_hop": [ + "0.4" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "50" + ], + "complete_print_exhaust_fan_speed": [ + "50" + ], + "compatible_printers": [ + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ], + "cool_plate_temp": [ + "85" + ], + "eng_plate_temp": [ + "85" + ], + "textured_plate_temp": [ + "85" + ], + "cool_plate_temp_initial_layer": [ + "85" + ], + "eng_plate_temp_initial_layer": [ + "85" + ], + "textured_plate_temp_initial_layer": [ + "85" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ] +} diff --git a/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero.json index a223521d25..b9632637ad 100644 --- a/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic PETG @Sovol Zero.json @@ -1,16 +1,21 @@ { "type": "filament", + "filament_id": "OFYPdQJh", + "setting_id": "i4OW2eAtXOKdtVNj", "name": "Generic PETG @Sovol Zero", - "inherits": "Generic PETG @System", "renamed_from": "Sovol Zero PETG", "from": "system", - "setting_id": "i4OW2eAtXOKdtVNj", "instantiation": "true", + "inherits": "fdm_filament_pet", "filament_flow_ratio": [ "1.0348" ], - "enable_pressure_advance": "1", - "pressure_advance": "0.046", + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.046" + ], "filament_max_volumetric_speed": [ "15" ], @@ -68,10 +73,44 @@ "filament_z_hop": [ "0.4" ], - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "50", - "complete_print_exhaust_fan_speed": "50", + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "50" + ], + "complete_print_exhaust_fan_speed": [ + "50" + ], "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle" + ], + "cool_plate_temp": [ + "85" + ], + "eng_plate_temp": [ + "85" + ], + "textured_plate_temp": [ + "85" + ], + "cool_plate_temp_initial_layer": [ + "85" + ], + "eng_plate_temp_initial_layer": [ + "85" + ], + "textured_plate_temp_initial_layer": [ + "85" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" ] } diff --git a/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json b/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json new file mode 100644 index 0000000000..bba0cbfb51 --- /dev/null +++ b/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json @@ -0,0 +1,110 @@ +{ + "type": "filament", + "filament_id": "OFDSrzZ8", + "setting_id": "nZgETe4CTpicEjQX", + "name": "Generic PLA @Sovol Zero Hardened Steel nozzle", + "renamed_from": "Sovol Zero PLA Basic HS Nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_filament_pla", + "filament_flow_ratio": [ + "1.0348" + ], + "filament_max_volumetric_speed": [ + "21" + ], + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.03" + ], + "compatible_printers": [ + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ], + "nozzle_temperature_initial_layer": [ + "245" + ], + "nozzle_temperature": [ + "230" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "nozzle_temperature_range_high": [ + "250" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "fan_min_speed": [ + "70" + ], + "fan_max_speed": [ + "100" + ], + "fan_cooling_layer_time": [ + "80" + ], + "full_fan_speed_layer": [ + "3" + ], + "slow_down_layer_time": [ + "5" + ], + "slow_down_min_speed": [ + "10" + ], + "dont_slow_down_outer_wall": [ + "0" + ], + "overhang_fan_speed": [ + "100" + ], + "overhang_fan_threshold": [ + "50%" + ], + "temperature_vitrification": [ + "60" + ], + "additional_cooling_fan_speed": [ + "75%" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "80%" + ], + "complete_print_exhaust_fan_speed": [ + "80%" + ], + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ] +} diff --git a/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero.json index 131867f6b8..c8424af4f4 100644 --- a/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic PLA @Sovol Zero.json @@ -1,21 +1,24 @@ { "type": "filament", + "filament_id": "OFDSrzZ8", + "setting_id": "NNDerIjh7qtuh1I3", "name": "Generic PLA @Sovol Zero", - "inherits": "Generic PLA @System", "renamed_from": "Sovol Zero PLA Basic", "from": "system", - "setting_id": "NNDerIjh7qtuh1I3", "instantiation": "true", + "inherits": "fdm_filament_pla", "filament_flow_ratio": [ "0.98" ], "filament_max_volumetric_speed": [ - "21" + "25" ], - "enable_pressure_advance": "1", - "pressure_advance": "0.032", "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle" ], "nozzle_temperature_initial_layer": [ "230" @@ -24,28 +27,28 @@ "210" ], "nozzle_temperature_range_low": [ - "190" + "180" ], "nozzle_temperature_range_high": [ - "250" + "240" ], "hot_plate_temp": [ - "65" + "60" ], "hot_plate_temp_initial_layer": [ - "65" + "60" ], "fan_min_speed": [ - "70" + "100" ], "fan_max_speed": [ "100" ], "fan_cooling_layer_time": [ - "80" + "60" ], "full_fan_speed_layer": [ - "3" + "2" ], "slow_down_layer_time": [ "5" @@ -53,18 +56,43 @@ "slow_down_min_speed": [ "10" ], - "dont_slow_down_outer_wall": "0", "overhang_fan_speed": [ "100" ], "overhang_fan_threshold": [ - "50%" + "10%" ], "temperature_vitrification": [ + "50" + ], + "filament_z_hop": [ + "0.4" + ], + "filament_retraction_length": [ + "0.4" + ], + "filament_diameter": [ + "1.75" + ], + "cool_plate_temp": [ "60" ], - "additional_cooling_fan_speed": "75%", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "80%", - "complete_print_exhaust_fan_speed": "80%" + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ] } diff --git a/resources/profiles/Sovol/filament/Generic PLA SPEEDBENCHY @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic PLA SPEEDBENCHY @Sovol Zero.json new file mode 100644 index 0000000000..a9aefc6bd2 --- /dev/null +++ b/resources/profiles/Sovol/filament/Generic PLA SPEEDBENCHY @Sovol Zero.json @@ -0,0 +1,118 @@ +{ + "type": "filament", + "filament_id": "OFIUkWYN", + "setting_id": "MC2InZ7iKDjIGike", + "name": "Generic PLA SPEEDBENCHY @Sovol Zero", + "from": "system", + "instantiation": "true", + "inherits": "fdm_filament_pla", + "filament_flow_ratio": [ + "1" + ], + "filament_max_volumetric_speed": [ + "50" + ], + "compatible_printers": [ + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle" + ], + "nozzle_temperature_initial_layer": [ + "245" + ], + "nozzle_temperature": [ + "225" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "nozzle_temperature_range_high": [ + "250" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.032" + ], + "fan_min_speed": [ + "100" + ], + "fan_max_speed": [ + "100" + ], + "fan_cooling_layer_time": [ + "30" + ], + "full_fan_speed_layer": [ + "3" + ], + "slow_down_layer_time": [ + "1.7" + ], + "slow_down_min_speed": [ + "40" + ], + "overhang_fan_speed": [ + "100" + ], + "overhang_fan_threshold": [ + "75%" + ], + "additional_cooling_fan_speed": [ + "100" + ], + "filament_z_hop": [ + "0" + ], + "filament_retraction_length": [ + "0.35" + ], + "filament_retraction_speed": [ + "90" + ], + "filament_deretraction_speed": [ + "90" + ], + "filament_retract_before_wipe": [ + "0%" + ], + "filament_wipe_distance": [ + "2" + ], + "filament_retract_when_changing_layer": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ], + "temperature_vitrification": [ + "100" + ] +} diff --git a/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json b/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json new file mode 100644 index 0000000000..7347fa08de --- /dev/null +++ b/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json @@ -0,0 +1,110 @@ +{ + "type": "filament", + "filament_id": "OFesA6rF", + "setting_id": "LA8X1RsMdV2xNT1o", + "name": "Generic PLA Silk @Sovol Zero Hardened Steel nozzle", + "renamed_from": "Sovol Zero PLA Silk HS Nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_filament_pla", + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.027" + ], + "compatible_printers": [ + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ], + "nozzle_temperature_initial_layer": [ + "245" + ], + "nozzle_temperature": [ + "230" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "nozzle_temperature_range_high": [ + "250" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "fan_min_speed": [ + "70" + ], + "fan_max_speed": [ + "100" + ], + "fan_cooling_layer_time": [ + "80" + ], + "full_fan_speed_layer": [ + "3" + ], + "slow_down_layer_time": [ + "5" + ], + "slow_down_min_speed": [ + "10" + ], + "dont_slow_down_outer_wall": [ + "0" + ], + "overhang_fan_speed": [ + "100" + ], + "overhang_fan_threshold": [ + "50%" + ], + "temperature_vitrification": [ + "60" + ], + "additional_cooling_fan_speed": [ + "75%" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "80%" + ], + "complete_print_exhaust_fan_speed": [ + "80%" + ], + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ] +} diff --git a/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero.json index 5b46a92d64..6c9c27a00a 100644 --- a/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic PLA Silk @Sovol Zero.json @@ -1,27 +1,30 @@ { "type": "filament", + "filament_id": "OFesA6rF", + "setting_id": "Se2yKerHRStYtWf5", "name": "Generic PLA Silk @Sovol Zero", - "inherits": "Generic PLA Silk @System", "renamed_from": "Sovol Zero PLA Silk", "from": "system", - "setting_id": "Se2yKerHRStYtWf5", "instantiation": "true", - "filament_multitool_ramming_flow": [ - "20" - ], - "filament_retraction_length": [ - "nil" - ], + "inherits": "fdm_filament_pla", "filament_flow_ratio": [ "0.98" ], "filament_max_volumetric_speed": [ "15" ], - "enable_pressure_advance": "1", - "pressure_advance": "0.029", + "enable_pressure_advance": [ + "1" + ], + "pressure_advance": [ + "0.029" + ], "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle" ], "nozzle_temperature_initial_layer": [ "245" @@ -59,7 +62,9 @@ "slow_down_min_speed": [ "10" ], - "dont_slow_down_outer_wall": "0", + "dont_slow_down_outer_wall": [ + "0" + ], "overhang_fan_speed": [ "100" ], @@ -69,8 +74,43 @@ "temperature_vitrification": [ "60" ], - "additional_cooling_fan_speed": "75%", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "80%", - "complete_print_exhaust_fan_speed": "80%" + "additional_cooling_fan_speed": [ + "75%" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "80%" + ], + "complete_print_exhaust_fan_speed": [ + "80%" + ], + "filament_multitool_ramming_flow": [ + "20" + ], + "filament_retraction_length": [ + "nil" + ], + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ] } diff --git a/resources/profiles/Sovol/filament/Generic TPU @Sovol Zero.json b/resources/profiles/Sovol/filament/Generic TPU @Sovol Zero.json index 8c7c18c523..8624043cf9 100644 --- a/resources/profiles/Sovol/filament/Generic TPU @Sovol Zero.json +++ b/resources/profiles/Sovol/filament/Generic TPU @Sovol Zero.json @@ -1,11 +1,12 @@ { "type": "filament", + "filament_id": "OFgbpcy9", + "setting_id": "MlY6WQ41FE8zDPSV", "name": "Generic TPU @Sovol Zero", - "inherits": "Generic TPU @System", "renamed_from": "Sovol Zero TPU", "from": "system", - "setting_id": "MlY6WQ41FE8zDPSV", "instantiation": "true", + "inherits": "fdm_filament_tpu", "filament_flow_ratio": [ "0.98" ], @@ -60,11 +61,55 @@ "filament_z_hop": [ "0.4" ], - "additional_cooling_fan_speed": "50", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "100", - "complete_print_exhaust_fan_speed": "50", + "additional_cooling_fan_speed": [ + "50" + ], + "activate_air_filtration": [ + "1" + ], + "during_print_exhaust_fan_speed": [ + "100" + ], + "complete_print_exhaust_fan_speed": [ + "50" + ], "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.8 nozzle", + "Sovol Zero 1.0 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ], + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "60" + ], + "textured_plate_temp": [ + "60" + ], + "cool_plate_temp_initial_layer": [ + "55" + ], + "eng_plate_temp_initial_layer": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_retraction_length": [ + "nil" + ], + "filament_start_gcode": [ + "; filament start gcode\n" ] } diff --git a/resources/profiles/Sovol/filament/Sovol Zero PETG HS Nozzle.json b/resources/profiles/Sovol/filament/Sovol Zero PETG HS Nozzle.json deleted file mode 100644 index ce68719ba9..0000000000 --- a/resources/profiles/Sovol/filament/Sovol Zero PETG HS Nozzle.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "type": "filament", - "name": "Sovol Zero PETG HS Nozzle", - "inherits": "Generic PETG @System", - "from": "system", - "setting_id": "AfxHmpdOkMDJa2fk", - "filament_id": "OFymnal9", - "instantiation": "true", - "filament_flow_ratio": [ - "0.98" - ], - "enable_pressure_advance": "1", - "pressure_advance": "0.048", - "filament_max_volumetric_speed": [ - "15" - ], - "nozzle_temperature_initial_layer": [ - "265" - ], - "nozzle_temperature": [ - "250" - ], - "nozzle_temperature_range_low": [ - "230" - ], - "nozzle_temperature_range_high": [ - "280" - ], - "hot_plate_temp": [ - "85" - ], - "hot_plate_temp_initial_layer": [ - "85" - ], - "fan_min_speed": [ - "10" - ], - "fan_max_speed": [ - "40" - ], - "fan_cooling_layer_time": [ - "50" - ], - "full_fan_speed_layer": [ - "3" - ], - "slow_down_layer_time": [ - "10" - ], - "slow_down_min_speed": [ - "10" - ], - "overhang_fan_speed": [ - "70" - ], - "overhang_fan_threshold": [ - "10%" - ], - "temperature_vitrification": [ - "60" - ], - "close_fan_the_first_x_layers": [ - "1" - ], - "filament_retraction_length": [ - "0.5" - ], - "filament_z_hop": [ - "0.4" - ], - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "50", - "complete_print_exhaust_fan_speed": "50", - "compatible_printers": [ - "Sovol Zero 0.4 nozzle" - ] -} diff --git a/resources/profiles/Sovol/filament/Sovol Zero PLA Basic HS Nozzle.json b/resources/profiles/Sovol/filament/Sovol Zero PLA Basic HS Nozzle.json deleted file mode 100644 index 6dfb630e0a..0000000000 --- a/resources/profiles/Sovol/filament/Sovol Zero PLA Basic HS Nozzle.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "type": "filament", - "name": "Sovol Zero PLA Basic HS Nozzle", - "inherits": "Generic PLA @System", - "from": "system", - "setting_id": "i9wDnSEIrOBPbOZl", - "filament_id": "OFzB4uOs", - "instantiation": "true", - "filament_flow_ratio": [ - "1.0348" - ], - "filament_max_volumetric_speed": [ - "21" - ], - "enable_pressure_advance": "1", - "pressure_advance": "0.03", - "compatible_printers": [ - "Sovol Zero 0.4 nozzle" - ], - "nozzle_temperature_initial_layer": [ - "245" - ], - "nozzle_temperature": [ - "230" - ], - "nozzle_temperature_range_low": [ - "190" - ], - "nozzle_temperature_range_high": [ - "250" - ], - "hot_plate_temp": [ - "65" - ], - "hot_plate_temp_initial_layer": [ - "65" - ], - "fan_min_speed": [ - "70" - ], - "fan_max_speed": [ - "100" - ], - "fan_cooling_layer_time": [ - "80" - ], - "full_fan_speed_layer": [ - "3" - ], - "slow_down_layer_time": [ - "5" - ], - "slow_down_min_speed": [ - "10" - ], - "dont_slow_down_outer_wall": "0", - "overhang_fan_speed": [ - "100" - ], - "overhang_fan_threshold": [ - "50%" - ], - "temperature_vitrification": [ - "60" - ], - "additional_cooling_fan_speed": "75%", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "80%", - "complete_print_exhaust_fan_speed": "80%" -} diff --git a/resources/profiles/Sovol/filament/Sovol Zero PLA Silk HS Nozzle.json b/resources/profiles/Sovol/filament/Sovol Zero PLA Silk HS Nozzle.json deleted file mode 100644 index 97e4050b8c..0000000000 --- a/resources/profiles/Sovol/filament/Sovol Zero PLA Silk HS Nozzle.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "type": "filament", - "name": "Sovol Zero PLA Silk HS Nozzle", - "inherits": "Generic PLA @System", - "from": "system", - "setting_id": "XxEJBNFLRltR2Xwn", - "filament_id": "OFAO9A7J", - "instantiation": "true", - "filament_flow_ratio": [ - "0.98" - ], - "filament_max_volumetric_speed": [ - "15" - ], - "enable_pressure_advance": "1", - "pressure_advance": "0.027", - "compatible_printers": [ - "Sovol Zero 0.4 nozzle" - ], - "nozzle_temperature_initial_layer": [ - "245" - ], - "nozzle_temperature": [ - "230" - ], - "nozzle_temperature_range_low": [ - "190" - ], - "nozzle_temperature_range_high": [ - "250" - ], - "hot_plate_temp": [ - "65" - ], - "hot_plate_temp_initial_layer": [ - "65" - ], - "fan_min_speed": [ - "70" - ], - "fan_max_speed": [ - "100" - ], - "fan_cooling_layer_time": [ - "80" - ], - "full_fan_speed_layer": [ - "3" - ], - "slow_down_layer_time": [ - "5" - ], - "slow_down_min_speed": [ - "10" - ], - "dont_slow_down_outer_wall": "0", - "overhang_fan_speed": [ - "100" - ], - "overhang_fan_threshold": [ - "50%" - ], - "temperature_vitrification": [ - "60" - ], - "additional_cooling_fan_speed": "75%", - "activate_air_filtration": "1", - "during_print_exhaust_fan_speed": "80%", - "complete_print_exhaust_fan_speed": "80%" -} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.2 Hardened Steel nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.2 Hardened Steel nozzle.json new file mode 100644 index 0000000000..89ee9c1c09 --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.2 Hardened Steel nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "machine", + "name": "Sovol Zero 0.2 Hardened Steel nozzle", + "inherits": "Sovol Zero 0.2 nozzle", + "from": "system", + "setting_id": "OkvEInEyzUUJzw9K", + "instantiation": "true", + "printer_model": "Sovol Zero", + "printer_variant": "0.2HS", + "nozzle_diameter": [ + "0.2" + ], + "default_filament_profile": [ + "Generic PLA @Sovol Zero Hardened Steel nozzle" + ], + "nozzle_type": [ + "hardened_steel" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.2 nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.2 nozzle.json new file mode 100644 index 0000000000..33fb16508a --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.2 nozzle.json @@ -0,0 +1,118 @@ +{ + "type": "machine", + "setting_id": "MAF2n6b8uoY92qVH", + "name": "Sovol Zero 0.2 nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_machine_common", + "printer_model": "Sovol Zero", + "default_print_profile": "0.10mm Standard @Sovol Zero 0.2 nozzle", + "printer_variant": "0.2", + "nozzle_diameter": [ + "0.2" + ], + "min_layer_height": [ + "0.04" + ], + "max_layer_height": [ + "0.2" + ], + "retract_before_wipe": [ + "0%" + ], + "printable_area": [ + "0x0", + "152.4x0", + "152.4x152.4", + "0x152.4" + ], + "printable_height": "152.4", + "gcode_flavor": "klipper", + "retraction_length": [ + "1.8" + ], + "machine_max_speed_e": [ + "50" + ], + "machine_max_speed_x": [ + "1200" + ], + "machine_max_speed_y": [ + "1200" + ], + "machine_max_speed_z": [ + "30" + ], + "machine_max_acceleration_e": [ + "20000" + ], + "machine_max_acceleration_extruding": [ + "40000" + ], + "machine_max_acceleration_retracting": [ + "20000" + ], + "machine_max_acceleration_travel": [ + "40000" + ], + "machine_max_acceleration_x": [ + "40000" + ], + "machine_max_acceleration_y": [ + "40000" + ], + "machine_max_acceleration_z": [ + "1000" + ], + "machine_max_jerk_e": [ + "2.5" + ], + "machine_max_jerk_x": [ + "5" + ], + "machine_max_jerk_y": [ + "5" + ], + "machine_max_jerk_z": [ + "0.5" + ], + "z_hop": [ + "0.6" + ], + "retraction_speed": [ + "40" + ], + "deretraction_speed": [ + "40" + ], + "retraction_minimum_travel": [ + "0" + ], + "retract_length_toolchange": [ + "2" + ], + "wipe": [ + "1" + ], + "wipe_distance": [ + "3" + ], + "z_hop_types": [ + "Auto Lift" + ], + "thumbnails": [ + "300x300", + "32x32" + ], + "retract_lift_below": [ + "150" + ], + "auxiliary_fan": "1", + "thumbnails_format": "PNG", + "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]\n", + "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", + "machine_end_gcode": "END_PRINT\n", + "default_filament_profile": [ + "Generic PLA @Sovol Zero" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.4 Hardened Steel nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.4 Hardened Steel nozzle.json new file mode 100644 index 0000000000..515c4cf696 --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.4 Hardened Steel nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "machine", + "name": "Sovol Zero 0.4 Hardened Steel nozzle", + "inherits": "Sovol Zero 0.4 nozzle", + "from": "system", + "setting_id": "RqwHKS8MYRdoeJPi", + "instantiation": "true", + "printer_model": "Sovol Zero", + "printer_variant": "0.4HS", + "nozzle_diameter": [ + "0.4" + ], + "default_filament_profile": [ + "Generic PLA @Sovol Zero Hardened Steel nozzle" + ], + "nozzle_type": [ + "hardened_steel" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.4 nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.4 nozzle.json index a5699a9eed..932c5b9121 100644 --- a/resources/profiles/Sovol/machine/Sovol Zero 0.4 nozzle.json +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.4 nozzle.json @@ -1,18 +1,24 @@ { "type": "machine", - "name": "Sovol Zero 0.4 nozzle", - "inherits": "fdm_machine_common", - "from": "system", "setting_id": "QclEa2nmpBiii6Y0", + "name": "Sovol Zero 0.4 nozzle", + "from": "system", "instantiation": "true", + "inherits": "fdm_machine_common", "printer_model": "Sovol Zero", "default_print_profile": "0.20mm Standard @Sovol Zero 0.4 nozzle", "printer_variant": "0.4", "nozzle_diameter": [ "0.4" ], + "min_layer_height": [ + "0.08" + ], + "max_layer_height": [ + "0.32" + ], "retract_before_wipe": [ - "100%" + "0%" ], "printable_area": [ "0x0", @@ -23,7 +29,7 @@ "printable_height": "152.4", "gcode_flavor": "klipper", "retraction_length": [ - "0.8" + "1.8" ], "machine_max_speed_e": [ "50" @@ -71,7 +77,7 @@ "0.5" ], "z_hop": [ - "0.4" + "0.6" ], "retraction_speed": [ "40" @@ -89,7 +95,7 @@ "1" ], "wipe_distance": [ - "2" + "3" ], "z_hop_types": [ "Auto Lift" @@ -104,7 +110,7 @@ "auxiliary_fan": "1", "thumbnails_format": "PNG", "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]\n", - "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", + "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", "machine_end_gcode": "END_PRINT\n", "default_filament_profile": [ "Generic PLA @Sovol Zero" diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.6 Hardened Steel nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.6 Hardened Steel nozzle.json new file mode 100644 index 0000000000..5b53d59ae2 --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.6 Hardened Steel nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "machine", + "name": "Sovol Zero 0.6 Hardened Steel nozzle", + "inherits": "Sovol Zero 0.6 nozzle", + "from": "system", + "setting_id": "s3N3FJkWrzOylFm8", + "instantiation": "true", + "printer_model": "Sovol Zero", + "printer_variant": "0.6HS", + "nozzle_diameter": [ + "0.6" + ], + "default_filament_profile": [ + "Generic PLA @Sovol Zero Hardened Steel nozzle" + ], + "nozzle_type": [ + "hardened_steel" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.6 nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.6 nozzle.json new file mode 100644 index 0000000000..e2cfc7ccc5 --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.6 nozzle.json @@ -0,0 +1,118 @@ +{ + "type": "machine", + "setting_id": "BlngL0WExXTeyrXg", + "name": "Sovol Zero 0.6 nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_machine_common", + "printer_model": "Sovol Zero", + "default_print_profile": "0.30mm Standard @Sovol Zero 0.6 nozzle", + "printer_variant": "0.6", + "nozzle_diameter": [ + "0.6" + ], + "min_layer_height": [ + "0.12" + ], + "max_layer_height": [ + "0.48" + ], + "retract_before_wipe": [ + "0%" + ], + "printable_area": [ + "0x0", + "152.4x0", + "152.4x152.4", + "0x152.4" + ], + "printable_height": "152.4", + "gcode_flavor": "klipper", + "retraction_length": [ + "3.0" + ], + "machine_max_speed_e": [ + "50" + ], + "machine_max_speed_x": [ + "1200" + ], + "machine_max_speed_y": [ + "1200" + ], + "machine_max_speed_z": [ + "30" + ], + "machine_max_acceleration_e": [ + "20000" + ], + "machine_max_acceleration_extruding": [ + "40000" + ], + "machine_max_acceleration_retracting": [ + "20000" + ], + "machine_max_acceleration_travel": [ + "40000" + ], + "machine_max_acceleration_x": [ + "40000" + ], + "machine_max_acceleration_y": [ + "40000" + ], + "machine_max_acceleration_z": [ + "1000" + ], + "machine_max_jerk_e": [ + "2.5" + ], + "machine_max_jerk_x": [ + "5" + ], + "machine_max_jerk_y": [ + "5" + ], + "machine_max_jerk_z": [ + "0.5" + ], + "z_hop": [ + "0.6" + ], + "retraction_speed": [ + "40" + ], + "deretraction_speed": [ + "40" + ], + "retraction_minimum_travel": [ + "0" + ], + "retract_length_toolchange": [ + "2" + ], + "wipe": [ + "1" + ], + "wipe_distance": [ + "3" + ], + "z_hop_types": [ + "Auto Lift" + ], + "thumbnails": [ + "300x300", + "32x32" + ], + "retract_lift_below": [ + "150" + ], + "auxiliary_fan": "1", + "thumbnails_format": "PNG", + "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]\n", + "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", + "machine_end_gcode": "END_PRINT\n", + "default_filament_profile": [ + "Generic PLA @Sovol Zero" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.8 Hardened Steel nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.8 Hardened Steel nozzle.json new file mode 100644 index 0000000000..db6bd740fb --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.8 Hardened Steel nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "machine", + "name": "Sovol Zero 0.8 Hardened Steel nozzle", + "inherits": "Sovol Zero 0.8 nozzle", + "from": "system", + "setting_id": "houacf8sQ3bLozqD", + "instantiation": "true", + "printer_model": "Sovol Zero", + "printer_variant": "0.8HS", + "nozzle_diameter": [ + "0.8" + ], + "default_filament_profile": [ + "Generic PLA @Sovol Zero Hardened Steel nozzle" + ], + "nozzle_type": [ + "hardened_steel" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 0.8 nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 0.8 nozzle.json new file mode 100644 index 0000000000..bc67a64ce5 --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 0.8 nozzle.json @@ -0,0 +1,118 @@ +{ + "type": "machine", + "setting_id": "DDpJMY1A2r4k1Cho", + "name": "Sovol Zero 0.8 nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_machine_common", + "printer_model": "Sovol Zero", + "default_print_profile": "0.40mm Standard @Sovol Zero 0.8 nozzle", + "printer_variant": "0.8", + "nozzle_diameter": [ + "0.8" + ], + "min_layer_height": [ + "0.08" + ], + "max_layer_height": [ + "0.64" + ], + "retract_before_wipe": [ + "0%" + ], + "printable_area": [ + "0x0", + "152.4x0", + "152.4x152.4", + "0x152.4" + ], + "printable_height": "152.4", + "gcode_flavor": "klipper", + "retraction_length": [ + "3.0" + ], + "machine_max_speed_e": [ + "50" + ], + "machine_max_speed_x": [ + "1200" + ], + "machine_max_speed_y": [ + "1200" + ], + "machine_max_speed_z": [ + "30" + ], + "machine_max_acceleration_e": [ + "20000" + ], + "machine_max_acceleration_extruding": [ + "40000" + ], + "machine_max_acceleration_retracting": [ + "20000" + ], + "machine_max_acceleration_travel": [ + "40000" + ], + "machine_max_acceleration_x": [ + "40000" + ], + "machine_max_acceleration_y": [ + "40000" + ], + "machine_max_acceleration_z": [ + "1000" + ], + "machine_max_jerk_e": [ + "2.5" + ], + "machine_max_jerk_x": [ + "5" + ], + "machine_max_jerk_y": [ + "5" + ], + "machine_max_jerk_z": [ + "0.5" + ], + "z_hop": [ + "0.6" + ], + "retraction_speed": [ + "40" + ], + "deretraction_speed": [ + "40" + ], + "retraction_minimum_travel": [ + "0" + ], + "retract_length_toolchange": [ + "2" + ], + "wipe": [ + "1" + ], + "wipe_distance": [ + "3" + ], + "z_hop_types": [ + "Auto Lift" + ], + "thumbnails": [ + "300x300", + "32x32" + ], + "retract_lift_below": [ + "150" + ], + "auxiliary_fan": "1", + "thumbnails_format": "PNG", + "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]\n", + "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", + "machine_end_gcode": "END_PRINT\n", + "default_filament_profile": [ + "Generic PLA @Sovol Zero" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 1.0 Hardened Steel nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 1.0 Hardened Steel nozzle.json new file mode 100644 index 0000000000..73b99e55ef --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 1.0 Hardened Steel nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "machine", + "name": "Sovol Zero 1.0 Hardened Steel nozzle", + "inherits": "Sovol Zero 1.0 nozzle", + "from": "system", + "setting_id": "sqlEiL0in8LSjmmn", + "instantiation": "true", + "printer_model": "Sovol Zero", + "printer_variant": "1.0HS", + "nozzle_diameter": [ + "1.0" + ], + "default_filament_profile": [ + "Generic PLA @Sovol Zero Hardened Steel nozzle" + ], + "nozzle_type": [ + "hardened_steel" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero 1.0 nozzle.json b/resources/profiles/Sovol/machine/Sovol Zero 1.0 nozzle.json new file mode 100644 index 0000000000..beb6db80bd --- /dev/null +++ b/resources/profiles/Sovol/machine/Sovol Zero 1.0 nozzle.json @@ -0,0 +1,118 @@ +{ + "type": "machine", + "setting_id": "CGunT3KHnCqEAlrN", + "name": "Sovol Zero 1.0 nozzle", + "from": "system", + "instantiation": "true", + "inherits": "fdm_machine_common", + "printer_model": "Sovol Zero", + "default_print_profile": "0.50mm Standard @Sovol Zero 1.0 nozzle", + "printer_variant": "1.0", + "nozzle_diameter": [ + "1.0" + ], + "min_layer_height": [ + "0.16" + ], + "max_layer_height": [ + "0.8" + ], + "retract_before_wipe": [ + "0%" + ], + "printable_area": [ + "0x0", + "152.4x0", + "152.4x152.4", + "0x152.4" + ], + "printable_height": "152.4", + "gcode_flavor": "klipper", + "retraction_length": [ + "3.0" + ], + "machine_max_speed_e": [ + "50" + ], + "machine_max_speed_x": [ + "1200" + ], + "machine_max_speed_y": [ + "1200" + ], + "machine_max_speed_z": [ + "30" + ], + "machine_max_acceleration_e": [ + "20000" + ], + "machine_max_acceleration_extruding": [ + "40000" + ], + "machine_max_acceleration_retracting": [ + "20000" + ], + "machine_max_acceleration_travel": [ + "40000" + ], + "machine_max_acceleration_x": [ + "40000" + ], + "machine_max_acceleration_y": [ + "40000" + ], + "machine_max_acceleration_z": [ + "1000" + ], + "machine_max_jerk_e": [ + "2.5" + ], + "machine_max_jerk_x": [ + "5" + ], + "machine_max_jerk_y": [ + "5" + ], + "machine_max_jerk_z": [ + "0.5" + ], + "z_hop": [ + "0.6" + ], + "retraction_speed": [ + "40" + ], + "deretraction_speed": [ + "40" + ], + "retraction_minimum_travel": [ + "0" + ], + "retract_length_toolchange": [ + "2" + ], + "wipe": [ + "1" + ], + "wipe_distance": [ + "3" + ], + "z_hop_types": [ + "Auto Lift" + ], + "thumbnails": [ + "300x300", + "32x32" + ], + "retract_lift_below": [ + "150" + ], + "auxiliary_fan": "1", + "thumbnails_format": "PNG", + "before_layer_change_gcode": "TIMELAPSE_TAKE_FRAME\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]\n", + "machine_start_gcode": "M140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\nG28\nSTART_PRINT\nG28\nG90\nG1 X0 Y0 F12000\nG1 Z0.300 F600\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nM109 S[nozzle_temperature_initial_layer];wait for extruder temp\n{if first_layer_print_min[1] - 6 > print_bed_min[1]}\nG90\nM83\nG1 E-0.5 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 5} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z1 F600\nG1 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4} Y{first_layer_print_min[1] - 4} F12000\nG0 Z0.3 F600 ;Move to start position\nG1 E0.200 F600\n{if first_layer_print_max[0] - first_layer_print_min[0] > 50}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*1} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*4} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*5} E{5 * 0.2}F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*8} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*9} E{5 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 4 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n{else}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0]) / 2} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG0 X{first_layer_print_min[0] + (first_layer_print_max[0] - first_layer_print_min[0])} E{(first_layer_print_max[0] - first_layer_print_min[0]) / 2 * 0.2}F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\n{endif}\nG1 E-0.300 F600\nG0 Z5 F600\nM400\n{else}\nG90\nM83\nG1 E-0.300 Z3 F600\nG1 X{print_bed_max[1] / 3} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 Z0.3 F600\nG1 E0.300 F600\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3} Y1 F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*1} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*2} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*3} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*4} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*5} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*6} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG1 X{print_bed_max[1] / 3 + 5*7} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20) * 60}\nG1 X{print_bed_max[1] / 3 + 5*8} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 X{print_bed_max[1] / 3 + 5*9} E{5 * 0.2} F{outer_wall_volumetric_speed/(24/20)* 60}\nG1 X{print_bed_max[1] / 3 + 5*10} E{5 * 0.2} F{outer_wall_volumetric_speed/(0.3*0.5)/4* 60}\nG1 E-0.300 Z3 F600\nM400\n{endif}\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\n\n", + "machine_end_gcode": "END_PRINT\n", + "default_filament_profile": [ + "Generic PLA @Sovol Zero" + ] +} diff --git a/resources/profiles/Sovol/machine/Sovol Zero.json b/resources/profiles/Sovol/machine/Sovol Zero.json index 6f99e8f8d0..1c67135cf9 100644 --- a/resources/profiles/Sovol/machine/Sovol Zero.json +++ b/resources/profiles/Sovol/machine/Sovol Zero.json @@ -2,11 +2,11 @@ "type": "machine_model", "name": "Sovol Zero", "model_id": "Sovol-Zero", - "nozzle_diameter": "0.4", + "nozzle_diameter": "0.2;0.4;0.6;0.8;1.0;0.2HS;0.4HS;0.6HS;0.8HS;1.0HS", "machine_tech": "FFF", "family": "Sovol", "bed_model": "sovol_zero_buildplate_model.stl", "bed_texture": "sovol_zero_buildplate_texture.svg", "hotend_model": "", - "default_materials": "Generic PLA @Sovol Zero;Sovol Zero PLA Basic HS Nozzle;Generic PLA Silk @Sovol Zero;Sovol Zero PLA Silk HS Nozzle;Generic ABS @Sovol Zero;Generic PETG @Sovol Zero;Sovol Zero PETG HS Nozzle;Generic TPU @Sovol Zero;Generic PC @Sovol Zero" + "default_materials": "Generic PLA @Sovol Zero;Generic PLA SPEEDBENCHY @Sovol Zero;Generic PLA @Sovol Zero Hardened Steel nozzle;Generic PLA Silk @Sovol Zero;Generic PLA Silk @Sovol Zero Hardened Steel nozzle;Generic ABS @Sovol Zero;Generic PETG @Sovol Zero;Generic PETG @Sovol Zero Hardened Steel nozzle;Generic TPU @Sovol Zero;Generic PC @Sovol Zero" } diff --git a/resources/profiles/Sovol/process/0.06mm Quality @Sovol Zero 0.2 nozzle.json b/resources/profiles/Sovol/process/0.06mm Quality @Sovol Zero 0.2 nozzle.json new file mode 100644 index 0000000000..908bfd9813 --- /dev/null +++ b/resources/profiles/Sovol/process/0.06mm Quality @Sovol Zero 0.2 nozzle.json @@ -0,0 +1,36 @@ +{ + "type": "process", + "name": "0.06mm Quality @Sovol Zero 0.2 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "fWP7jaL7sJmmZ6QN", + "instantiation": "true", + "layer_height": "0.06", + "bottom_shell_layers": "8", + "bottom_shell_thickness": "0.8", + "bridge_speed": "30", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.21", + "line_width": "0.21", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.06", + "initial_layer_line_width": "0.3", + "infill_wall_overlap": "18", + "inner_wall_line_width": "0.22", + "wall_loops": "3", + "internal_solid_infill_line_width": "0.21", + "sparse_infill_line_width": "0.21", + "support_top_z_distance": "0.10", + "support_line_width": "0.21", + "tree_support_tip_diameter": "0.21", + "support_speed": "100", + "top_surface_line_width": "0.21", + "top_shell_layers": "8", + "top_shell_thickness": "1", + "compatible_printers": [ + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.10mm Standard @Sovol Zero 0.2 nozzle.json b/resources/profiles/Sovol/process/0.10mm Standard @Sovol Zero 0.2 nozzle.json new file mode 100644 index 0000000000..15540bb172 --- /dev/null +++ b/resources/profiles/Sovol/process/0.10mm Standard @Sovol Zero 0.2 nozzle.json @@ -0,0 +1,36 @@ +{ + "type": "process", + "name": "0.10mm Standard @Sovol Zero 0.2 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "Gql3487jsaTXyuYZ", + "instantiation": "true", + "layer_height": "0.10", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "50", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.22", + "line_width": "0.22", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.12", + "initial_layer_line_width": "0.3", + "infill_wall_overlap": "20", + "inner_wall_line_width": "0.22", + "wall_loops": "2", + "internal_solid_infill_line_width": "0.22", + "sparse_infill_line_width": "0.22", + "support_top_z_distance": "0.20", + "support_line_width": "0.22", + "tree_support_tip_diameter": "0.22", + "support_speed": "100", + "top_surface_line_width": "0.22", + "top_shell_layers": "4", + "top_shell_thickness": "1", + "compatible_printers": [ + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.12mm Quality @Sovol Zero 0.4 nozzle.json b/resources/profiles/Sovol/process/0.12mm Quality @Sovol Zero 0.4 nozzle.json new file mode 100644 index 0000000000..c1cc06a737 --- /dev/null +++ b/resources/profiles/Sovol/process/0.12mm Quality @Sovol Zero 0.4 nozzle.json @@ -0,0 +1,35 @@ +{ + "type": "process", + "setting_id": "CaEopiv2Wg6pQJjH", + "name": "0.12mm Quality @Sovol Zero 0.4 nozzle", + "from": "system", + "inherits": "fdm_process_zero", + "instantiation": "true", + "layer_height": "0.12", + "bottom_shell_layers": "8", + "bottom_shell_thickness": "0.8", + "bridge_speed": "30", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.42", + "line_width": "0.42", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.12", + "initial_layer_line_width": "0.6", + "sparse_infill_line_width": "0.42", + "infill_wall_overlap": "18", + "inner_wall_line_width": "0.44", + "wall_loops": "3", + "support_top_z_distance": "0.10", + "support_line_width": "0.42", + "tree_support_tip_diameter": "0.42", + "support_speed": "100", + "top_surface_line_width": "0.42", + "internal_solid_infill_line_width": "0.42", + "top_shell_layers": "8", + "compatible_printers": [ + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.14mm Fast @Sovol Zero 0.2 nozzle.json b/resources/profiles/Sovol/process/0.14mm Fast @Sovol Zero 0.2 nozzle.json new file mode 100644 index 0000000000..79fe17eb39 --- /dev/null +++ b/resources/profiles/Sovol/process/0.14mm Fast @Sovol Zero 0.2 nozzle.json @@ -0,0 +1,36 @@ +{ + "type": "process", + "name": "0.14mm Fast @Sovol Zero 0.2 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "I9yoyCcGGTRrDoKu", + "instantiation": "true", + "layer_height": "0.14", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "bridge_speed": "60", + "outer_wall_acceleration": "22000", + "top_surface_acceleration": "22000", + "outer_wall_line_width": "0.24", + "line_width": "0.24", + "sparse_infill_density": "10%", + "inner_wall_acceleration": "28000", + "initial_layer_print_height": "0.14", + "initial_layer_line_width": "0.3", + "infill_wall_overlap": "20", + "inner_wall_line_width": "0.24", + "wall_loops": "2", + "internal_solid_infill_line_width": "0.24", + "sparse_infill_line_width": "0.24", + "support_top_z_distance": "0.30", + "support_line_width": "0.24", + "tree_support_tip_diameter": "0.24", + "support_speed": "120", + "top_surface_line_width": "0.24", + "top_shell_layers": "4", + "top_shell_thickness": "1", + "compatible_printers": [ + "Sovol Zero 0.2 nozzle", + "Sovol Zero 0.2 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.15mm Quality @Sovol Zero 0.6 nozzle.json b/resources/profiles/Sovol/process/0.15mm Quality @Sovol Zero 0.6 nozzle.json new file mode 100644 index 0000000000..f532985258 --- /dev/null +++ b/resources/profiles/Sovol/process/0.15mm Quality @Sovol Zero 0.6 nozzle.json @@ -0,0 +1,34 @@ +{ + "type": "process", + "setting_id": "IfDpa3vM99D4ytny", + "name": "0.15mm Quality @Sovol Zero 0.6 nozzle", + "from": "system", + "inherits": "fdm_process_zero", + "instantiation": "true", + "layer_height": "0.15", + "bottom_shell_layers": "5", + "bottom_shell_thickness": "0.8", + "bridge_speed": "30", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.63", + "line_width": "0.63", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_line_width": "0.9", + "sparse_infill_line_width": "0.63", + "infill_wall_overlap": "18", + "inner_wall_line_width": "0.66", + "wall_loops": "3", + "support_top_z_distance": "0.15", + "support_line_width": "0.63", + "tree_support_tip_diameter": "0.63", + "support_speed": "100", + "top_surface_line_width": "0.63", + "top_shell_layers": "5", + "internal_solid_infill_line_width": "0.63", + "compatible_printers": [ + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.20mm Quality @Sovol Zero 0.8 nozzle.json b/resources/profiles/Sovol/process/0.20mm Quality @Sovol Zero 0.8 nozzle.json new file mode 100644 index 0000000000..c9774c6d65 --- /dev/null +++ b/resources/profiles/Sovol/process/0.20mm Quality @Sovol Zero 0.8 nozzle.json @@ -0,0 +1,42 @@ +{ + "type": "process", + "name": "0.20mm Quality @Sovol Zero 0.8 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "MSxikpQZNYdoBynZ", + "instantiation": "true", + "layer_height": "0.20", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "30", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.84", + "line_width": "0.84", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.36", + "initial_layer_line_width": "1.2", + "sparse_infill_line_width": "0.84", + "infill_wall_overlap": "18", + "inner_wall_line_width": "0.88", + "wall_loops": "3", + "support_top_z_distance": "0.20", + "support_line_width": "0.84", + "tree_support_tip_diameter": "0.84", + "support_speed": "100", + "top_surface_line_width": "0.84", + "top_shell_layers": "4", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "50%", + "internal_solid_infill_speed": "200", + "internal_solid_infill_line_width": "0.84", + "top_surface_speed": "200", + "gap_infill_speed": "200", + "sparse_infill_speed": "500", + "compatible_printers": [ + "Sovol Zero 0.8 nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.20mm Standard @Sovol Zero 0.4 nozzle.json b/resources/profiles/Sovol/process/0.20mm Standard @Sovol Zero 0.4 nozzle.json index 323553beaa..d8820163d6 100644 --- a/resources/profiles/Sovol/process/0.20mm Standard @Sovol Zero 0.4 nozzle.json +++ b/resources/profiles/Sovol/process/0.20mm Standard @Sovol Zero 0.4 nozzle.json @@ -1,141 +1,36 @@ { "type": "process", - "name": "0.20mm Standard @Sovol Zero 0.4 nozzle", - "inherits": "fdm_process_common", - "from": "system", "setting_id": "ShJTVnJ492No1j2j", + "name": "0.20mm Standard @Sovol Zero 0.4 nozzle", + "from": "system", + "inherits": "fdm_process_zero", "instantiation": "true", - "reduce_crossing_wall": "1", - "max_travel_detour_distance": "100%", "layer_height": "0.20", - "bottom_surface_pattern": "monotonic", - "bottom_shell_layers": "3", - "bottom_shell_thickness": "0", - "bridge_flow": "1.2", - "internal_bridge_flow": "1.2", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", "bridge_speed": "50", - "internal_bridge_speed": "200", - "brim_type": "auto_brim", - "brim_width": "5", - "brim_object_gap": "0", - "compatible_printers_condition": "", - "print_sequence": "by layer", - "default_acceleration": "40000", "outer_wall_acceleration": "10000", "top_surface_acceleration": "5000", - "bridge_no_support": "0", - "draft_shield": "disabled", - "elefant_foot_compensation": "0.1", - "enable_arc_fitting": "0", - "exclude_object": "1", - "outer_wall_line_width": "0.4", - "wall_infill_order": "inner wall/outer wall/infill", - "line_width": "0.4", - "infill_direction": "45", - "sparse_infill_density": "10%", - "sparse_infill_pattern": "grid", - "internal_solid_infill_acceleration": "50%", - "initial_layer_acceleration": "1000", - "initial_solid_infill_acceleration": "3000", - "travel_acceleration": "40000", + "outer_wall_line_width": "0.44", + "line_width": "0.44", + "sparse_infill_density": "15%", "inner_wall_acceleration": "12000", - "outer_wall_jerk": "5", - "inner_wall_jerk": "5", - "infill_jerk": "5", - "top_surface_jerk": "5", - "initial_layer_jerk": "5", - "travel_jerk": "5", - "initial_layer_line_width": "0.42", - "initial_layer_print_height": "0.25", - "infill_combination": "0", - "sparse_infill_line_width": "0.45", - "infill_wall_overlap": "15%", - "interface_shells": "0", - "ironing_flow": "15%", - "ironing_spacing": "0.25", - "ironing_speed": "15", - "ironing_type": "no ironing", - "reduce_infill_retraction": "1", - "filename_format": "{printer_model}_{input_filename_base}_{filament_type[0]}_{layer_height}_{print_time}.gcode", - "detect_overhang_wall": "1", - "overhang_1_4_speed": "0", - "overhang_2_4_speed": "50", - "overhang_3_4_speed": "30", - "overhang_4_4_speed": "20", - "inner_wall_line_width": "0.4", + "initial_layer_print_height": "0.24", + "initial_layer_line_width": "0.6", + "sparse_infill_line_width": "0.44", + "infill_wall_overlap": "20", + "ironing_speed": "100", + "inner_wall_line_width": "0.44", "wall_loops": "2", - "print_settings_id": "", - "raft_layers": "0", - "seam_position": "aligned", - "skirt_distance": "0.8", - "skirt_height": "1", - "skirt_loops": "1", - "minimum_sparse_infill_area": "15", - "internal_solid_infill_line_width": "0.45", - "spiral_mode": "0", - "standby_temperature_delta": "-5", - "enable_support": "0", - "resolution": "0.012", - "support_type": "tree(auto)", - "support_style": "default", - "support_on_build_plate_only": "0", - "support_top_z_distance": "0.235", - "support_bottom_z_distance": "0.235", - "support_filament": "0", - "support_line_width": "0.45", - "support_interface_loop_pattern": "0", - "support_interface_filament": "0", - "support_interface_top_layers": "5", - "support_interface_bottom_layers": "-1", - "support_interface_spacing": "0.2", - "support_bottom_interface_spacing": "0.2", - "support_interface_speed": "100%", - "support_interface_pattern": "grid", - "support_base_pattern": "rectilinear", - "support_base_pattern_spacing": "3.5", - "support_speed": "100", - "support_threshold_angle": "20", - "support_object_xy_distance": "0.35", - "tree_support_branch_angle": "40", - "tree_support_wall_count": "0", - "detect_thin_wall": "1", - "top_surface_pattern": "monotonic", - "top_surface_line_width": "0.38", + "support_top_z_distance": "0.20", + "support_line_width": "0.44", + "tree_support_tip_diameter": "0.44", + "support_speed": "60", + "top_surface_line_width": "0.44", "top_shell_layers": "4", - "top_shell_thickness": "1", - "initial_layer_speed": "55", - "initial_layer_infill_speed": "105", - "initial_layer_travel_speed": "60%", - "outer_wall_speed": "350", - "inner_wall_speed": "400", - "small_perimeter_speed": "50%", - "internal_solid_infill_speed": "200", - "top_surface_speed": "200", - "gap_infill_speed": "200", - "sparse_infill_speed": "500", - "accel_to_decel_enable": "1", - "accel_to_decel_factor": "25%", - "travel_speed": "1000", - "enable_prime_tower": "1", - "wipe_tower_no_sparse_layers": "0", - "prime_tower_width": "60", - "xy_hole_compensation": "0", - "xy_contour_compensation": "0", - "bridge_acceleration": "50%", - "seam_gap": "10%", - "precise_outer_wall": "1", - "wall_generator": "classic", - "gcode_label_objects": "1", - "slow_down_layers": "3", - "top_solid_infill_flow_ratio": "0.9", - "only_one_wall_top": "1", - "wall_loop_direction": "clockwise", - "top_bottom_infill_wall_overlap": "25%", - "filter_out_gap_fill": "0", - "detect_narrow_internal_solid_infill": "1", - "thick_bridges": "1", - "bridge_angle": "0", + "internal_solid_infill_line_width": "0.44", "compatible_printers": [ - "Sovol Zero 0.4 nozzle" + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle" ] } diff --git a/resources/profiles/Sovol/process/0.25mm Quality @Sovol Zero 1.0 nozzle.json b/resources/profiles/Sovol/process/0.25mm Quality @Sovol Zero 1.0 nozzle.json new file mode 100644 index 0000000000..60e8db168f --- /dev/null +++ b/resources/profiles/Sovol/process/0.25mm Quality @Sovol Zero 1.0 nozzle.json @@ -0,0 +1,79 @@ +{ + "type": "process", + "name": "0.25mm Quality @Sovol Zero 1.0 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "JUmnFOoEMJrbWCN9", + "instantiation": "true", + "layer_height": "0.25", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "30", + "internal_bridge_speed": "200", + "default_acceleration": "40000", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "1.05", + "line_width": "1.05", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.45", + "initial_layer_line_width": "1.5", + "infill_combination": "0", + "sparse_infill_line_width": "1.05", + "infill_wall_overlap": "18", + "interface_shells": "0", + "ironing_flow": "15%", + "ironing_spacing": "0.25", + "ironing_speed": "15", + "ironing_type": "no ironing", + "filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode", + "detect_overhang_wall": "1", + "overhang_1_4_speed": "0", + "overhang_2_4_speed": "50", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "20", + "inner_wall_line_width": "1.1", + "wall_loops": "3", + "print_settings_id": "", + "raft_layers": "0", + "seam_position": "aligned", + "skirt_distance": "0.8", + "skirt_height": "1", + "skirt_loops": "1", + "minimum_sparse_infill_area": "15", + "internal_solid_infill_line_width": "1.05", + "spiral_mode": "0", + "standby_temperature_delta": "-5", + "enable_support": "0", + "resolution": "0.012", + "support_type": "tree(auto)", + "support_style": "snug", + "support_on_build_plate_only": "0", + "support_top_z_distance": "0.25", + "support_bottom_z_distance": "0.235", + "support_filament": "0", + "support_line_width": "1.05", + "tree_support_tip_diameter": "1.05", + "support_interface_loop_pattern": "0", + "support_interface_filament": "0", + "support_interface_top_layers": "5", + "support_interface_bottom_layers": "-1", + "support_interface_spacing": "0.2", + "support_bottom_interface_spacing": "0.2", + "support_interface_speed": "100%", + "support_interface_pattern": "grid", + "support_base_pattern": "rectilinear", + "support_base_pattern_spacing": "3.5", + "support_speed": "100", + "support_threshold_angle": "50", + "support_object_xy_distance": "0.35", + "tree_support_branch_angle": "40", + "top_surface_line_width": "1.05", + "top_shell_layers": "4", + "top_shell_thickness": "1", + "compatible_printers": [ + "Sovol Zero 1.0 nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json b/resources/profiles/Sovol/process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json new file mode 100644 index 0000000000..89e248b223 --- /dev/null +++ b/resources/profiles/Sovol/process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json @@ -0,0 +1,85 @@ +{ + "type": "process", + "setting_id": "oFrWcSxmad1b6sD4", + "name": "0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle", + "from": "system", + "inherits": "fdm_process_zero", + "instantiation": "true", + "layer_height": "0.25", + "initial_layer_print_height": "0.25", + "line_width": "0.5", + "initial_layer_line_width": "0.5", + "outer_wall_line_width": "0.5", + "inner_wall_line_width": "0.5", + "top_surface_line_width": "0.55", + "internal_solid_infill_line_width": "0.55", + "sparse_infill_line_width": "0.55", + "support_line_width": "0.5", + "tree_support_tip_diameter": "0.5", + "wall_loops": "2", + "top_shell_layers": "3", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "sparse_infill_density": "10%", + "sparse_infill_pattern": "grid", + "bottom_solid_infill_flow_ratio": "1.2", + "top_solid_infill_flow_ratio": "1.4", + "bridge_flow": "1", + "internal_bridge_flow": "1", + "bridge_speed": "250", + "internal_bridge_speed": "250", + "bridge_acceleration": "100%", + "thick_bridges": "0", + "thick_internal_bridges": "0", + "brim_type": "outer_only", + "brim_width": "1", + "brim_object_gap": "0", + "filter_out_gap_fill": "13", + "gap_fill_target": "nowhere", + "min_width_top_surface": "200%", + "minimum_sparse_infill_area": "0", + "infill_direction": "0", + "solid_infill_direction": "0", + "infill_wall_overlap": "15%", + "reduce_crossing_wall": "0", + "skirt_loops": "0", + "only_one_wall_top": "1", + "slow_down_layers": "1", + "wall_direction": "cw", + "initial_layer_speed": "300", + "initial_layer_infill_speed": "300", + "initial_layer_travel_speed": "100%", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "100%", + "internal_solid_infill_speed": "400", + "top_surface_speed": "300", + "gap_infill_speed": "350", + "sparse_infill_speed": "500", + "support_speed": "100", + "travel_speed": "1200", + "default_acceleration": "40000", + "initial_layer_acceleration": "20000", + "outer_wall_acceleration": "40000", + "inner_wall_acceleration": "40000", + "top_surface_acceleration": "20000", + "internal_solid_infill_acceleration": "100%", + "travel_acceleration": "40000", + "accel_to_decel_factor": "50%", + "outer_wall_jerk": "20", + "inner_wall_jerk": "20", + "infill_jerk": "20", + "top_surface_jerk": "20", + "initial_layer_jerk": "20", + "travel_jerk": "20", + "overhang_1_4_speed": "160", + "overhang_2_4_speed": "100", + "overhang_3_4_speed": "60", + "overhang_4_4_speed": "40", + "support_top_z_distance": "0.235", + "support_bottom_z_distance": "0.235", + "compatible_printers": [ + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.28mm Fast @Sovol Zero 0.4 nozzle.json b/resources/profiles/Sovol/process/0.28mm Fast @Sovol Zero 0.4 nozzle.json new file mode 100644 index 0000000000..1ad361e3e2 --- /dev/null +++ b/resources/profiles/Sovol/process/0.28mm Fast @Sovol Zero 0.4 nozzle.json @@ -0,0 +1,39 @@ +{ + "type": "process", + "name": "0.28mm Fast @Sovol Zero 0.4 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "1VoML2LGDk4TJgLI", + "instantiation": "true", + "layer_height": "0.28", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "bridge_speed": "60", + "outer_wall_acceleration": "22000", + "top_surface_acceleration": "22000", + "outer_wall_line_width": "0.48", + "line_width": "0.48", + "sparse_infill_density": "10%", + "inner_wall_acceleration": "28000", + "initial_layer_print_height": "0.28", + "initial_layer_line_width": "0.6", + "sparse_infill_line_width": "0.48", + "inner_wall_line_width": "0.48", + "internal_solid_infill_line_width": "0.48", + "support_top_z_distance": "0.30", + "support_line_width": "0.48", + "tree_support_tip_diameter": "0.48", + "support_speed": "120", + "top_surface_line_width": "0.48", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "50%", + "internal_solid_infill_speed": "200", + "top_surface_speed": "200", + "gap_infill_speed": "200", + "sparse_infill_speed": "500", + "compatible_printers": [ + "Sovol Zero 0.4 nozzle", + "Sovol Zero 0.4 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.30mm Standard @Sovol Zero 0.6 nozzle.json b/resources/profiles/Sovol/process/0.30mm Standard @Sovol Zero 0.6 nozzle.json new file mode 100644 index 0000000000..4f1f487bdf --- /dev/null +++ b/resources/profiles/Sovol/process/0.30mm Standard @Sovol Zero 0.6 nozzle.json @@ -0,0 +1,35 @@ +{ + "type": "process", + "setting_id": "lTAs2USEP8D749K7", + "name": "0.30mm Standard @Sovol Zero 0.6 nozzle", + "from": "system", + "inherits": "fdm_process_zero", + "instantiation": "true", + "layer_height": "0.30", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "50", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.66", + "line_width": "0.66", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.36", + "initial_layer_line_width": "0.9", + "sparse_infill_line_width": "0.66", + "infill_wall_overlap": "20", + "inner_wall_line_width": "0.66", + "wall_loops": "2", + "support_top_z_distance": "0.30", + "support_line_width": "0.66", + "tree_support_tip_diameter": "0.66", + "support_speed": "100", + "top_surface_line_width": "0.66", + "top_shell_layers": "4", + "internal_solid_infill_line_width": "0.66", + "compatible_printers": [ + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.40mm Standard @Sovol Zero 0.8 nozzle.json b/resources/profiles/Sovol/process/0.40mm Standard @Sovol Zero 0.8 nozzle.json new file mode 100644 index 0000000000..7eeecf4ece --- /dev/null +++ b/resources/profiles/Sovol/process/0.40mm Standard @Sovol Zero 0.8 nozzle.json @@ -0,0 +1,42 @@ +{ + "type": "process", + "name": "0.40mm Standard @Sovol Zero 0.8 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "8x4CsuqroC9HOdAN", + "instantiation": "true", + "layer_height": "0.40", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "50", + "outer_wall_acceleration": "10000", + "top_surface_acceleration": "5000", + "outer_wall_line_width": "0.88", + "line_width": "0.88", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "12000", + "initial_layer_print_height": "0.48", + "initial_layer_line_width": "1.2", + "sparse_infill_line_width": "0.88", + "infill_wall_overlap": "20", + "inner_wall_line_width": "0.88", + "wall_loops": "2", + "support_top_z_distance": "0.40", + "support_line_width": "0.88", + "tree_support_tip_diameter": "0.88", + "support_speed": "100", + "top_surface_line_width": "0.88", + "top_shell_layers": "4", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "50%", + "internal_solid_infill_speed": "200", + "top_surface_speed": "200", + "gap_infill_speed": "200", + "sparse_infill_speed": "500", + "internal_solid_infill_line_width": "0.88", + "compatible_printers": [ + "Sovol Zero 0.8 nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.42mm Fast @Sovol Zero 0.6 nozzle.json b/resources/profiles/Sovol/process/0.42mm Fast @Sovol Zero 0.6 nozzle.json new file mode 100644 index 0000000000..75a9522c62 --- /dev/null +++ b/resources/profiles/Sovol/process/0.42mm Fast @Sovol Zero 0.6 nozzle.json @@ -0,0 +1,39 @@ +{ + "type": "process", + "name": "0.42mm Fast @Sovol Zero 0.6 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "illqJAnGiA2pY0hw", + "instantiation": "true", + "layer_height": "0.42", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "bridge_speed": "60", + "outer_wall_acceleration": "22000", + "top_surface_acceleration": "22000", + "outer_wall_line_width": "0.72", + "line_width": "0.72", + "sparse_infill_density": "10%", + "inner_wall_acceleration": "28000", + "initial_layer_print_height": "0.42", + "initial_layer_line_width": "0.9", + "sparse_infill_line_width": "0.72", + "inner_wall_line_width": "0.72", + "internal_solid_infill_line_width": "0.72", + "support_top_z_distance": "0.45", + "support_line_width": "0.72", + "tree_support_tip_diameter": "0.72", + "support_speed": "120", + "top_surface_line_width": "0.72", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "50%", + "internal_solid_infill_speed": "200", + "top_surface_speed": "200", + "gap_infill_speed": "200", + "sparse_infill_speed": "500", + "compatible_printers": [ + "Sovol Zero 0.6 nozzle", + "Sovol Zero 0.6 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.50mm Standard @Sovol Zero 1.0 nozzle.json b/resources/profiles/Sovol/process/0.50mm Standard @Sovol Zero 1.0 nozzle.json new file mode 100644 index 0000000000..c1446a6536 --- /dev/null +++ b/resources/profiles/Sovol/process/0.50mm Standard @Sovol Zero 1.0 nozzle.json @@ -0,0 +1,87 @@ +{ + "type": "process", + "name": "0.50mm Standard @Sovol Zero 1.0 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "E5K55O4RkMyYCAlt", + "instantiation": "true", + "layer_height": "0.50", + "bottom_shell_layers": "4", + "bottom_shell_thickness": "0.8", + "bridge_speed": "45", + "internal_bridge_speed": "200", + "default_acceleration": "22000", + "outer_wall_acceleration": "16000", + "top_surface_acceleration": "16000", + "outer_wall_line_width": "1.1", + "line_width": "1.1", + "sparse_infill_density": "15%", + "inner_wall_acceleration": "22000", + "initial_layer_print_height": "0.60", + "initial_layer_line_width": "1.5", + "infill_combination": "0", + "sparse_infill_line_width": "1.1", + "infill_wall_overlap": "20", + "interface_shells": "0", + "ironing_flow": "15%", + "ironing_spacing": "0.25", + "ironing_speed": "15", + "ironing_type": "no ironing", + "filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode", + "detect_overhang_wall": "1", + "overhang_1_4_speed": "0", + "overhang_2_4_speed": "50", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "20", + "inner_wall_line_width": "1.1", + "wall_loops": "2", + "print_settings_id": "", + "raft_layers": "0", + "seam_position": "aligned", + "skirt_distance": "0.8", + "skirt_height": "1", + "skirt_loops": "1", + "minimum_sparse_infill_area": "15", + "internal_solid_infill_line_width": "1.1", + "spiral_mode": "0", + "standby_temperature_delta": "-5", + "enable_support": "0", + "resolution": "0.012", + "support_type": "tree(auto)", + "support_style": "snug", + "support_on_build_plate_only": "0", + "support_top_z_distance": "0.50", + "support_bottom_z_distance": "0.235", + "support_filament": "0", + "support_line_width": "1.1", + "tree_support_tip_diameter": "1.1", + "support_interface_loop_pattern": "0", + "support_interface_filament": "0", + "support_interface_top_layers": "5", + "support_interface_bottom_layers": "-1", + "support_interface_spacing": "0.2", + "support_bottom_interface_spacing": "0.2", + "support_interface_speed": "100%", + "support_interface_pattern": "grid", + "support_base_pattern": "rectilinear", + "support_base_pattern_spacing": "3.5", + "support_speed": "60", + "support_threshold_angle": "50", + "support_object_xy_distance": "0.35", + "tree_support_branch_angle": "40", + "top_surface_line_width": "1.1", + "top_shell_layers": "4", + "top_shell_thickness": "1", + "outer_wall_speed": "30", + "inner_wall_speed": "45", + "small_perimeter_speed": "45", + "internal_solid_infill_speed": "45", + "top_surface_speed": "35", + "gap_infill_speed": "35", + "sparse_infill_speed": "70", + "travel_acceleration": "38000", + "compatible_printers": [ + "Sovol Zero 1.0 nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.56mm Fast @Sovol Zero 0.8 nozzle.json b/resources/profiles/Sovol/process/0.56mm Fast @Sovol Zero 0.8 nozzle.json new file mode 100644 index 0000000000..3bef013a12 --- /dev/null +++ b/resources/profiles/Sovol/process/0.56mm Fast @Sovol Zero 0.8 nozzle.json @@ -0,0 +1,40 @@ +{ + "type": "process", + "name": "0.56mm Fast @Sovol Zero 0.8 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "g9PPRM4FLMwjMUfy", + "instantiation": "true", + "layer_height": "0.56", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "bridge_speed": "60", + "default_acceleration": "28000", + "outer_wall_acceleration": "22000", + "top_surface_acceleration": "22000", + "outer_wall_line_width": "0.96", + "line_width": "0.96", + "sparse_infill_density": "10%", + "inner_wall_acceleration": "28000", + "initial_layer_print_height": "0.56", + "initial_layer_line_width": "1.2", + "sparse_infill_line_width": "0.96", + "inner_wall_line_width": "0.96", + "internal_solid_infill_line_width": "0.96", + "support_top_z_distance": "0.60", + "support_line_width": "0.96", + "tree_support_tip_diameter": "0.96", + "top_surface_line_width": "0.96", + "top_shell_layers": "4", + "outer_wall_speed": "35", + "inner_wall_speed": "55", + "small_perimeter_speed": "60", + "internal_solid_infill_speed": "55", + "top_surface_speed": "40", + "gap_infill_speed": "40", + "sparse_infill_speed": "80", + "compatible_printers": [ + "Sovol Zero 0.8 nozzle", + "Sovol Zero 0.8 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/0.70mm Fast @Sovol Zero 1.0 nozzle.json b/resources/profiles/Sovol/process/0.70mm Fast @Sovol Zero 1.0 nozzle.json new file mode 100644 index 0000000000..39d5309914 --- /dev/null +++ b/resources/profiles/Sovol/process/0.70mm Fast @Sovol Zero 1.0 nozzle.json @@ -0,0 +1,33 @@ +{ + "type": "process", + "name": "0.70mm Fast @Sovol Zero 1.0 nozzle", + "inherits": "fdm_process_zero", + "from": "system", + "setting_id": "fW5KJBVndgQE868q", + "instantiation": "true", + "layer_height": "0.70", + "bottom_shell_layers": "3", + "bottom_shell_thickness": "0", + "bridge_speed": "60", + "outer_wall_acceleration": "22000", + "top_surface_acceleration": "22000", + "outer_wall_line_width": "1.2", + "line_width": "1.2", + "sparse_infill_density": "10%", + "inner_wall_acceleration": "28000", + "initial_layer_print_height": "0.70", + "initial_layer_line_width": "1.5", + "sparse_infill_line_width": "1.2", + "inner_wall_line_width": "1.2", + "internal_solid_infill_line_width": "1.2", + "support_top_z_distance": "0.75", + "support_line_width": "1.2", + "tree_support_tip_diameter": "1.2", + "support_speed": "120", + "top_surface_line_width": "1.2", + "top_shell_layers": "3", + "compatible_printers": [ + "Sovol Zero 1.0 nozzle", + "Sovol Zero 1.0 Hardened Steel nozzle" + ] +} diff --git a/resources/profiles/Sovol/process/fdm_process_zero.json b/resources/profiles/Sovol/process/fdm_process_zero.json new file mode 100644 index 0000000000..da4df2686e --- /dev/null +++ b/resources/profiles/Sovol/process/fdm_process_zero.json @@ -0,0 +1,73 @@ +{ + "type": "process", + "name": "fdm_process_zero", + "inherits": "fdm_process_common", + "from": "system", + "instantiation": "false", + "reduce_crossing_wall": "1", + "max_travel_detour_distance": "10", + "bottom_surface_pattern": "monotonic", + "bridge_flow": "1.2", + "internal_bridge_flow": "1.2", + "brim_type": "auto_brim", + "brim_width": "5", + "brim_object_gap": "0", + "print_sequence": "by layer", + "bridge_no_support": "0", + "draft_shield": "disabled", + "elefant_foot_compensation": "0.1", + "enable_arc_fitting": "0", + "exclude_object": "1", + "wall_infill_order": "inner wall/outer wall/infill", + "infill_direction": "45", + "sparse_infill_pattern": "grid", + "internal_solid_infill_acceleration": "50%", + "initial_layer_acceleration": "1000", + "travel_acceleration": "40000", + "outer_wall_jerk": "5", + "inner_wall_jerk": "5", + "infill_jerk": "5", + "top_surface_jerk": "5", + "initial_layer_jerk": "5", + "travel_jerk": "5", + "tree_support_wall_count": "0", + "reduce_infill_retraction": "1", + "detect_thin_wall": "1", + "top_surface_pattern": "monotonic", + "initial_layer_speed": "55", + "initial_layer_infill_speed": "105", + "initial_layer_travel_speed": "60%", + "outer_wall_speed": "350", + "inner_wall_speed": "400", + "small_perimeter_speed": "50%", + "internal_solid_infill_speed": "200", + "top_surface_speed": "200", + "gap_infill_speed": "200", + "sparse_infill_speed": "500", + "accel_to_decel_enable": "1", + "accel_to_decel_factor": "25%", + "travel_speed": "1000", + "enable_prime_tower": "0", + "wipe_tower_no_sparse_layers": "0", + "prime_tower_width": "60", + "xy_hole_compensation": "0", + "xy_contour_compensation": "0", + "bridge_acceleration": "50%", + "seam_gap": "10%", + "precise_outer_wall": "1", + "wall_generator": "classic", + "gcode_label_objects": "1", + "slow_down_layers": "3", + "top_solid_infill_flow_ratio": "0.9", + "only_one_wall_top": "1", + "top_bottom_infill_wall_overlap": "25%", + "filter_out_gap_fill": "0", + "detect_narrow_internal_solid_infill": "1", + "thick_bridges": "1", + "bridge_angle": "0", + "initial_layer_line_width": "150%", + "default_acceleration": "40000", + "compatible_printers": [], + "internal_bridge_speed": "150", + "filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode" +} From fcd813199877fd1247c46cd6cb353bddc9ac5e6e Mon Sep 17 00:00:00 2001 From: Lam Wei Lun Date: Wed, 23 Sep 2026 20:23:52 +0800 Subject: [PATCH 2/6] WebGuide's Filament Dialog Fix to ensure filaments inheritance chain is checked properly (#15855) * fix: resolve filament vendor/type across split base presets WebGuide's filament list dropped presets whose vendor and type came from different ancestors, and looped forever on inherits cycles. Walk the full inherits chain with a path-scoped guard, fill only missing values, and skip presets that still lack vendor or type. Add tests for split-base resolution and validate the real profile tree. * Merge branch 'main' into feat/filament_dialog_fix * Fixes unit test * Merge branch 'main' into feat/filament_dialog_fix * Merge branch 'main' into feat/filament_dialog_fix * revert tests/fff_print/test_gcodewriter.cpp changes --- scripts/tests/test_filament_id.py | 45 +++++++++++++++++++++ src/slic3r/GUI/WebGuideDialog.cpp | 67 +++++++++++++++++-------------- src/slic3r/GUI/WebGuideDialog.hpp | 4 ++ 3 files changed, 85 insertions(+), 31 deletions(-) diff --git a/scripts/tests/test_filament_id.py b/scripts/tests/test_filament_id.py index 001763fca9..fc62f5abc3 100644 --- a/scripts/tests/test_filament_id.py +++ b/scripts/tests/test_filament_id.py @@ -405,6 +405,20 @@ class TestTripleResolution(unittest.TestCase): self.assertEqual(afi.resolve_triple("MyPLA @P1", fmap, {}), ("MyVendor", "PLA", "MyPLA")) + def test_split_vendor_and_type_bases_resolve(self): + # A partial base is normal, not an error: vendor and type may live on + # different ancestors, with an intermediate supplying neither (the + # Snapmaker shape). The pair is complete at the instantiated preset. + recs = [ + self.rec("APLA @P1", inherits="mid"), + self.rec("mid", inherits="typebase"), + self.rec("typebase", filament_type=["PLA"], inherits="vendorbase"), + self.rec("vendorbase", filament_vendor=["AV"]), + ] + fmap = {r["name"]: r for r in recs} + self.assertEqual(afi.resolve_triple("APLA @P1", fmap, {}), + ("AV", "PLA", "APLA")) + # --------------------------------------------------------------------------- # checks on synthetic trees @@ -417,6 +431,24 @@ class TestChecks(OfCleanTreeCase): self.assertNotIn("[ERROR]", out) self.assertNotIn("[WARNING]", out) + def test_instantiated_preset_over_partial_bases_is_silent(self): + # Vendor and type split across two non-instantiated bases, an + # intermediate base with neither: base profiles are allowed to be + # partial. Only the instantiated preset must resolve both. + self.t.write_preset("VendorA", preset("XPLA vendorbase", instantiation=False, + filament_vendor="XV")) + self.t.write_preset("VendorA", preset("XPLA typebase", instantiation=False, + filament_type="PLA", + inherits="XPLA vendorbase")) + self.t.write_preset("VendorA", preset("XPLA mid", instantiation=False, + inherits="XPLA typebase")) + self.t.write_preset("VendorA", preset( + "XPLA @P1", inherits="XPLA mid", + filament_id=afi.generate_filament_id("XV", "PLA", "XPLA"), + compatible_printers=["P1"])) + errors, out = self.t.check() + self.assertEqual(errors, 0, out) + def test_check1_unknown_non_of_id(self): self.t.write_preset("VendorA", preset("BPLA @base", filament_id="BOGUS_9", instantiation=False, @@ -1523,6 +1555,19 @@ class TestRealTree(unittest.TestCase): self.assertEqual(analysis["missing_effective"], []) self.assertEqual(analysis["read_errors"], []) + def test_every_instantiated_filament_resolves_vendor_and_type(self): + # The property the web guide resolves at load: a partial base is fine as + # long as the instantiated preset ends up with both fields. Guards the + # split-base bundles (Snapmaker, Anker, SeeMeCNC). + analysis = afi.analyze_tree(REAL_PROFILES) + unresolved = [ + (vendor, rec["name"], rec["triple"][0], rec["triple"][1]) + for vendor, filaments in analysis["vendors"].items() + for rec in filaments.values() + if rec["instantiation"] and not (rec["triple"][0] and rec["triple"][1]) + ] + self.assertEqual(unresolved, []) + # --------------------------------------------------------------------------- # review-fix regressions # --------------------------------------------------------------------------- diff --git a/src/slic3r/GUI/WebGuideDialog.cpp b/src/slic3r/GUI/WebGuideDialog.cpp index 78030c68da..9cea8bec28 100644 --- a/src/slic3r/GUI/WebGuideDialog.cpp +++ b/src/slic3r/GUI/WebGuideDialog.cpp @@ -1159,10 +1159,25 @@ bool GuideFrame::run() } int GuideFrame::GetFilamentInfo( std::string VendorDirectory, json & pFilaList, std::string filepath, std::string &sVendor, std::string &sType) +{ + std::unordered_set visiting; + return GetFilamentInfo(VendorDirectory, pFilaList, filepath, sVendor, sType, visiting); +} + +int GuideFrame::GetFilamentInfo(const std::string& VendorDirectory, json& pFilaList, + const std::string& filepath, std::string& sVendor, + std::string& sType, std::unordered_set& visiting) { //GetStardardFilePath(filepath); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " GetFilamentInfo:VendorDirectory - " << VendorDirectory << ", Filepath - "< #include #include +#include #include @@ -110,6 +111,9 @@ public: void on_dpi_changed(const wxRect &suggested_rect) {} private: + int GetFilamentInfo(const std::string& VendorDirectory, json& pFilaList, const std::string& filepath, + std::string& sVendor, std::string& sType, std::unordered_set& visiting); + GUI_App *m_MainPtr; AppConfig m_appconfig_new; From 9bae19fcb33ee03eca8e000555cd197650078b6d Mon Sep 17 00:00:00 2001 From: Kris Austin Date: Wed, 23 Sep 2026 16:21:16 -0500 Subject: [PATCH 3/6] fix: the 3D scene is drawn in the wrong view for the first half second of startup (#15830) --- src/slic3r/GUI/GUI_App.cpp | 3 +++ src/slic3r/GUI/Plater.cpp | 15 ++++++++------- src/slic3r/GUI/Plater.hpp | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 29bab18aeb..6b9b977219 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -865,6 +865,9 @@ void GUI_App::post_init() plater_->canvas3D()->enable_render(false); mainframe->select_tab(TAB_ID_PREPARE); plater_->select_view_3D("3D"); + // The first render happens before the queued new_project() sets the same view. + plater_->get_camera().select_view("topfront"); + plater_->get_camera().requires_zoom_to_bed = true; //BBS init the opengl resource here if (!plater_->canvas3D()->get_wxglcanvas()->IsShownOnScreen() || !plater_->canvas3D()->make_current_for_postinit()) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d4386fbe93..5a10dcd2a7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -7033,7 +7033,7 @@ struct Plater::priv void remove(size_t obj_idx); bool delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); //BBS void delete_all_objects_from_model(); - void reset(bool apply_presets_change = false); + void reset(bool apply_presets_change = false, bool reload_presets = true); void center_selection(); void drop_selection(); void mirror(Axis axis); @@ -7891,7 +7891,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) if (this->q->get_project_filename().IsEmpty() && this->q->is_empty_project()) { int skip_confirm = e.GetInt(); - this->q->new_project(skip_confirm, true); + // Skips the preset reload; trigger_restore_project()'s callers load the presets first. + this->q->new_project(skip_confirm, true, wxString(), false); } }); //wxPostEvent(this->q, wxCommandEvent{EVT_RESTORE_PROJECT}); @@ -10356,7 +10357,7 @@ void Plater::priv::delete_all_objects_from_model() model.plates_custom_gcodes.clear(); } -void Plater::priv::reset(bool apply_presets_change) +void Plater::priv::reset(bool apply_presets_change, bool reload_presets) { // TakeSnapshot below and load_current_presets() further down each re-evaluate the // aggregate dirty flag against a baseline that hasn't been reset yet, so they can toggle @@ -10431,7 +10432,7 @@ void Plater::priv::reset(bool apply_presets_change) wxGetApp().preset_bundle->reset_project_embedded_presets(); if (apply_presets_change) wxGetApp().apply_keeped_preset_modifications(); - else + else if (reload_presets) wxGetApp().load_current_presets(false, false); //BBS @@ -15351,7 +15352,7 @@ Print& Plater::fff_print() { return p->fff_print; } const SLAPrint& Plater::sla_print() const { return p->sla_print; } SLAPrint& Plater::sla_print() { return p->sla_print; } -int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_name) +int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_name, bool reload_presets) { model().calib_pa_pattern.reset(nullptr); model().plates_custom_gcodes.clear(); @@ -15399,7 +15400,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_ // completes, so hold notifications until then to avoid firing on transient flips. ProjectDirtyStateManager::NotificationSuppressor dirty_notify_suppressor(p->dirty_state); - reset(transfer_preset_changes); + reset(transfer_preset_changes, reload_presets); reset_project_dirty_after_save(); reset_project_dirty_initial_presets(); wxGetApp().update_saved_preset_from_current_preset(); @@ -17984,7 +17985,7 @@ void Plater::deselect_all() { p->deselect_all(); } void Plater::exit_gizmo() { p->exit_gizmo(); } void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } -void Plater::reset(bool apply_presets_change) { p->reset(apply_presets_change); } +void Plater::reset(bool apply_presets_change, bool reload_presets) { p->reset(apply_presets_change, reload_presets); } void Plater::reset_with_confirm() { if (p->model.objects.empty() || MessageDialog(static_cast(this), _L("All objects will be removed, continue?"), diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index b30f0298ee..90d0e5e673 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -339,7 +339,7 @@ public: // Helper: returns config indices where filament_is_mixed == false std::vector physical_filament_config_indices() const; - int new_project(bool skip_confirm = false, bool silent = false, const wxString& project_name = wxString()); + int new_project(bool skip_confirm = false, bool silent = false, const wxString& project_name = wxString(), bool reload_presets = true); // BBS: save & backup void load_project(wxString const & filename = "", wxString const & originfile = "-"); int save_project(bool saveAs = false); @@ -499,7 +499,7 @@ public: void deselect_all(); void exit_gizmo(); void remove(size_t obj_idx); - void reset(bool apply_presets_change = false); + void reset(bool apply_presets_change = false, bool reload_presets = true); void reset_with_confirm(); //BBS: return int for various result int close_with_confirm(std::function second_check = nullptr); // BBS close project From 66b300987ba99762c7d93ef2ce8721d474338fda Mon Sep 17 00:00:00 2001 From: Kris Austin Date: Wed, 23 Sep 2026 17:11:10 -0500 Subject: [PATCH 4/6] feat: faster startup by lazy-loading main window panels on idle or first use (#15811) --- docs/HLSD/deferred-page-construction.md | 220 ++++++++++++ src/slic3r/CMakeLists.txt | 8 + src/slic3r/GUI/Auxiliary.cpp | 32 +- src/slic3r/GUI/Auxiliary.hpp | 3 +- src/slic3r/GUI/CAD/DesignPanel.hpp | 3 +- src/slic3r/GUI/CAD/McpControl.cpp | 3 +- src/slic3r/GUI/CalibrationPanel.cpp | 9 +- src/slic3r/GUI/CalibrationPanel.hpp | 4 +- src/slic3r/GUI/CalibrationWizard.cpp | 121 +++---- src/slic3r/GUI/CalibrationWizard.hpp | 6 +- src/slic3r/GUI/CalibrationWizardCaliPage.cpp | 4 +- src/slic3r/GUI/DeviceErrorDialog.cpp | 9 +- .../GUI/DeviceTab/wgtDeviceNozzleRack.cpp | 3 +- .../DeviceTab/wgtDeviceNozzleRackUpdate.cpp | 3 +- src/slic3r/GUI/GUI_App.cpp | 89 +++-- src/slic3r/GUI/GUI_App.hpp | 7 + src/slic3r/GUI/HMSPanel.cpp | 3 +- src/slic3r/GUI/IdleScheduler.cpp | 100 ++++++ src/slic3r/GUI/IdleScheduler.hpp | 41 +++ src/slic3r/GUI/Lazy.cpp | 27 ++ src/slic3r/GUI/Lazy.hpp | 198 +++++++++++ src/slic3r/GUI/LazyPage.cpp | 14 + src/slic3r/GUI/LazyPage.hpp | 77 +++++ src/slic3r/GUI/MainFrame.cpp | 327 +++++++++--------- src/slic3r/GUI/MainFrame.hpp | 44 ++- src/slic3r/GUI/Monitor.cpp | 81 +++-- src/slic3r/GUI/Monitor.hpp | 14 +- src/slic3r/GUI/MultiMachineManagerPage.cpp | 5 +- src/slic3r/GUI/MultiMachinePage.cpp | 1 + src/slic3r/GUI/MultiMachinePage.hpp | 3 +- src/slic3r/GUI/ParamsPanel.cpp | 34 +- src/slic3r/GUI/ParamsPanel.hpp | 21 ++ src/slic3r/GUI/Plater.cpp | 33 +- src/slic3r/GUI/PrebuildQueue.hpp | 89 +++++ src/slic3r/GUI/Preferences.cpp | 9 +- src/slic3r/GUI/PrinterWebView.hpp | 3 +- src/slic3r/GUI/Project.cpp | 2 + src/slic3r/GUI/Project.hpp | 4 +- src/slic3r/GUI/SelectMachine.cpp | 2 +- src/slic3r/GUI/StagedBuild.hpp | 60 ++++ src/slic3r/GUI/StatusPanel.cpp | 165 +++++---- src/slic3r/GUI/StatusPanel.hpp | 8 +- src/slic3r/GUI/Tab.cpp | 73 +++- src/slic3r/GUI/Tab.hpp | 10 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 5 +- src/slic3r/GUI/UnsavedChangesDialog.hpp | 3 +- src/slic3r/GUI/WebViewDialog.cpp | 4 +- src/slic3r/GUI/WebViewDialog.hpp | 3 +- tests/slic3rutils/CMakeLists.txt | 3 + tests/slic3rutils/test_lazy.cpp | 240 +++++++++++++ tests/slic3rutils/test_prebuild_queue.cpp | 183 ++++++++++ tests/slic3rutils/test_staged_build.cpp | 105 ++++++ 52 files changed, 2035 insertions(+), 483 deletions(-) create mode 100644 docs/HLSD/deferred-page-construction.md create mode 100644 src/slic3r/GUI/IdleScheduler.cpp create mode 100644 src/slic3r/GUI/IdleScheduler.hpp create mode 100644 src/slic3r/GUI/Lazy.cpp create mode 100644 src/slic3r/GUI/Lazy.hpp create mode 100644 src/slic3r/GUI/LazyPage.cpp create mode 100644 src/slic3r/GUI/LazyPage.hpp create mode 100644 src/slic3r/GUI/PrebuildQueue.hpp create mode 100644 src/slic3r/GUI/StagedBuild.hpp create mode 100644 tests/slic3rutils/test_lazy.cpp create mode 100644 tests/slic3rutils/test_prebuild_queue.cpp create mode 100644 tests/slic3rutils/test_staged_build.cpp diff --git a/docs/HLSD/deferred-page-construction.md b/docs/HLSD/deferred-page-construction.md new file mode 100644 index 0000000000..748ca65d52 --- /dev/null +++ b/docs/HLSD/deferred-page-construction.md @@ -0,0 +1,220 @@ +# Deferred Page Construction: High Level Design + +## Why it exists + +The main window is a notebook of tabs. When the first frame appears, one tab is on +screen and the others are not; some of them are opened later in the session, some +never, and some only exist for certain printers. Building a tab before the first frame +adds its cost to every startup, whether or not the tab is used. + +This subsystem builds a tab's panel the first time the tab is shown. It also builds the +remaining tabs while the user is idle after startup, in units of tens of milliseconds, +so a click that lands in the middle of one waits for that unit and no longer. Startup +pays only for what the first frame shows, and the other tabs are usually built before +anyone opens them. + +## The parts + +`src/slic3r/GUI/Lazy.hpp`, `LazyPage.hpp`, `StagedBuild.hpp` and `IdleScheduler.hpp/.cpp` +(with its wx-free `PrebuildQueue.hpp`) are independent. A holder can hold anything a +factory makes, a page is a holder with a placeholder widget, a staged object can live +outside a holder, and the scheduler knows none of them; it runs tasks, which `MainFrame` +makes from the holders. + +### Lazy: the holder + +Holds an object that a factory makes on first use, under a name for the log and a place +in the idle queue, both given by the owner. The header has no wx dependency; the busy +cursor for an on-demand build lives in `Lazy.cpp` and is skipped when there is no app, +so the holder is unit-tested. + +- `get()` is null until the object is completely built; `built()` says the same. +- `ensure()` builds whatever is left now, under a busy cursor, and returns the object, or + null in the two cases below. A click on an unbuilt tab or a first open of a dialog goes + through this, and it logs the units and time it took. +- `build_step()` runs one unit of construction and returns true while more remain. The + first unit is the factory call, and each later unit is one `StagedBuild` step if the + type has them. +- `when_built(fn)` runs `fn(object)` now if it exists, otherwise once it is built. +- `pending()` says whether the idle prebuild has work here: not built, and the factory + has not returned null. A null factory result is logged and the holder stays unbuilt. +- A unit that pumps the event loop cannot re-enter the holder; a nested `build_step()` + does nothing and a nested `ensure()` returns null. +- After a unit throws, the holder and the scheduler still run the next one. + +The holder does not own the object; its wx parent does, as for any window. A type with +one instance in the app derives from `LazyInstance`, which points at that instance's +holder (the holder registers itself, and a recreated `MainFrame`'s holder replaces the +old frame's) and gives the type the static entry points the rest of the app uses, +`T::if_built()`, `T::ensure()` and `T::when_built(fn)`. They return null, or do +nothing, while no holder exists, so a caller needs no `mainframe` check. + +`built()` is an atomic flag, since a job worker reads it through the statics +(`MainFrame::get_calibration_curr_tab()`); it is set after the object is complete. + +`LazyBase` is the holder's type-free interface (`name()`, `built()`, `pending()`, +`build_step()`, `prebuild_order()`) and is what the scheduler side sees. + +### LazyPage: the placeholder + +A `wxPanel` placed in the parent in place of the real panel, and a `Lazy` whose +factory makes the panel inside it (by default `new Panel(parent)`). The notebook needs a +page object for the tab to exist and for `show_device()` to insert and remove tabs by +pointer, and the placeholder is that object. `MainFrame` creates every page once, named +after its `TAB_ID_*`, and keeps it for the frame's life; `show_device()` only moves +pages in and out of the book. + +- `Show()` is forwarded to the panel, so a panel's own `Show()` override stays its + activation hook (refresh timers, machine sync) and `SelectPageByName()` works + unchanged. A show builds the panel unless the frame itself is still hidden, because + the book selects its first page as it is inserted; `MainFrame::Show()` shows the + current page again when the frame becomes visible, which builds it. +- `in_book()` says whether the parent notebook currently lists the page, and + `pending()` is that and not built, so a tab `show_device()` has taken out of the book + is not prebuilt. +- A panel built while its page is hidden stays hidden, and a completed panel gets the + dark-mode pass the frame ran before it existed. + +The Compare presets dialog is a holder without a page. `MainFrame` keeps a +`Lazy` whose factory constructs the dialog and binds its events, the +dialog derives from `LazyInstance`, and its callers use +`DiffPresetDialog::ensure()->show()` and `DiffPresetDialog::if_built()` like a tab's +callers do. Saving a preset refreshes the dialog only while it is shown, since `show()` +reloads the presets. + +### StagedBuild: construction in units + +A mixin for a panel whose constructor is too big to be one unit. The constructor builds +the skeleton (sizers, and the parts other code may touch) and queues the rest with +`add_build_step()`. `build_step()` runs one step, and `add_build_steps_of(child)` +forwards a child's steps so a nested panel is spread the same way; the parent is built +only once the child is, including steps the child queues later. Steps run in order, on +the main thread. A `Lazy` recognises a staged type at compile time and runs its steps +one per unit. + +Nothing may touch what a step builds before the last step has run. In practice: + +- nothing paints the panel before it is complete, since a panel built at idle is hidden + with its page and one built on demand finishes inside `ensure()` before the event loop + runs again; +- members created in steps are initialised to null in the header, so a partially built + panel can be destroyed; +- timers and event handlers that use step content check `built()` first + (`MonitorPanel::update_all()`, `CalibrationPanel::update_all()`), and a child's steps + are queued before anything in the constructor can fire such a handler; +- a destructor that disconnects from step content checks `built()` first; +- a constructor or step does not take focus while the panel is off screen + (`IsShownOnScreen()` before `SetFocus()`), since it may run while the user is typing + elsewhere; +- where a step's widgets must keep their place in a sizer that later steps also fill, the + constructor adds an empty slot sizer in that position and the step fills the slot + (`StatusBasePanel`). + +### IdleScheduler: when to build + +A task is any `LazyBase`: a name for the log, `pending()`, `build_step()` and +`prebuild_order()`. `PrebuildQueue` holds the tasks by order (equal order in the order +added) and runs a slice, the units of the first pending task until it completes, the +budget is spent on the clock it is given, or the interrupt predicate says input arrived. +It has no wx dependency and is unit-tested with a fake clock. A task whose work is gone +is passed over and stays in the queue, so a tab that `show_device()` removes and later +re-inserts is pending again. + +`IdleScheduler` drives the queue with the real clock, the app's input timestamp and the +Windows queue check, and logs each unit and slice. Each slice is a timer message: a +period of 250 ms while waiting for the user to go quiet, and a one-shot of zero after a +slice that left work, so the event loop dispatches whatever it has queued (paint, +timers, input) before the next slice runs. Chaining slices with `CallAfter` would not do +this: wx drains pending events fully before the next native message, on every platform. +On GTK the one-shot is 5 ms, because a due GLib timeout runs ahead of the redraw and +idle sources that paint and deliver posted events. +A slice runs only once the user has been idle for the quiet time, and the timer stops +itself once no task is pending. The tick period, quiet time and slice length are +constants in `IdleScheduler.cpp`. A unit cannot be interrupted once started, so the +largest unit bounds click latency on Windows; on the other platforms a click also waits +for the rest of the slice. A unit that pumps the event loop lets the timer fire inside +its own slice, and that tick does nothing. + +The tasks are made by their owners. `MainFrame::prebuild_pages_when_idle()` registers +every `LazyPage` the frame created, in or out of the book (`pending()` is false for a +page out of the book), the Compare presets holder, and the Prepare sidebar's settings +page from `ParamsPanel::settings_page_prebuild()`, whose first unit selects the default +tab if none is selected yet and whose later units build one option group each. +`show_device()` only restarts the timer. `MainFrame` owns the scheduler because it owns +everything the tasks build, and clearing the queue with the frame is what keeps a task +from outliving its object. + +Idle time comes from `GUI_App::FilterEvent`, which timestamps mouse and keyboard events +(`wxEVT_CATEGORY_USER_INPUT` minus command events, which all claim that category), and +`GUI_App::input_idle_ms()` reports it. On Windows a slice additionally refuses to start +when the message queue holds keyboard, button, touch or pen input. Mouse moves are +excluded because Windows synthesises one whenever a window appears under the cursor, +which every unit does. Other platforms use the timestamp alone. + +Once every registered page is built the timer is stopped and the subsystem costs +nothing. + +## Rules + +**What builds before the first frame.** The Prepare tab's plater, because `post_init()` +needs its GL canvas on screen to initialise OpenGL in every startup state, and the start +page the user configured. Home is built by the first `MainFrame::Show()`, Prepare's +settings page by selecting the tab. `post_init()` passes through the Prepare tab for GL +init under `Freeze()` with `MainFrame::select_prepare_for_gl_init()`, which changes the +selection without the page-changed event, so nothing else is built for that pass. + +**Reaching a lazy object.** A caller uses the type's own statics. `T::if_built()` may +return null and is for telling the object something it can live without (a rescale, a +colour change, a status update). `T::ensure()` builds the object and is for navigating +to it or for a caller that is about to show it. A caller that tells the object something +it would not fetch for itself on construction uses `T::when_built()`, which keeps the +message until the object exists. A panel that pulls its state when constructed (the Home +page requests the recent list on load, the Device tab reads the device manager on show) +is reached with `if_built()`; one that cannot pull gets `when_built()`. + +**Unit size.** A unit cannot be interrupted, so it should stay within the slice length on +a fast machine. A constructor above that is staged. A single widget above it is the +floor unless the widget itself is split. + +**Order.** Cheapest and most likely to be opened first, given where `MainFrame` creates +each holder. The settings page is 0 (the Prepare tab's own content), Home 10, Device 20 +(a Bambu user's usual second stop), Calibration 30, Multi-device 40, the web Device +view 50, Project 60 (a second WebView2 instance) and the Compare presets dialog 100; +steps of ten so a new tab takes a value between its neighbours without renumbering +them. `MainFrame::prebuild_pages_when_idle()` registers the tasks once, from +`post_init()`. + +**Never prebuilt.** A holder with a negative order, for a tab that few sessions open +and that costs more to build unasked than it saves (the Design tab), and plugin-provided +tabs, which are Python-side and not lazy pages. + +## Adopting it + +A lazy tab needs: + +1. The panel derived from `LazyInstance`, since a tab's panel has one instance. +2. A `LazyPage*` member in `MainFrame`, created once in `init_tabpanel()` with + its `TAB_ID_*` as the name, its place by the order rule (and a factory if + `new Panel(parent)` is not enough), added to `m_lazy_pages`, and used wherever the + tab is added to or looked up in the notebook. +3. Every use of the panel outside `MainFrame` going through one of the panel's statics, + chosen by the rule above. When converting an existing member, `grep` for it; the + compiler finds the rest. +4. A constructor that copes with the frame already existing and the user being busy + elsewhere, since `wxGetApp().mainframe` is set, the frame may be shown, and the user + may be typing when a lazy panel is built: no `SetFocus()` while off screen, and + whatever the constructor did through a `MainFrame` accessor before (a mode update, a + deferred URL) done in the constructor itself. + +To stage a heavy constructor, inherit `StagedBuild`, keep the skeleton in the constructor, +move the rest into `add_build_step()` lambdas in the original order, and follow the +staged-panel rules above. Measure the units. A step that is still one big widget has to +be split inside that widget or accepted as the floor. + +Verification is by log. `MainFrame::prebuild_pages_when_idle` lists the queue it +registered, `IdleScheduler::tick` reports each completed task by name at info level and +each slice and unit at debug level, and `Lazy::ensure` reports an object a user built +on demand with the units and time it took. A run from the configured start +page shows every registered page complete, in order, with no unit longer than intended. +A click on a tab mid-prebuild shows the finished panel with an `ensure` line for what was +left, and the slices resume for the remaining tasks once the user is idle again. diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 7ac307c87b..584fc2a2aa 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -286,6 +286,8 @@ set(SLIC3R_GUI_SOURCES GUI/FilamentMapDialog.hpp GUI/IconManager.cpp GUI/IconManager.hpp + GUI/IdleScheduler.cpp + GUI/IdleScheduler.hpp GUI/ImageGrid.cpp GUI/ImageGrid.h GUI/ImGuiWrapper.cpp @@ -347,6 +349,10 @@ set(SLIC3R_GUI_SOURCES GUI/KBShortcutsDialog.hpp GUI/KeyChord.cpp GUI/KeyChord.hpp + GUI/Lazy.cpp + GUI/Lazy.hpp + GUI/LazyPage.cpp + GUI/LazyPage.hpp GUI/LibVGCode/LibVGCodeWrapper.hpp GUI/LibVGCode/LibVGCodeWrapper.cpp GUI/LinuxDisplayBackend.cpp @@ -433,6 +439,7 @@ set(SLIC3R_GUI_SOURCES GUI/Plater.hpp GUI/PlateSettingsDialog.cpp GUI/PlateSettingsDialog.hpp + GUI/PrebuildQueue.hpp GUI/Preferences.cpp GUI/Preferences.hpp GUI/PresetBundleDialog.cpp @@ -512,6 +519,7 @@ set(SLIC3R_GUI_SOURCES GUI/SliceInfoPanel.hpp GUI/SlicingProgressNotification.cpp GUI/SlicingProgressNotification.hpp + GUI/StagedBuild.hpp GUI/StatusPanel.cpp GUI/StatusPanel.hpp GUI/StepMeshDialog.cpp diff --git a/src/slic3r/GUI/Auxiliary.cpp b/src/slic3r/GUI/Auxiliary.cpp index 13ca173eb6..14b8d238a2 100644 --- a/src/slic3r/GUI/Auxiliary.cpp +++ b/src/slic3r/GUI/Auxiliary.cpp @@ -863,17 +863,27 @@ void AuxiliaryPanel::init_tabpanel() m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF")); m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [](wxBookCtrlEvent &e) { /* Event handling */ }); - m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER); - m_pictures_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE); - m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS); - m_assembly_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE); - m_others_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS); - - m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), true); - m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), false); - m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), false); - m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), false); - m_tabpanel->AddPage(m_others_panel, _L("Others"), false); + add_build_step([this] { + m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER); + m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), true); + }); + add_build_step([this] { + m_pictures_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE); + m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), false); + }); + add_build_step([this] { + m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS); + m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), false); + }); + add_build_step([this] { + m_assembly_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE); + m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), false); + }); + add_build_step([this] { + m_others_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS); + m_tabpanel->AddPage(m_others_panel, _L("Others"), false); + Layout(); + }); } wxWindow *AuxiliaryPanel::create_side_tools() diff --git a/src/slic3r/GUI/Auxiliary.hpp b/src/slic3r/GUI/Auxiliary.hpp index 0bced37115..76e6adf97b 100644 --- a/src/slic3r/GUI/Auxiliary.hpp +++ b/src/slic3r/GUI/Auxiliary.hpp @@ -46,6 +46,7 @@ #include "slic3r/GUI/UpgradePanel.hpp" #include "slic3r/GUI/AmsWidgets.hpp" #include "Widgets/SideTools.hpp" +#include "StagedBuild.hpp" #define AUFILE_GREY700 wxColour(107, 107, 107) #define AUFILE_GREY500 wxColour(158, 158, 158) @@ -194,7 +195,7 @@ public: }; -class AuxiliaryPanel : public wxPanel +class AuxiliaryPanel : public wxPanel, public StagedBuild { private: Tabbook *m_tabpanel = {nullptr}; diff --git a/src/slic3r/GUI/CAD/DesignPanel.hpp b/src/slic3r/GUI/CAD/DesignPanel.hpp index 88b445534d..16f0a2722c 100644 --- a/src/slic3r/GUI/CAD/DesignPanel.hpp +++ b/src/slic3r/GUI/CAD/DesignPanel.hpp @@ -12,6 +12,7 @@ #include "libslic3r/CAD/CadDocument.hpp" #include "slic3r/GUI/CAD/DesignInteraction.hpp" // CadLevel: what one Esc press means +#include "slic3r/GUI/Lazy.hpp" class ComboBox; // Orca dropdown (Widgets/ComboBox.hpp) — replaces wxChoice everywhere here class StaticBox; // Orca rounded card frame (Widgets/StaticBox.hpp) @@ -46,7 +47,7 @@ class DesignCanvas; // Design (CAD) tab: a sketch-first, Onshape-style form-driven CAD panel. // Sketch and Extrude are independent tools: the user creates a Sketch first, // then selects it and Extrudes to produce a solid. -class DesignPanel : public wxPanel +class DesignPanel : public wxPanel, public LazyInstance { public: explicit DesignPanel(wxWindow* parent); diff --git a/src/slic3r/GUI/CAD/McpControl.cpp b/src/slic3r/GUI/CAD/McpControl.cpp index 8e34e2aac8..0ad05667c3 100644 --- a/src/slic3r/GUI/CAD/McpControl.cpp +++ b/src/slic3r/GUI/CAD/McpControl.cpp @@ -1989,11 +1989,10 @@ json action_set_feature_expr(DesignPanel* panel, const json& params) // Dispatch one parsed request ON THE MAIN THREAD. Returns a JSON-RPC reply string. std::string handle_on_main(const std::string& method, const json& params, const json& id) { - MainFrame* mf = wxGetApp().mainframe; // The panel is built on first use, and in a headless session nobody clicks the tab that // would build it -- so build it here rather than refusing. Safe: this runs on the main // thread (see the CallAfter that dispatches us). - DesignPanel* panel = mf ? mf->ensure_design_panel() : nullptr; + DesignPanel* panel = DesignPanel::ensure(); if (!panel) return rpc_error(id, -32001, "Design panel not ready"); diff --git a/src/slic3r/GUI/CalibrationPanel.cpp b/src/slic3r/GUI/CalibrationPanel.cpp index bdc79c1c8e..fca9fa2be9 100644 --- a/src/slic3r/GUI/CalibrationPanel.cpp +++ b/src/slic3r/GUI/CalibrationPanel.cpp @@ -491,14 +491,15 @@ void CalibrationPanel::init_tabpanel() { selected); } + for (int i = 0; i < (int)CALI_MODE_COUNT; i++) + add_build_steps_of(*m_cali_panels[i]); + // ORCA use standard paddings and keep arrow icon for consistent look between sidebars //for (int i = 0; i < (int)CALI_MODE_COUNT; i++) // m_tabpanel->SetPageImage(i, ""); //auto padding_size = m_tabpanel->GetBtnsListCtrl()->GetPaddingSize(0); //m_tabpanel->GetBtnsListCtrl()->SetPaddingSize({ FromDIP(15), padding_size.y }); - - m_initialized = true; } void CalibrationPanel::init_timer() @@ -534,6 +535,8 @@ void CalibrationPanel::update_print_error_info(int code, std::string msg, std::s } void CalibrationPanel::update_all() { + // Every wizard's pages exist once the last build step has run. + if (!built()) return; NetworkAgent* m_agent = wxGetApp().getAgent(); Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); @@ -597,7 +600,7 @@ void CalibrationPanel::update_all() { void CalibrationPanel::show_status(int status) { - if (!m_initialized) return; + if (!built()) return; if (last_status == status)return; last_status = status; diff --git a/src/slic3r/GUI/CalibrationPanel.hpp b/src/slic3r/GUI/CalibrationPanel.hpp index 1f6b097af9..960c5eed37 100644 --- a/src/slic3r/GUI/CalibrationPanel.hpp +++ b/src/slic3r/GUI/CalibrationPanel.hpp @@ -3,6 +3,7 @@ #include "CalibrationWizard.hpp" #include "Tabbook.hpp" +#include "Lazy.hpp" //#include "Widgets/SideTools.hpp" namespace Slic3r { namespace GUI { @@ -88,7 +89,7 @@ private: }; -class CalibrationPanel : public wxPanel +class CalibrationPanel : public wxPanel, public StagedBuild, public LazyInstance { public: CalibrationPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL); @@ -109,7 +110,6 @@ protected: int last_status; - bool m_initialized { false }; std::string last_conn_type = "undedefined"; MachineObject* obj{ nullptr }; MachineObject* last_obj { nullptr }; diff --git a/src/slic3r/GUI/CalibrationWizard.cpp b/src/slic3r/GUI/CalibrationWizard.cpp index f80562578d..fa42143f06 100644 --- a/src/slic3r/GUI/CalibrationWizard.cpp +++ b/src/slic3r/GUI/CalibrationWizard.cpp @@ -130,6 +130,15 @@ CalibrationWizard::~CalibrationWizard() ; } +void CalibrationWizard::add_page_step(CalibrationWizardPageStep*& step, std::function make) +{ + add_build_step([this, &step, make = std::move(make)] { + step = new CalibrationWizardPageStep(make()); + m_all_pages_sizer->Add(step->page, 1, wxEXPAND | wxALL, FromDIP(25)); + step->page->Hide(); + }); +} + void CalibrationWizard::on_cali_job_finished(wxCommandEvent& event) { this->on_cali_job_finished(event.GetString()); @@ -520,33 +529,28 @@ void PressureAdvanceWizard::on_cali_job_finished(wxString evt_data) void PressureAdvanceWizard::create_pages() { - start_step = new CalibrationWizardPageStep(new CalibrationPAStartPage(m_scrolledWindow)); - preset_step = new CalibrationWizardPageStep(new CalibrationPresetPage(m_scrolledWindow, m_mode, false)); - cali_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode)); - save_step = new CalibrationWizardPageStep(new CalibrationPASavePage(m_scrolledWindow)); + add_page_step(start_step, [this] { return new CalibrationPAStartPage(m_scrolledWindow); }); + add_page_step(preset_step, [this] { return new CalibrationPresetPage(m_scrolledWindow, m_mode, false); }); + add_page_step(cali_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode); }); + add_page_step(save_step, [this] { return new CalibrationPASavePage(m_scrolledWindow); }); - m_all_pages_sizer->Add(start_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(preset_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(cali_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); + add_build_step([this] { + m_page_steps.push_back(start_step); + m_page_steps.push_back(preset_step); + m_page_steps.push_back(cali_step); + m_page_steps.push_back(save_step); + for (int i = 0; i < m_page_steps.size() -1; i++) { + m_page_steps[i]->chain(m_page_steps[i+1]); + } - m_page_steps.push_back(start_step); - m_page_steps.push_back(preset_step); - m_page_steps.push_back(cali_step); - m_page_steps.push_back(save_step); + for (int i = 0; i < m_page_steps.size(); i++) { + m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &PressureAdvanceWizard::on_cali_action, this); + } - for (int i = 0; i < m_page_steps.size() -1; i++) { - m_page_steps[i]->chain(m_page_steps[i+1]); - } - - for (int i = 0; i < m_page_steps.size(); i++) { - m_page_steps[i]->page->Hide(); - m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &PressureAdvanceWizard::on_cali_action, this); - } - - if (!m_page_steps.empty()) - show_step(m_page_steps.front()); + if (!m_page_steps.empty()) + show_step(m_page_steps.front()); + }); } void PressureAdvanceWizard::on_cali_action(wxCommandEvent& evt) @@ -1053,59 +1057,46 @@ FlowRateWizard::FlowRateWizard(wxWindow* parent, wxWindowID id, const wxPoint& p void FlowRateWizard::create_pages() { - start_step = new CalibrationWizardPageStep(new CalibrationFlowRateStartPage(m_scrolledWindow)); - preset_step = new CalibrationWizardPageStep(new CalibrationPresetPage(m_scrolledWindow, m_mode, false)); + add_page_step(start_step, [this] { return new CalibrationFlowRateStartPage(m_scrolledWindow); }); + add_page_step(preset_step, [this] { return new CalibrationPresetPage(m_scrolledWindow, m_mode, false); }); // manual - cali_coarse_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_CALI)); - coarse_save_step = new CalibrationWizardPageStep(new CalibrationFlowCoarseSavePage(m_scrolledWindow)); - cali_fine_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_FINE_CALI)); - fine_save_step = new CalibrationWizardPageStep(new CalibrationFlowFineSavePage(m_scrolledWindow)); + add_page_step(cali_coarse_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_CALI); }); + add_page_step(coarse_save_step, [this] { return new CalibrationFlowCoarseSavePage(m_scrolledWindow); }); + add_page_step(cali_fine_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_FINE_CALI); }); + add_page_step(fine_save_step, [this] { return new CalibrationFlowFineSavePage(m_scrolledWindow); }); // auto - cali_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode)); - save_step = new CalibrationWizardPageStep(new CalibrationFlowX1SavePage(m_scrolledWindow)); + add_page_step(cali_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode); }); + add_page_step(save_step, [this] { return new CalibrationFlowX1SavePage(m_scrolledWindow); }); - m_all_pages_sizer->Add(start_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(preset_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(cali_coarse_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(coarse_save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(cali_fine_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(fine_save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); + add_build_step([this] { + m_page_steps.push_back(start_step); + m_page_steps.push_back(preset_step); + m_page_steps.push_back(cali_coarse_step); + m_page_steps.push_back(coarse_save_step); + m_page_steps.push_back(cali_fine_step); + m_page_steps.push_back(fine_save_step); - m_all_pages_sizer->Add(cali_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); - m_all_pages_sizer->Add(save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); + //m_page_steps.push_back(cali_step); + //m_page_steps.push_back(save_step); - m_page_steps.push_back(start_step); - m_page_steps.push_back(preset_step); - m_page_steps.push_back(cali_coarse_step); - m_page_steps.push_back(coarse_save_step); - m_page_steps.push_back(cali_fine_step); - m_page_steps.push_back(fine_save_step); + for (int i = 0; i < m_page_steps.size() - 1; i++) { + m_page_steps[i]->chain(m_page_steps[i + 1]); + } - //m_page_steps.push_back(cali_step); - //m_page_steps.push_back(save_step); + for (int i = 0; i < m_page_steps.size(); i++) { + m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); + } - for (int i = 0; i < m_page_steps.size() - 1; i++) { - m_page_steps[i]->chain(m_page_steps[i + 1]); - } + cali_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); + save_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); - // hide all pages - cali_step->page->Hide(); - save_step->page->Hide(); - for (int i = 0; i < m_page_steps.size(); i++) { - m_page_steps[i]->page->Hide(); - m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); - } + if (!m_page_steps.empty()) + show_step(m_page_steps.front()); - - cali_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); - save_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); - - if (!m_page_steps.empty()) - show_step(m_page_steps.front()); - - set_cali_method(CalibrationMethod::CALI_METHOD_MANUAL); + set_cali_method(CalibrationMethod::CALI_METHOD_MANUAL); + }); } void FlowRateWizard::on_cali_action(wxCommandEvent& evt) diff --git a/src/slic3r/GUI/CalibrationWizard.hpp b/src/slic3r/GUI/CalibrationWizard.hpp index d72d5fcb7b..89c515eb80 100644 --- a/src/slic3r/GUI/CalibrationWizard.hpp +++ b/src/slic3r/GUI/CalibrationWizard.hpp @@ -9,6 +9,7 @@ #include "CalibrationWizardPresetPage.hpp" #include "CalibrationWizardCaliPage.hpp" #include "CalibrationWizardSavePage.hpp" +#include "StagedBuild.hpp" namespace Slic3r { namespace GUI { @@ -36,7 +37,7 @@ struct ConfigIndexValue int index{0}; }; -class CalibrationWizard : public wxPanel { +class CalibrationWizard : public wxPanel, public StagedBuild { public: CalibrationWizard(wxWindow* parent, CalibMode mode, wxWindowID id = wxID_ANY, @@ -79,6 +80,9 @@ public: protected: void on_cali_go_home(); + // Queues a page as a build step, created hidden and added to the pages sizer. + void add_page_step(CalibrationWizardPageStep*& step, std::function make); + protected: /* wx widgets*/ wxScrolledWindow* m_scrolledWindow; diff --git a/src/slic3r/GUI/CalibrationWizardCaliPage.cpp b/src/slic3r/GUI/CalibrationWizardCaliPage.cpp index 152f46f37c..2dc766dca3 100644 --- a/src/slic3r/GUI/CalibrationWizardCaliPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardCaliPage.cpp @@ -192,8 +192,10 @@ void CalibrationCaliPage::update(MachineObject* obj) set_cali_img(); } + // A calibration can run before the Device tab is ever opened, and only its status + // panel shows a print error. if (obj->print_error > 0) { - StatusPanel* status_panel = Slic3r::GUI::wxGetApp().mainframe->m_monitor->get_status_panel(); + StatusPanel* status_panel = MonitorPanel::ensure()->get_status_panel(); status_panel->obj = obj; status_panel->update_error_message(); } diff --git a/src/slic3r/GUI/DeviceErrorDialog.cpp b/src/slic3r/GUI/DeviceErrorDialog.cpp index 2a55d77d24..9790db67bd 100644 --- a/src/slic3r/GUI/DeviceErrorDialog.cpp +++ b/src/slic3r/GUI/DeviceErrorDialog.cpp @@ -538,7 +538,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id) break; } case DeviceErrorDialog::CHECK_ASSISTANT: { - wxGetApp().mainframe->m_monitor->jump_to_HMS(); // go to assistant page + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->jump_to_HMS(); // go to assistant page break; } case DeviceErrorDialog::FILAMENT_EXTRUDED: { @@ -568,7 +569,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id) } case DeviceErrorDialog::JUMP_TO_LIVEVIEW: { Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); - Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_LiveView(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->jump_to_LiveView(); break; } case DeviceErrorDialog::NO_REMINDER_NEXT_TIME: { @@ -618,7 +620,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id) } case DeviceErrorDialog::OK_JUMP_RACK: { Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); - Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_Rack(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->jump_to_Rack(); break; } case DeviceErrorDialog::ABORT: { diff --git a/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp b/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp index 44394866c8..00d4c3e809 100644 --- a/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp +++ b/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp @@ -934,7 +934,8 @@ void wgtDeviceNozzleRackNozzleItem::OnBtnNozzleStatus(wxMouseEvent& evt) dlg.AddButton(wxID_OK,_L("Jump to the upgrade page"), true); if (dlg.ShowModal() == wxID_OK) { - wxGetApp().mainframe->m_monitor->jump_to_Upgrade(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->jump_to_Upgrade(); }; } } diff --git a/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp b/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp index fac14e31d9..eae377c147 100644 --- a/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp +++ b/src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp @@ -344,7 +344,8 @@ void wgtDeviceNozzleRackHotendUpdate::OnStatusIconClick(wxMouseEvent& event) if (dlg.ShowModal() == wxID_OK) { - wxGetApp().mainframe->m_monitor->jump_to_Upgrade(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->jump_to_Upgrade(); wxCommandEvent evt(wxEVT_NOZZLE_JUMP_UPGRADE, GetId()); evt.SetEventObject(this); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 6b9b977219..1a153ed4fb 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -863,7 +863,7 @@ void GUI_App::post_init() mainframe->Freeze(); #endif plater_->canvas3D()->enable_render(false); - mainframe->select_tab(TAB_ID_PREPARE); + mainframe->select_prepare_for_gl_init(); plater_->select_view_3D("3D"); // The first render happens before the queued new_project() sets the same view. plater_->get_camera().select_view("topfront"); @@ -903,10 +903,10 @@ void GUI_App::post_init() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test"; } } - if (is_editor()) - mainframe->select_tab(TAB_ID_HOME); - if (app_config->get("default_page") == "1") + if (starts_on_prepare()) mainframe->select_tab(TAB_ID_PREPARE); + else if (is_editor()) + mainframe->select_tab(TAB_ID_HOME); #ifndef __linux__ mainframe->Thaw(); #endif @@ -915,6 +915,7 @@ void GUI_App::post_init() plater_->trigger_restore_project(1); //#endif + mainframe->prebuild_pages_when_idle(); //BBS: remove GCodeViewer as seperate APP logic /*if (this->init_params->start_as_gcodeviewer) { @@ -1929,9 +1930,9 @@ bool GUI_App::hot_reload_network_plugin() m_device_manager->add_user_subscribe(); } - if (mainframe && mainframe->m_monitor) { - mainframe->m_monitor->update_network_version_footer(); - mainframe->m_monitor->set_default(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) { + monitor->update_network_version_footer(); + monitor->set_default(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": reset monitor panel"; } @@ -3422,14 +3423,16 @@ bool GUI_App::on_init_inner() } BOOST_LOG_TRIVIAL(info) << "create the main window"; mainframe = new MainFrame(); - // hide settings tabs after first Layout if (is_editor()) { - mainframe->select_tab(TAB_ID_HOME); + if (starts_on_prepare()) { + mainframe->select_tab(TAB_ID_PREPARE); + } else { + mainframe->select_tab(TAB_ID_HOME); + } } sidebar().obj_list()->init(); //sidebar().aux_list()->init_auxiliary(); - mainframe->m_project->init_auxiliary(); // update_mode(); // !!! do that later SetTopWindow(mainframe); @@ -4140,13 +4143,13 @@ void GUI_App::select_machine(const std::string& agent_id) // Use MonitorPanel::select_machine() to trigger full selection flow // This reuses existing logic for machine switching (UI updates, callbacks, etc.) - if (mainframe && mainframe->m_monitor) { - mainframe->m_monitor->select_machine(dev_id); + if (MonitorPanel* monitor = MonitorPanel::if_built()) { + monitor->select_machine(dev_id); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": triggered select_machine for dev_id=" << dev_id; - } else { - // Fallback if MonitorPanel not available - m_device_manager->set_selected_machine(dev_id); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": fallback set_selected_machine dev_id=" << dev_id; + } else if (m_device_manager->set_selected_machine(dev_id)) { + // The Device tab's own state is set when the tab is built. + MonitorPanel::on_machine_selected(m_device_manager->get_selected_machine()); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": set_selected_machine dev_id=" << dev_id; } } @@ -4670,6 +4673,7 @@ void GUI_App::recreate_GUI(const wxString &msg_name) //BBS: trigger restore project logic here, and skip confirm plater_->trigger_restore_project(1); + mainframe->prebuild_pages_when_idle(); // #ys_FIXME_delete_after_testing Do we still need this ? // CallAfter([]() { @@ -5011,7 +5015,8 @@ void GUI_App::get_login_info(const std::string& provider/* = ORCA_CLOUD_PROVIDER wxString strJS = wxString::Format("window.postMessage(%s)", from_u8(logout_cmd)); GUI::wxGetApp().run_script(strJS); } - mainframe->m_webview->SetLoginPanelVisibility(true); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SetLoginPanelVisibility(true); } } @@ -5143,9 +5148,9 @@ std::string GUI_App::handle_web_request(std::string cmd) "homepage_bambu_login_or_register", }; if (app_config->get_stealth_mode() && stealth_blocked_info_commands.count(command_str)) { - CallAfter([this] { - if (mainframe && mainframe->m_webview) - mainframe->m_webview->SendCloudProvidersInfo(); + CallAfter([] { + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendCloudProvidersInfo(); }); return ""; } @@ -5159,8 +5164,8 @@ std::string GUI_App::handle_web_request(std::string cmd) if (dlg.ShowModal() == wxID_OK) { app_config->set_bool("stealth_mode", false); app_config->save(); - if (mainframe && mainframe->m_webview) - mainframe->m_webview->SendCloudProvidersInfo(); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendCloudProvidersInfo(); // Continue with login if (command_str == "homepage_login_or_register") this->request_login(true); @@ -5241,8 +5246,8 @@ std::string GUI_App::handle_web_request(std::string cmd) } else if (command_str.compare("get_recent_projects") == 0) { if (mainframe) { - if (mainframe->m_webview) { - mainframe->m_webview->SendRecentList(INT_MAX); + if (WebViewPanel* home = WebViewPanel::if_built()) { + home->SendRecentList(INT_MAX); } } } @@ -7775,8 +7780,8 @@ void GUI_App::on_stealth_mode_enter() BOOST_LOG_TRIVIAL(info) << "logout: on_stealth_mode_enter"; request_user_logout(ORCA_CLOUD_PROVIDER); request_user_logout(BBL_CLOUD_PROVIDER); - if (mainframe && mainframe->m_webview) { - mainframe->m_webview->SendCloudProvidersInfo(); + if (WebViewPanel* home = WebViewPanel::if_built()) { + home->SendCloudProvidersInfo(); } } @@ -8186,6 +8191,24 @@ ConfigOptionMode GUI_App::get_saved_mode() return saved_mode_from_string(app_config->get("user_mode")); } +bool GUI_App::starts_on_prepare() const +{ + return app_config->get("default_page") == "1"; +} + +int GUI_App::input_idle_ms() const +{ + return int(std::chrono::duration_cast(std::chrono::steady_clock::now() - m_last_input).count()); +} + +// Every wxCommandEvent claims the user-input category, so only real mouse and key events count. +int GUI_App::FilterEvent(wxEvent& event) +{ + if (!event.IsCommandEvent() && (event.GetEventCategory() & wxEVT_CATEGORY_USER_INPUT)) + m_last_input = std::chrono::steady_clock::now(); + return Event_Skip; +} + ConfigOptionMode GUI_App::get_mode() { return app_config->get_bool("developer_mode") ? comDevelop : get_saved_mode(); @@ -8237,9 +8260,10 @@ void GUI_App::update_mode() mainframe->m_param_panel->update_mode(); if (mainframe->m_param_dialog) mainframe->m_param_dialog->panel()->update_mode(); - if (mainframe->m_printer_view) - mainframe->m_printer_view->update_mode(); - mainframe->m_webview->update_mode(); + if (PrinterWebView* view = PrinterWebView::if_built()) + view->update_mode(); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->update_mode(); #ifdef _MSW_DARK_MODE if (!wxGetApp().tabs_as_menu()) @@ -8257,9 +8281,10 @@ void GUI_App::update_mode() } void GUI_App::update_internal_development() { - mainframe->m_webview->update_mode(); - if (mainframe->m_printer_view) - mainframe->m_printer_view->update_mode(); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->update_mode(); + if (PrinterWebView* view = PrinterWebView::if_built()) + view->update_mode(); } void GUI_App::show_ip_address_enter_dialog(wxString title) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 2d55c5e96c..e888a52b06 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_GUI_App_hpp_ #define slic3r_GUI_App_hpp_ +#include #include #include #include @@ -248,6 +249,7 @@ private: bool m_app_conf_exists{ false }; EAppMode m_app_mode{ EAppMode::Editor }; bool m_is_recreating_gui{ false }; + std::chrono::steady_clock::time_point m_last_input{ std::chrono::steady_clock::now() }; #ifdef __linux__ bool m_opengl_initialized{ false }; #endif @@ -387,6 +389,11 @@ public: bool is_editor() const { return m_app_mode == EAppMode::Editor; } bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; } bool is_recreating_gui() const { return m_is_recreating_gui; } + // Milliseconds since the last mouse or keyboard event the app processed. + int input_idle_ms() const; + int FilterEvent(wxEvent& event) override; + // The Preferences "Default page" choice, stored as its index: 0 Home, 1 Prepare. + bool starts_on_prepare() const; std::string logo_name() const { return is_editor() ? "OrcaSlicer" : "OrcaSlicer-gcodeviewer"; } bool is_closing() const { return m_is_closing.load(std::memory_order_acquire); } diff --git a/src/slic3r/GUI/HMSPanel.cpp b/src/slic3r/GUI/HMSPanel.cpp index cd3d35bfc8..c2a8314bd5 100644 --- a/src/slic3r/GUI/HMSPanel.cpp +++ b/src/slic3r/GUI/HMSPanel.cpp @@ -122,7 +122,8 @@ HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMS m_hms_content->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) { wxCommandEvent evt(EVT_ALREADY_READ_HMS); evt.SetString(long_error_code); - wxPostEvent(wxGetApp().mainframe->m_monitor, evt); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + wxPostEvent(monitor, evt); if (!m_url.empty()) wxLaunchDefaultBrowser(m_url); }); diff --git a/src/slic3r/GUI/IdleScheduler.cpp b/src/slic3r/GUI/IdleScheduler.cpp new file mode 100644 index 0000000000..2b71a9f8e6 --- /dev/null +++ b/src/slic3r/GUI/IdleScheduler.cpp @@ -0,0 +1,100 @@ +#include "IdleScheduler.hpp" + +#include + +#include + +#include "libslic3r/Utils.hpp" + +#ifdef _WIN32 +#include +#endif + +namespace Slic3r { namespace GUI { + +namespace { + +// The timer's period while waiting for the user to go quiet. +constexpr int tick_ms = 250; +// Input-free time before a slice may start, about a double-click interval, so a user +// mid-gesture is left alone. +constexpr int quiet_ms = 500; +// Budget of one slice. The next slice is a timer message, so paint, timers and input +// queued meanwhile are handled first; a click waits at most a slice plus the unit that +// overran it. +constexpr int slice_ms = 40; +// On GTK a due timer runs ahead of repaints and posted events, so the next slice waits a few ms. +#ifdef __WXGTK__ +constexpr int next_slice_ms = 5; +#else +constexpr int next_slice_ms = 0; +#endif + +// True when unhandled keyboard, button, touch or pen input is queued; only Windows can ask. +bool input_pending() +{ +#ifdef _WIN32 + // Windows synthesizes a mouse move whenever a window appears under the cursor, so those + // do not count. + return (GetQueueStatus(QS_INPUT & ~QS_MOUSEMOVE) >> 16) != 0; +#else + return false; +#endif +} + +} // namespace + +IdleScheduler::IdleScheduler(std::function input_idle_ms) : m_input_idle_ms(std::move(input_idle_ms)) +{ + m_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&) { tick(); }); +} + +void IdleScheduler::start() +{ + if (!m_timer.IsRunning()) + m_timer.Start(tick_ms); +} + +void IdleScheduler::stop() +{ + m_timer.Stop(); +} + +void IdleScheduler::tick() +{ + // A unit that pumps the event loop lets the timer fire inside its own slice. + if (m_in_slice) + return; + if (!m_queue.pending()) { + stop(); + return; + } + if (m_input_idle_ms() < quiet_ms || input_pending()) { + start(); + return; + } + const auto now_ms = [] { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + }; + const char* const fn = __FUNCTION__; + m_in_slice = true; + PrebuildQueue::Slice slice; + { + ScopeGuard in_slice([this] { m_in_slice = false; }); + slice = m_queue.run_slice(slice_ms, now_ms, input_pending, [fn](const std::string& name, long long ms) { + BOOST_LOG_TRIVIAL(debug) << fn << ": " << name << ": unit took " << ms << " ms"; + }); + } + if (slice.completed) + BOOST_LOG_TRIVIAL(info) << fn << ": task complete: " << slice.name << ", " << slice.units << " unit(s) in " << slice.ms << " ms this slice"; + else + BOOST_LOG_TRIVIAL(debug) << fn << ": " << slice.name << ": " << slice.units << " unit(s) in " << slice.ms << " ms, yielding"; + if (!slice.remaining) + stop(); + else if (input_pending()) + m_timer.Start(tick_ms); + else + m_timer.StartOnce(next_slice_ms); +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/IdleScheduler.hpp b/src/slic3r/GUI/IdleScheduler.hpp new file mode 100644 index 0000000000..7c31e9414c --- /dev/null +++ b/src/slic3r/GUI/IdleScheduler.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +#include +#include + +#include "PrebuildQueue.hpp" + +namespace Slic3r { namespace GUI { + +// Runs the queue's units while the user is idle. Once the user has been idle long enough, +// slices run one per timer message until the work is done or input arrives, so the event +// loop handles what it has between slices. Main thread only. +class IdleScheduler +{ +public: + // input_idle_ms reports how long ago the user last touched the mouse or keyboard. + explicit IdleScheduler(std::function input_idle_ms); + + void add(LazyBase& task) { m_queue.add(task); } + void clear() { m_queue.clear(); } + // The task names in queue order, for a log line. + std::string names() const { return m_queue.names(); } + + // Arms the timer; it stops itself once no task is pending, so call again when a task + // appears. + void start(); + void stop(); + +private: + void tick(); + + PrebuildQueue m_queue; + wxTimer m_timer; + std::function m_input_idle_ms; + bool m_in_slice{ false }; +}; + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Lazy.cpp b/src/slic3r/GUI/Lazy.cpp new file mode 100644 index 0000000000..2a1a74510a --- /dev/null +++ b/src/slic3r/GUI/Lazy.cpp @@ -0,0 +1,27 @@ +#include "Lazy.hpp" + +#include +#include +#include + +namespace Slic3r { namespace GUI { + +LazyBase::OnDemandBuild::OnDemandBuild(const LazyBase& lazy) : m_lazy(lazy), m_started(std::chrono::steady_clock::now()) +{ + // The unit tests have no app. + if (wxTheApp != nullptr) + m_busy = std::make_unique(); +} + +LazyBase::OnDemandBuild::~OnDemandBuild() +{ + BOOST_LOG_TRIVIAL(info) << "Lazy::ensure: built " << m_lazy.name() << " on demand, " << m_units << " unit(s) in " + << std::chrono::duration_cast(std::chrono::steady_clock::now() - m_started).count() << " ms"; +} + +void LazyBase::log_null_factory(const std::string& name) +{ + BOOST_LOG_TRIVIAL(error) << "Lazy::build_step: the factory for " << name << " returned null"; +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Lazy.hpp b/src/slic3r/GUI/Lazy.hpp new file mode 100644 index 0000000000..33e092d887 --- /dev/null +++ b/src/slic3r/GUI/Lazy.hpp @@ -0,0 +1,198 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "StagedBuild.hpp" + +class wxBusyCursor; + +// Deferred construction of one object. Lazy holds the factory and builds the object on +// demand or, unit by unit, from an IdleScheduler; LazyBase is what the scheduler sees of +// it; LazyInstance gives a type with one such object app-wide static access to it. +// docs/HLSD/deferred-page-construction.md covers the design. + +namespace Slic3r { namespace GUI { + +template class LazyInstance; + +// A prebuild task: what PrebuildQueue sees of a Lazy. A type with its own unit sequence +// implements it directly. +class LazyBase +{ +public: + virtual ~LazyBase() = default; + + // Labels the object in logs. + virtual const std::string& name() const = 0; + virtual bool built() const = 0; + // Whether the idle prebuild has work here. + virtual bool pending() const { return !built(); } + // Runs one unit and returns true while more remain. + virtual bool build_step() = 0; + // Position in the idle queue: lower builds first, negative is never prebuilt. + virtual int prebuild_order() const = 0; + +protected: + // Busy cursor around a build the user is waiting on, and a log line after it. + class OnDemandBuild + { + public: + explicit OnDemandBuild(const LazyBase& lazy); + ~OnDemandBuild(); + void unit() { ++m_units; } + + private: + const LazyBase& m_lazy; + std::unique_ptr m_busy; + std::chrono::steady_clock::time_point m_started; + int m_units{ 0 }; + }; + + static void log_null_factory(const std::string& name); +}; + +// Holds an object a factory makes on the first build_step() or ensure(), followed by one +// StagedBuild step per unit if the type has them, and keeps callbacks until the object is +// complete. The object's parent owns it, not the holder. A LazyInstance type is registered +// for its statics; any other type is reached only through the holder. +template +class Lazy : public LazyBase +{ +public: + using Factory = std::function; + + Lazy(std::string name, int order, Factory make) : m_name(std::move(name)), m_order(order), m_make(std::move(make)) + { + if constexpr (registered()) + LazyInstance::s_lazy = this; + } + ~Lazy() override + { + if constexpr (registered()) + if (LazyInstance::s_lazy == this) + LazyInstance::s_lazy = nullptr; + } + Lazy(const Lazy&) = delete; + Lazy& operator=(const Lazy&) = delete; + + // Null until completely built. + T* get() const { return built() ? m_object : nullptr; } + + // Builds whatever is left now and returns the object, null if the factory returned null + // or a nested call finds the object mid-build. + T* ensure() + { + if (!built() && !m_building) { + OnDemandBuild build(*this); + do + build.unit(); + while (build_step()); + } + return get(); + } + + // Runs fn on the object now if it is built, otherwise once it is. + void when_built(std::function fn) + { + if (built()) + fn(*m_object); + else + m_deferred.push_back(std::move(fn)); + } + + const std::string& name() const override { return m_name; } + // Read by a worker thread through the statics; the last write in build_step() releases it. + bool built() const override { return m_complete.load(std::memory_order_acquire); } + bool pending() const override { return !built() && !m_failed; } + int prebuild_order() const override { return m_order; } + + // The factory is the first unit, then one StagedBuild step each. A unit that pumps the + // event loop cannot re-enter; a nested call does nothing. + bool build_step() override + { + if (built() || m_building || m_failed) + return false; + m_building = true; + try { + if (m_object == nullptr) + m_object = m_make(); + else + step(); + } catch (...) { + m_building = false; + throw; + } + m_building = false; + if (m_object == nullptr) { + m_failed = true; + log_null_factory(m_name); + return false; + } + if (steps_remain()) + return true; + m_complete.store(true, std::memory_order_release); + for (auto& fn : m_deferred) + fn(*m_object); + m_deferred.clear(); + return false; + } + +private: + static constexpr bool registered() { return std::is_base_of_v, T>; } + static constexpr bool staged() { return std::is_base_of_v; } + + bool steps_remain() const + { + if constexpr (staged()) + return !m_object->built(); + else + return false; + } + void step() + { + if constexpr (staged()) + m_object->build_step(); + } + + std::string m_name; + int m_order; + Factory m_make; + T* m_object{ nullptr }; + std::atomic m_complete{ false }; + bool m_building{ false }; + bool m_failed{ false }; + std::vector> m_deferred; +}; + +// Mixin for a type with one lazily built instance in the app. The statics reach that +// instance through its Lazy holder (a recreated MainFrame's holder replaces the old +// frame's). +template +class LazyInstance +{ +public: + // Null until completely built. + static Self* if_built() { return s_lazy ? s_lazy->get() : nullptr; } + // Builds the object if needed; null while no holder exists or the holder has no + // object. + static Self* ensure() { return s_lazy ? s_lazy->ensure() : nullptr; } + // Runs fn on the object now if it is built, otherwise once it is. + static void when_built(std::function fn) + { + if (s_lazy) + s_lazy->when_built(std::move(fn)); + } + +private: + friend class Lazy; + inline static Lazy* s_lazy{ nullptr }; +}; + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/LazyPage.cpp b/src/slic3r/GUI/LazyPage.cpp new file mode 100644 index 0000000000..d14947bd80 --- /dev/null +++ b/src/slic3r/GUI/LazyPage.cpp @@ -0,0 +1,14 @@ +#include "LazyPage.hpp" + +#include "GUI_App.hpp" + +namespace Slic3r { namespace GUI { + +void apply_dark_ui_to_lazy_panel(wxWindow* panel) +{ +#ifdef _MSW_DARK_MODE + wxGetApp().UpdateDarkUIWin(panel); +#endif +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/LazyPage.hpp b/src/slic3r/GUI/LazyPage.hpp new file mode 100644 index 0000000000..fc85f69285 --- /dev/null +++ b/src/slic3r/GUI/LazyPage.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +#include "Lazy.hpp" + +namespace Slic3r { namespace GUI { + +// Applies the app's dark-mode pass to a panel built after the frame's own pass ran. +void apply_dark_ui_to_lazy_panel(wxWindow* panel); + +// A page whose panel is built the first time the page is shown, or earlier by an +// IdleScheduler; nothing builds while the frame is still hidden. The Lazy side holds the +// panel and, for a LazyInstance panel type, registers it for the type's statics. +template +class LazyPage : public wxPanel, public Lazy +{ +public: + using Factory = std::function; + + LazyPage(wxWindow* parent, std::string name, int order, Factory make = [](wxWindow* parent) { return new Panel(parent); }) + : wxPanel(parent), Lazy(std::move(name), order, [this, make = std::move(make)] { + Panel* panel = make(this); + GetSizer()->Add(panel, 1, wxEXPAND); + // Hidden while its page is, as an inserted page would be. + if (!IsShown()) + panel->Hide(); + return panel; + }) + { + SetSizer(new wxBoxSizer(wxVERTICAL)); + // Shown by the book when its tab is selected. + Hide(); + this->when_built([this](Panel& panel) { + apply_dark_ui_to_lazy_panel(&panel); + Layout(); + }); + } + + // The parent book currently lists this page. + bool in_book() const + { + auto* book = dynamic_cast(GetParent()); + return book != nullptr && book->FindPage(this) != wxNOT_FOUND; + } + + // Pending only while the tab is in the book. + bool pending() const override { return in_book() && Lazy::pending(); } + + // Forwarded so the panel's own Show() override stays its activation hook; wx calls this + // virtual from the book's ShowWithEffect() only for wxSHOW_EFFECT_NONE, the default. + bool Show(bool show = true) override + { + const bool changed = wxPanel::Show(show); + if (show) { + // The book shows its first page as it is inserted, before startup has chosen the + // start page, so a hidden frame builds nothing; MainFrame::Show() completes it. + if (this->built() || wxGetTopLevelParent(this)->IsShown()) { + if (Panel* panel = this->ensure()) + panel->Show(true); + // The sizer skipped the panel while the book kept it hidden. + Layout(); + } + } else if (Panel* panel = this->get()) { + panel->Show(false); + } + return changed; + } +}; + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ca0ef95a76..ec4428a32a 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -317,7 +317,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ // BBS , m_recent_projects(18) , m_settings_dialog(this) - , diff_dialog(this) + , m_idle([] { return wxGetApp().input_idle_ms(); }) + , m_diff_dialog("compare_presets", 100, [this] { return make_diff_dialog(); }) { #ifdef __WXOSX__ set_miniaturizable(GetHandle()); @@ -737,9 +738,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ wxGetApp().persist_window_geometry(this, true); wxGetApp().persist_window_geometry(&m_settings_dialog, true); - // bind events from DiffDlg - - bind_diff_dialog(); } bool MainFrame::handle_global_shortcut(const KeyChord& chord) @@ -832,8 +830,10 @@ bool MainFrame::handle_global_shortcut(const KeyChord& chord) return true; } -void MainFrame::bind_diff_dialog() +DiffPresetDialog* MainFrame::make_diff_dialog() { + auto* dialog = new DiffPresetDialog(this); + auto get_tab = [](Preset::Type type) { Tab* null_tab = nullptr; for (Tab* tab : wxGetApp().tabs_list) @@ -842,23 +842,24 @@ void MainFrame::bind_diff_dialog() return null_tab; }; - auto transfer = [this, get_tab](Preset::Type type) { - get_tab(type)->transfer_options(diff_dialog.get_left_preset_name(type), - diff_dialog.get_right_preset_name(type), - diff_dialog.get_selected_options(type)); + auto transfer = [dialog, get_tab](Preset::Type type) { + get_tab(type)->transfer_options(dialog->get_left_preset_name(type), + dialog->get_right_preset_name(type), + dialog->get_selected_options(type)); }; - auto process_options = [this](std::function process) { - const Preset::Type diff_dlg_type = diff_dialog.view_type(); + auto process_options = [dialog](std::function process) { + const Preset::Type diff_dlg_type = dialog->view_type(); if (diff_dlg_type == Preset::TYPE_INVALID) { - for (const Preset::Type& type : diff_dialog.types_list() ) + for (const Preset::Type& type : dialog->types_list() ) process(type); } else process(diff_dlg_type); }; - diff_dialog.Bind(EVT_DIFF_DIALOG_TRANSFER, [process_options, transfer](SimpleEvent&) { process_options(transfer); }); + dialog->Bind(EVT_DIFF_DIALOG_TRANSFER, [process_options, transfer](SimpleEvent&) { process_options(transfer); }); + return dialog; } @@ -1186,8 +1187,9 @@ void MainFrame::update_edge_panels() void MainFrame::shutdown() { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter"; - if (m_project != nullptr) - m_project->shutdown(); + m_idle.stop(); + if (ProjectPanel* project = ProjectPanel::if_built()) + project->shutdown(); m_plugin_pages.shutdown(); if (m_plater != nullptr) m_plater->remove_dock_panes(); @@ -1314,19 +1316,6 @@ void MainFrame::show_option(bool show) } } -#ifdef SLIC3R_CAD -DesignPanel* MainFrame::ensure_design_panel() -{ - if (m_design_panel == nullptr && m_design_page != nullptr) { - wxBusyCursor busy; - m_design_panel = new DesignPanel(m_design_page); - m_design_page->GetSizer()->Add(m_design_panel, 1, wxEXPAND); - m_design_page->Layout(); - } - return m_design_panel; -} -#endif - void MainFrame::init_tabpanel() { // wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on // Windows 10 with multiple high resolution displays connected. @@ -1369,23 +1358,20 @@ void MainFrame::init_tabpanel() { // m_param_panel->OnActivate(); #ifdef SLIC3R_CAD else if (m_design_page != nullptr && panel == m_design_page) { - // Built on first activation, never at startup: the panel creates several hundred - // controls and its own GL canvas, which a user who does not open the tab should - // not pay for. - ensure_design_panel(); // Re-sync the Design bed to the active printer: the panel is built before the // printer profile is fully applied, so its bed must refresh on activation or the // grid (true bed) spills past the stale default bed quad. - m_design_panel->on_tab_shown(); + DesignPanel::ensure()->on_tab_shown(); } #endif - else if (panel == m_monitor) { + else if (panel == m_monitor_page) { //monitor } #ifdef SLIC3R_CAD // Any page that is not Design takes the Design status line down with it — see // DesignPanel::on_tab_hidden for why the popup does not follow the page on its own. - if (m_design_panel != nullptr && panel != m_design_page) m_design_panel->on_tab_hidden(); + if (DesignPanel* design = DesignPanel::if_built(); design != nullptr && panel != m_design_page) + design->on_tab_hidden(); #endif #ifndef __APPLE__ if (m_last_selected_tab == TAB_ID_PREPARE) { @@ -1401,13 +1387,14 @@ void MainFrame::init_tabpanel() { }); if (wxGetApp().is_editor()) { - m_webview = new WebViewPanel(m_tabpanel); + m_home_page = new LazyPage(m_tabpanel, TAB_ID_HOME, 10); + m_lazy_pages.push_back(m_home_page); Bind(EVT_LOAD_URL, [this](wxCommandEvent &evt) { wxString url = evt.GetString(); select_tab(TAB_ID_HOME); - m_webview->load_url(url); + WebViewPanel::ensure()->load_url(url); }); - m_tabpanel->AddPage(TAB_ID_HOME, m_webview, "", "tab_home_active"); + m_tabpanel->AddPage(TAB_ID_HOME, m_home_page, "", "tab_home_active"); m_param_panel = new ParamsPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); } @@ -1418,15 +1405,13 @@ void MainFrame::init_tabpanel() { wxGetApp().plater_ = m_plater; #ifdef SLIC3R_CAD - // Stand-in page for the Design tab. The real DesignPanel is built into it the first time - // the tab is selected (see the page-changed handler above), so nothing it constructs sits - // on the startup path. The experimental feature is off by default, and when it is off the - // page is never created, so the tab does not appear at all (the preference takes effect on - // the next start, like the other feature toggles). + // The experimental feature is off by default, and when it is off the page is never + // created, so the tab does not appear at all (the preference takes effect on the next + // start, like the other feature toggles). if (wxGetApp().is_enable_cad_feature()) { - m_design_page = new wxPanel(this); - m_design_page->SetSizer(new wxBoxSizer(wxVERTICAL)); - m_design_page->Hide(); + // Experimental and heavy enough that building it unasked would cost more than it saves. + m_design_page = new LazyPage(this, TAB_ID_DESIGN, -1); + m_lazy_pages.push_back(m_design_page); start_mcp_control_if_enabled(); // opens the MCP socket iff ORCA_CAD_MCP is set } #endif @@ -1434,33 +1419,41 @@ void MainFrame::init_tabpanel() { create_preset_tabs(); //BBS add pages - m_monitor = new MonitorPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_monitor->SetBackgroundColour(*wxWHITE); - m_tabpanel->AddPage(TAB_ID_MONITOR, m_monitor, _L("Device"), "tab_monitor_active"); + m_monitor_page = new LazyPage(m_tabpanel, TAB_ID_MONITOR, 20); + m_lazy_pages.push_back(m_monitor_page); + m_tabpanel->AddPage(TAB_ID_MONITOR, m_monitor_page, _L("Device"), "tab_monitor_active"); - m_printer_view = new PrinterWebView(m_tabpanel); + m_printer_view_page = new LazyPage(m_tabpanel, TAB_ID_MONITOR_WEB, 50, [this](wxWindow* parent) { + auto* view = new PrinterWebView(parent); + if (!m_printer_url.empty()) + view->load_url(m_printer_url, m_printer_api_key); + return view; + }); + m_lazy_pages.push_back(m_printer_view_page); Bind(EVT_LOAD_PRINTER_URL, [this](LoadPrinterViewEvent &evt) { - wxString url = evt.GetString(); - wxString key = evt.GetAPIkey(); //select_tab(MainFrame::tpMonitor); - m_printer_view->load_url(url, key); + m_printer_url = evt.GetString(); + m_printer_api_key = evt.GetAPIkey(); + if (PrinterWebView* view = PrinterWebView::if_built()) + view->load_url(m_printer_url, m_printer_api_key); }); - m_printer_view->Hide(); + m_multi_machine_page = new LazyPage(m_tabpanel, TAB_ID_MULTI_DEVICE, 40); + m_lazy_pages.push_back(m_multi_machine_page); if (wxGetApp().is_enable_multi_machine()) { - m_multi_machine = new MultiMachinePage(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_multi_machine->SetBackgroundColour(*wxWHITE); // TODO: change the bitmap - m_tabpanel->AddPage(TAB_ID_MULTI_DEVICE, m_multi_machine, _L("Multi-device"), "tab_multi_active"); + m_tabpanel->AddPage(TAB_ID_MULTI_DEVICE, m_multi_machine_page, _L("Multi-device"), "tab_multi_active"); } - m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_project->SetBackgroundColour(*wxWHITE); - m_tabpanel->AddPage(TAB_ID_PROJECT, m_project, _L("Project"), "tab_auxiliary_active"); + m_project_page = new LazyPage(m_tabpanel, TAB_ID_PROJECT, 60); + m_lazy_pages.push_back(m_project_page); + m_tabpanel->AddPage(TAB_ID_PROJECT, m_project_page, _L("Project"), "tab_auxiliary_active"); - m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_calibration->SetBackgroundColour(*wxWHITE); - m_tabpanel->AddPage(TAB_ID_CALIBRATION, m_calibration, _L("Calibration"), "tab_calibration_active"); + // show_device() removes this tab for printers without the Bambu device tab, and the page + // then never builds its panel. + m_calibration_page = new LazyPage(m_tabpanel, TAB_ID_CALIBRATION, 30); + m_lazy_pages.push_back(m_calibration_page); + m_tabpanel->AddPage(TAB_ID_CALIBRATION, m_calibration_page, _L("Calibration"), "tab_calibration_active"); // Plugin pages are appended after the built-in tabs; their ids are namespaced // (plugin..) so they can't collide with the built-in TAB_ID_* constants. @@ -1495,67 +1488,44 @@ void MainFrame::show_device(bool should_use_native) { // Remove the extra page before switching to any layout that shouldn't have it. if (!want_web_device_tab) { if ((idx = m_tabpanel->FindPageByName(TAB_ID_MONITOR_WEB)) != wxNOT_FOUND) { - m_printer_view->Show(false); + m_printer_view_page->Show(false); m_tabpanel->RemovePage(idx); } } if (use_printer_agents) { - if (!m_monitor) { - m_monitor = new MonitorPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_monitor->SetBackgroundColour(*wxWHITE); - } - - if (m_tabpanel->FindPage(m_monitor) == wxNOT_FOUND) { - if ((idx = m_tabpanel->FindPage(m_printer_view)) != wxNOT_FOUND) { - m_printer_view->Show(false); + if (!m_monitor_page->in_book()) { + if ((idx = m_tabpanel->FindPage(m_printer_view_page)) != wxNOT_FOUND) { + m_printer_view_page->Show(false); m_tabpanel->RemovePage(idx); } - m_monitor->Show(false); - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_monitor, + m_monitor_page->Show(false); + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_monitor_page, _L("Device"), "tab_monitor_active"); } - if (m_printer_view == nullptr) { - m_printer_view = new PrinterWebView(m_tabpanel); - Bind(EVT_LOAD_PRINTER_URL, [this](LoadPrinterViewEvent& evt) { - wxString url = evt.GetString(); - wxString key = evt.GetAPIkey(); - // select_tab(MainFrame::tpMonitor); - m_printer_view->load_url(url, key); - }); - } - if (wxGetApp().is_enable_multi_machine()) { - if (!m_multi_machine) { - m_multi_machine = new MultiMachinePage(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_multi_machine->SetBackgroundColour(*wxWHITE); - } // TODO: change the bitmap - if (m_tabpanel->FindPage(m_multi_machine) == wxNOT_FOUND) { - m_multi_machine->Show(false); + if (!m_multi_machine_page->in_book()) { + m_multi_machine_page->Show(false); // Past the web Device tab when it is already there, so enabling multi-machine // later can't wedge this page between the two Device tabs. m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_MONITOR_WEB, TAB_ID_MONITOR}), - TAB_ID_MULTI_DEVICE, m_multi_machine, _L("Multi-device"), "tab_multi_active"); + TAB_ID_MULTI_DEVICE, m_multi_machine_page, _L("Multi-device"), "tab_multi_active"); } } - if (!m_calibration) { - m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_calibration->SetBackgroundColour(*wxWHITE); - } - if (m_tabpanel->FindPage(m_calibration) == wxNOT_FOUND) { - m_calibration->Show(false); - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PROJECT}), TAB_ID_CALIBRATION, m_calibration, + if (!m_calibration_page->in_book()) { + m_calibration_page->Show(false); + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PROJECT}), TAB_ID_CALIBRATION, m_calibration_page, _L("Calibration"), "tab_calibration_active"); } if (want_web_device_tab) { - if ((idx = m_tabpanel->FindPage(m_printer_view)) == wxNOT_FOUND) { - m_printer_view->Show(false); + if ((idx = m_tabpanel->FindPage(m_printer_view_page)) == wxNOT_FOUND) { + m_printer_view_page->Show(false); // Immediately right of the native Device tab, not at the end of the tab bar. m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_MONITOR}), TAB_ID_MONITOR_WEB, - m_printer_view, _L("Device (Web)"), "tab_monitor_active"); + m_printer_view_page, _L("Device (Web)"), "tab_monitor_active"); } else { m_tabpanel->SetPageText(idx, _L("Device (Web)")); } @@ -1567,48 +1537,37 @@ void MainFrame::show_device(bool should_use_native) { fit_tab_labels(); // ORCA on printer change m_plugin_pages.relayout(); // re-sync plugin tabs against the native tabs just mutated above - + if (m_prebuild_started) + m_idle.start(); return; } if (should_use_native) { - if (m_tabpanel->FindPage(m_monitor) != wxNOT_FOUND) { + if (m_monitor_page->in_book()) { fit_tab_labels(); // ORCA on printer change - same button layout return; } // Remove printer view - if ((idx = m_tabpanel->FindPage(m_printer_view)) != wxNOT_FOUND) { - m_printer_view->Show(false); + if ((idx = m_tabpanel->FindPage(m_printer_view_page)) != wxNOT_FOUND) { + m_printer_view_page->Show(false); m_tabpanel->RemovePage(idx); } - // Create/insert monitor page - if (!m_monitor) { - m_monitor = new MonitorPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_monitor->SetBackgroundColour(*wxWHITE); - } - m_monitor->Show(false); - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_monitor, + // Insert monitor page + m_monitor_page->Show(false); + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_monitor_page, _L("Device"), "tab_monitor_active"); if (wxGetApp().is_enable_multi_machine()) { - if (!m_multi_machine) { - m_multi_machine = new MultiMachinePage(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_multi_machine->SetBackgroundColour(*wxWHITE); - } // TODO: change the bitmap - m_multi_machine->Show(false); - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_MONITOR}), TAB_ID_MULTI_DEVICE, m_multi_machine, + m_multi_machine_page->Show(false); + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_MONITOR}), TAB_ID_MULTI_DEVICE, m_multi_machine_page, _L("Multi-device"), "tab_multi_active"); } - if (!m_calibration) { - m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_calibration->SetBackgroundColour(*wxWHITE); - } - m_calibration->Show(false); + m_calibration_page->Show(false); // Last of the built-in tabs, but plugin tabs already sit past it — anchor rather than // append, so its position doesn't depend on the relayout() below running afterwards. - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PROJECT}), TAB_ID_CALIBRATION, m_calibration, + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PROJECT}), TAB_ID_CALIBRATION, m_calibration_page, _L("Calibration"), "tab_calibration_active"); #ifdef _MSW_DARK_MODE @@ -1616,37 +1575,30 @@ void MainFrame::show_device(bool should_use_native) { #endif // _MSW_DARK_MODE } else { - if (m_tabpanel->FindPage(m_printer_view) != wxNOT_FOUND) { + if (m_printer_view_page->in_book()) { fit_tab_labels(); // ORCA on printer change - same button layout return; } - if ((idx = m_tabpanel->FindPage(m_calibration)) != wxNOT_FOUND) { - m_calibration->Show(false); + if ((idx = m_tabpanel->FindPage(m_calibration_page)) != wxNOT_FOUND) { + m_calibration_page->Show(false); m_tabpanel->RemovePage(idx); } - if ((idx = m_tabpanel->FindPage(m_multi_machine)) != wxNOT_FOUND) { - m_multi_machine->Show(false); + if ((idx = m_tabpanel->FindPage(m_multi_machine_page)) != wxNOT_FOUND) { + m_multi_machine_page->Show(false); m_tabpanel->RemovePage(idx); } - if ((idx = m_tabpanel->FindPage(m_monitor)) != wxNOT_FOUND) { - m_monitor->Show(false); + if ((idx = m_tabpanel->FindPage(m_monitor_page)) != wxNOT_FOUND) { + m_monitor_page->Show(false); m_tabpanel->RemovePage(idx); } - if (m_printer_view == nullptr) { - m_printer_view = new PrinterWebView(m_tabpanel); - Bind(EVT_LOAD_PRINTER_URL, [this](LoadPrinterViewEvent& evt) { - wxString url = evt.GetString(); - wxString key = evt.GetAPIkey(); - // select_tab(MainFrame::tpMonitor); - m_printer_view->load_url(url, key); - }); - } - m_printer_view->Show(false); - m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_printer_view, + m_printer_view_page->Show(false); + m_tabpanel->InsertPage(m_tabpanel->PositionAfter({TAB_ID_PREVIEW}), TAB_ID_MONITOR, m_printer_view_page, _L("Device"), "tab_monitor_active"); } fit_tab_labels(); // ORCA on printer change m_plugin_pages.relayout(); // re-sync plugin tabs against the native tabs just mutated above + if (m_prebuild_started) + m_idle.start(); } bool MainFrame::is_prepare_or_preview_tab() const @@ -2692,13 +2644,11 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect) //BBS GUI refactor: remove unused layout new/dlg //if (m_layout != ESettingsLayout::Dlg) // Do not update tabs if the Settings are in the separated dialog m_param_panel->msw_rescale(); - m_project->msw_rescale(); - if(m_monitor) - m_monitor->msw_rescale(); - if(m_multi_machine) - m_multi_machine->msw_rescale(); - if(m_calibration) - m_calibration->msw_rescale(); + // A panel mid-build gets the pass once it is complete. + ProjectPanel::when_built([](ProjectPanel& project) { project.msw_rescale(); }); + MonitorPanel::when_built([](MonitorPanel& monitor) { monitor.msw_rescale(); }); + MultiMachinePage::when_built([](MultiMachinePage& multi_machine) { multi_machine.msw_rescale(); }); + CalibrationPanel::when_built([](CalibrationPanel& calibration) { calibration.msw_rescale(); }); // BBS #if 0 @@ -2752,7 +2702,8 @@ void MainFrame::on_sys_color_changed() #endif #endif - diff_dialog.on_sys_color_changed(); + if (DiffPresetDialog* dialog = DiffPresetDialog::if_built()) + dialog->on_sys_color_changed(); // BBS m_tabpanel->Rescale(); @@ -2760,10 +2711,8 @@ void MainFrame::on_sys_color_changed() // update Plater wxGetApp().plater()->sys_color_changed(); - if(m_monitor) - m_monitor->on_sys_color_changed(); - if(m_calibration) - m_calibration->on_sys_color_changed(); + MonitorPanel::when_built([](MonitorPanel& monitor) { monitor.on_sys_color_changed(); }); + CalibrationPanel::when_built([](CalibrationPanel& calibration) { calibration.on_sys_color_changed(); }); // update Tabs for (auto tab : wxGetApp().tabs_list) tab->sys_color_changed(); @@ -3696,7 +3645,8 @@ void MainFrame::set_max_recent_count(int max) } wxGetApp().app_config->set_recent_projects(recent_projects); wxGetApp().app_config->save(); - m_webview->SendRecentList(-1); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendRecentList(-1); } } @@ -4040,23 +3990,56 @@ void MainFrame::select_tab(wxPanel* panel) select_tab(page_name); } +// Selects the Prepare page without the page-changed event, so the GL canvas is on screen +// and nothing else is built for the pass. +void MainFrame::select_prepare_for_gl_init() +{ + m_tabpanel->ChangeSelection(m_tabpanel->FindPageByName(TAB_ID_PREPARE)); +} + +// The book shows its first page as it is inserted, while the frame is hidden and nothing +// may build; the first show completes that page. +bool MainFrame::Show(bool show) +{ + const bool changed = DPIFrame::Show(show); + if (show && changed && m_tabpanel != nullptr) + if (wxWindow* page = m_tabpanel->GetCurrentPage()) + page->Show(true); + return changed; +} + +// A page out of the book stays registered and is passed over; a negative order is never +// registered. +void MainFrame::prebuild_pages_when_idle() +{ + m_idle.clear(); + if (m_param_panel) + m_idle.add(m_param_panel->settings_page_prebuild()); + for (LazyBase* page : m_lazy_pages) + if (page->prebuild_order() >= 0) + m_idle.add(*page); + m_idle.add(m_diff_dialog); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": prebuild queue: " << m_idle.names(); + m_idle.start(); + m_prebuild_started = true; +} + //BBS void MainFrame::jump_to_monitor(std::string dev_id) { - if(!m_monitor) - return; m_tabpanel->SelectPageByName(TAB_ID_MONITOR); if (!dev_id.empty()) { - ((MonitorPanel*)m_monitor)->select_machine(dev_id); + MonitorPanel::ensure()->select_machine(dev_id); } } void MainFrame::jump_to_multipage() { - if(!m_multi_machine) + if (!m_multi_machine_page->in_book()) return; m_tabpanel->SelectPageByName(TAB_ID_MULTI_DEVICE); - ((MultiMachinePage*)m_multi_machine)->jump_to_send_page(); + if (MultiMachinePage* page = m_multi_machine_page->ensure()) + page->jump_to_send_page(); } @@ -4105,8 +4088,8 @@ void MainFrame::request_select_tab(const wxString& id) } int MainFrame::get_calibration_curr_tab() { - if (m_calibration) - return m_calibration->get_tabpanel()->GetSelection(); + if (CalibrationPanel* calibration = CalibrationPanel::if_built()) + return calibration->get_tabpanel()->GetSelection(); return -1; } @@ -4215,7 +4198,8 @@ void MainFrame::add_to_recent_projects(const wxString& filename) recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i))); } wxGetApp().app_config->set_recent_projects(recent_projects); - m_webview->SendRecentList(0); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendRecentList(0); } } @@ -4331,7 +4315,8 @@ void MainFrame::open_recent_project(size_t file_id, wxString const & filename) recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i))); } wxGetApp().app_config->set_recent_projects(recent_projects); - m_webview->SendRecentList(-1); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendRecentList(-1); } } } @@ -4354,7 +4339,8 @@ void MainFrame::remove_recent_project(size_t file_id, wxString const &filename) recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i))); } wxGetApp().app_config->set_recent_projects(recent_projects); - m_webview->SendRecentList(-1); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendRecentList(-1); } void MainFrame::load_url(wxString url) @@ -4408,14 +4394,14 @@ bool MainFrame::is_printer_view() const { return m_tabpanel->GetSelectedPageName void MainFrame::refresh_plugin_tips() { - if (m_webview != nullptr) - m_webview->ShowNetpluginTip(); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->ShowNetpluginTip(); } void MainFrame::RunScript(wxString js) { - if (m_webview != nullptr) - m_webview->RunScript(js); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->RunScript(js); } void MainFrame::technology_changed() @@ -4524,7 +4510,8 @@ void MainFrame::update_side_preset_ui() //take off multi machine - if(m_multi_machine){m_multi_machine->clear_page();} + if (MultiMachinePage* multi_machine = MultiMachinePage::if_built()) + multi_machine->clear_page(); } void MainFrame::on_select_default_preset(SimpleEvent& evt) diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 66f3b31263..f580de57e0 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -26,6 +26,8 @@ #include "Widgets/SideButton.hpp" #include "Widgets/SideMenuPopup.hpp" #include "FilamentGroupPopup.hpp" +#include "LazyPage.hpp" +#include "IdleScheduler.hpp" #include @@ -136,6 +138,13 @@ class MainFrame : public DPIFrame #endif bool m_loaded {false}; wxTimer* m_reset_title_text_colour_timer{ nullptr }; + IdleScheduler m_idle; + bool m_prebuild_started{ false }; + // Every LazyPage, in and out of the book; prebuild_pages_when_idle() registers them. + std::vector m_lazy_pages; + // The latest EVT_LOAD_PRINTER_URL, applied when the web Device view is built. + wxString m_printer_url; + wxString m_printer_api_key; wxString m_qs_last_input_file = wxEmptyString; wxString m_qs_last_output_file = wxEmptyString; @@ -180,7 +189,7 @@ class MainFrame : public DPIFrame bool can_delete() const; bool can_delete_all() const; bool can_reslice() const; - void bind_diff_dialog(); + DiffPresetDialog* make_diff_dialog(); // BBS wxBoxSizer* create_side_tools(); @@ -377,6 +386,12 @@ public: void select_tab(wxPanel* panel); void select_tab(const wxString& id = wxString()); void request_select_tab(const wxString& id); + // post_init() needs the plater's canvas on screen to initialize OpenGL; this pass does not + // build the settings page. + void select_prepare_for_gl_init(); + // Builds the lazy tab pages while the user is idle; post_init() calls it once. + void prebuild_pages_when_idle(); + bool Show(bool show = true) override; int get_calibration_curr_tab(); void select_view(const std::string& direction); void update_shortcut_labels(); @@ -435,27 +450,21 @@ public: BBLTopbar* m_topbar{ nullptr }; PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; } Plater* m_plater { nullptr }; + // Lazy pages, created once and kept for the frame's life; their panels are reached + // through LazyInstance's statics, and show_device() only moves pages in and out of the book. #ifdef SLIC3R_CAD - // The tab page is the placeholder; m_design_panel stays null until the tab is first - // selected, so everything the Design panel builds stays off the startup path. - wxPanel* m_design_page { nullptr }; - DesignPanel* m_design_panel { nullptr }; - // Builds the Design panel if it does not exist yet and returns it (null only before the - // placeholder page itself exists). Main thread only -- it creates wx controls. Both the - // tab activation and the MCP socket go through this: the socket is driven headlessly, - // with nobody to click the tab, and without this every verb would answer "not ready". - DesignPanel* ensure_design_panel(); + LazyPage* m_design_page { nullptr }; #endif //BBS: GUI refactor - MonitorPanel* m_monitor{ nullptr }; + LazyPage* m_monitor_page{ nullptr }; //AuxiliaryPanel* m_auxiliary{ nullptr }; - MultiMachinePage* m_multi_machine{ nullptr }; - ProjectPanel* m_project{ nullptr }; + LazyPage* m_multi_machine_page{ nullptr }; + LazyPage* m_project_page{ nullptr }; - CalibrationPanel* m_calibration{ nullptr }; - WebViewPanel* m_webview { nullptr }; - PrinterWebView* m_printer_view{nullptr}; + LazyPage* m_calibration_page{ nullptr }; + LazyPage* m_home_page { nullptr }; + LazyPage* m_printer_view_page{nullptr}; PluginPages m_plugin_pages; wxLogWindow* m_log_window { nullptr }; // BBS @@ -466,7 +475,8 @@ public: ParamsDialog* m_param_dialog{ nullptr }; //BBS SettingsDialog m_settings_dialog; - DiffPresetDialog diff_dialog; + // The Compare presets dialog, built on first use or at idle through its holder. + Lazy m_diff_dialog; wxWindow* m_plater_page{ nullptr }; PrintHostQueueDialog* m_printhost_queue_dlg; diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index 1a6d969988..7352ee3dd7 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -103,6 +103,7 @@ MonitorPanel::MonitorPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, : wxPanel(parent, id, pos, size, style), m_select_machine(SelectMachinePopup(this)) { + SetBackgroundColour(*wxWHITE); #ifdef __WINDOWS__ SetDoubleBuffered(true); #endif //__WINDOWS__ @@ -180,31 +181,36 @@ void MonitorPanel::init_tabpanel() auto title = m_tabpanel->GetPageText(m_tabpanel->GetSelection()); m_media_file_panel->SwitchStorage(title == _L("Storage")); } - page->SetFocus(); + // The first page is selected while the panel is built off screen. + if (page->IsShownOnScreen()) + page->SetFocus(); update_all(); }, m_tabpanel->GetId()); - //m_status_add_machine_panel = new AddMachinePanel(m_tabpanel); - m_status_info_panel = new StatusPanel(m_tabpanel); + m_status_info_panel = new StatusPanel(m_tabpanel); + // Queued before the page is added, since adding it selects it and runs the handler above, + // where built() must already be false. + add_build_steps_of(*m_status_info_panel); m_tabpanel->AddPage(m_status_info_panel, _L("Status"), true); + add_build_step([this] { + m_media_file_panel = new MediaFilePanel(m_tabpanel); + m_tabpanel->AddPage(m_media_file_panel, _L("Storage"), false); + }); + add_build_step([this] { + m_upgrade_panel = new UpgradePanel(m_tabpanel); + m_tabpanel->AddPage(m_upgrade_panel, _L_CONTEXT(L_CONTEXT("Update", "Firmware"), "Firmware"), false); + }); + add_build_step([this] { + m_hms_panel = new HMSPanel(m_tabpanel); + m_tabpanel->AddPage(m_hms_panel, _L("Assistant(HMS)"), false); - m_media_file_panel = new MediaFilePanel(m_tabpanel); - m_tabpanel->AddPage(m_media_file_panel, _L("Storage"), false); - //m_tabpanel->AddPage(m_media_file_panel, _L("Internal Storage"), false); + std::string network_ver = Slic3r::NetworkAgent::get_version(); + if (!network_ver.empty()) { + m_tabpanel->SetFooterText(wxString::Format(_L("Network plug-in v%s"), network_ver)); + } - m_upgrade_panel = new UpgradePanel(m_tabpanel); - m_tabpanel->AddPage(m_upgrade_panel, _L_CONTEXT(L_CONTEXT("Update", "Firmware"), "Firmware"), false); - - m_hms_panel = new HMSPanel(m_tabpanel); - m_tabpanel->AddPage(m_hms_panel, _L("Assistant(HMS)"), false); - - std::string network_ver = Slic3r::NetworkAgent::get_version(); - if (!network_ver.empty()) { - m_tabpanel->SetFooterText(wxString::Format(_L("Network plug-in v%s"), network_ver)); - } - - m_initialized = true; - show_status((int)MonitorStatus::MONITOR_NO_PRINTER); + show_status((int)MonitorStatus::MONITOR_NO_PRINTER); + }); } void MonitorPanel::set_default() @@ -288,19 +294,23 @@ void MonitorPanel::on_select_printer(wxCommandEvent& event) set_default(); update_all(); - MachineObject *obj_ = dev->get_selected_machine(); - if (obj_) { - obj_->last_cali_version = -1; - obj_->reset_pa_cali_history_result(); - obj_->reset_pa_cali_result(); - Sidebar &sidebar = GUI::wxGetApp().sidebar(); - sidebar.update_sync_status(obj_); - sidebar.set_need_auto_sync_after_connect_printer(sidebar.need_auto_sync_extruder_list_after_connect_priner(obj_)); - } + on_machine_selected(dev->get_selected_machine()); Layout(); } +void MonitorPanel::on_machine_selected(MachineObject* obj) +{ + if (obj == nullptr) + return; + obj->last_cali_version = -1; + obj->reset_pa_cali_history_result(); + obj->reset_pa_cali_result(); + Sidebar& sidebar = GUI::wxGetApp().sidebar(); + sidebar.update_sync_status(obj); + sidebar.set_need_auto_sync_after_connect_printer(sidebar.need_auto_sync_extruder_list_after_connect_priner(obj)); +} + void MonitorPanel::on_printer_clicked(wxMouseEvent &event) { auto mouse_pos = ClientToScreen(event.GetPosition()); @@ -331,7 +341,8 @@ void MonitorPanel::on_size(wxSizeEvent &event) void MonitorPanel::update_all() { - if (!m_initialized) + // Every page exists once the last build step has run. + if (!built()) return; NetworkAgent* m_agent = wxGetApp().getAgent(); @@ -412,16 +423,12 @@ void MonitorPanel::update_hms_tag() bool MonitorPanel::Show(bool show) { -#ifdef __APPLE__ - // Notebook::InsertPage() hides every page it appends, so this also runs while MainFrame is - // still constructing, before GUI_App::mainframe is assigned. Same guard as Plater::Show(). - if (wxGetApp().mainframe) - wxGetApp().mainframe->SetMinSize(wxGetApp().plater()->GetMinSize()); -#endif - NetworkAgent* m_agent = wxGetApp().getAgent(); DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (show) { +#ifdef __APPLE__ + wxGetApp().mainframe->SetMinSize(wxGetApp().plater()->GetMinSize()); +#endif start_update(); update_network_version_footer(); @@ -448,7 +455,7 @@ bool MonitorPanel::Show(bool show) void MonitorPanel::show_status(int status) { - if (!m_initialized) return; + if (!built()) return; if (last_status == status)return; if ((last_status & (int)MonitorStatus::MONITOR_CONNECTING) != 0) { NetworkAgent* agent = wxGetApp().getAgent(); diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index 9252b04559..94474f73b0 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -49,6 +49,7 @@ #include "slic3r/GUI/AmsWidgets.hpp" #include "Widgets/SideTools.hpp" #include "SelectMachinePop.hpp" +#include "Lazy.hpp" namespace Slic3r { namespace GUI { @@ -72,16 +73,16 @@ public: void msw_rescale(); }; -class MonitorPanel : public wxPanel +class MonitorPanel : public wxPanel, public StagedBuild, public LazyInstance { private: Tabbook* m_tabpanel{ nullptr }; wxSizer* m_main_sizer{ nullptr }; - StatusPanel* m_status_info_panel; - MediaFilePanel* m_media_file_panel; - UpgradePanel* m_upgrade_panel; - HMSPanel* m_hms_panel; + StatusPanel* m_status_info_panel{ nullptr }; + MediaFilePanel* m_media_file_panel{ nullptr }; + UpgradePanel* m_upgrade_panel{ nullptr }; + HMSPanel* m_hms_panel{ nullptr }; /* side tools */ SideTools* m_side_tools{nullptr}; @@ -96,7 +97,6 @@ private: wxBitmap m_arrow_img; int last_status; - bool m_initialized { false }; bool update_flag{false}; wxTimer* m_refresh_timer = nullptr; @@ -125,6 +125,8 @@ public: StatusPanel* get_status_panel() {return m_status_info_panel;}; void select_machine(std::string machine_sn); + // Resets the selected printer's calibration results and syncs the sidebar, without the Device tab. + static void on_machine_selected(MachineObject* obj); void on_timer(wxTimerEvent& event); void on_select_printer(wxCommandEvent& event); void on_printer_clicked(wxMouseEvent &event); diff --git a/src/slic3r/GUI/MultiMachineManagerPage.cpp b/src/slic3r/GUI/MultiMachineManagerPage.cpp index 792c23fb13..d5f9cbce8a 100644 --- a/src/slic3r/GUI/MultiMachineManagerPage.cpp +++ b/src/slic3r/GUI/MultiMachineManagerPage.cpp @@ -21,8 +21,9 @@ MultiMachineItem::MultiMachineItem(wxWindow* parent, MachineObject* obj) Bind(wxEVT_MOTION, &MultiMachineItem::OnMove, this); Bind(EVT_MULTI_DEVICE_VIEW, [obj](auto& e) { wxGetApp().mainframe->jump_to_monitor(obj->get_dev_id()); - if (wxGetApp().mainframe->m_monitor->get_status_panel()->get_media_play_ctrl()) { - wxGetApp().mainframe->m_monitor->get_status_panel()->get_media_play_ctrl()->jump_to_play(); + MonitorPanel* monitor = MonitorPanel::if_built(); + if (monitor && monitor->get_status_panel()->get_media_play_ctrl()) { + monitor->get_status_panel()->get_media_play_ctrl()->jump_to_play(); } }); wxGetApp().UpdateDarkUIWin(this); diff --git a/src/slic3r/GUI/MultiMachinePage.cpp b/src/slic3r/GUI/MultiMachinePage.cpp index dd67e099a0..e48e402405 100644 --- a/src/slic3r/GUI/MultiMachinePage.cpp +++ b/src/slic3r/GUI/MultiMachinePage.cpp @@ -11,6 +11,7 @@ namespace GUI { MultiMachinePage::MultiMachinePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxPanel(parent, id, pos, size, style) { + SetBackgroundColour(*wxWHITE); init_tabpanel(); m_main_sizer = new wxBoxSizer(wxHORIZONTAL); m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxLEFT, 0); diff --git a/src/slic3r/GUI/MultiMachinePage.hpp b/src/slic3r/GUI/MultiMachinePage.hpp index 724eeed2a9..14d531e8ab 100644 --- a/src/slic3r/GUI/MultiMachinePage.hpp +++ b/src/slic3r/GUI/MultiMachinePage.hpp @@ -7,6 +7,7 @@ #include "MultiTaskManagerPage.hpp" #include "MultiMachineManagerPage.hpp" #include "Tabbook.hpp" +#include "Lazy.hpp" #include "wx/button.h" @@ -19,7 +20,7 @@ namespace GUI { #define PICK_LEFT_DEV_STATUS 250 #define PICK_DEVICE_MAX 6 -class MultiMachinePage : public wxPanel +class MultiMachinePage : public wxPanel, public LazyInstance { private: wxTimer* m_refresh_timer = nullptr; diff --git a/src/slic3r/GUI/ParamsPanel.cpp b/src/slic3r/GUI/ParamsPanel.cpp index 5a49df1280..b4fd81706a 100644 --- a/src/slic3r/GUI/ParamsPanel.cpp +++ b/src/slic3r/GUI/ParamsPanel.cpp @@ -290,7 +290,7 @@ ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, c m_compare_btn = new ScalableButton(m_top_panel, wxID_ANY, "compare", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true); m_compare_btn->SetToolTip(_L("Compare presets")); - m_compare_btn->Bind(wxEVT_BUTTON, ([](wxCommandEvent e) { wxGetApp().mainframe->diff_dialog.show(); })); + m_compare_btn->Bind(wxEVT_BUTTON, ([](wxCommandEvent e) { DiffPresetDialog::ensure()->show(); })); m_setting_btn = new ScalableButton(m_top_panel, wxID_ANY, "table", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true); m_setting_btn->SetToolTip(_L("View all object's settings")); @@ -550,18 +550,36 @@ void ParamsPanel::clear_page() void ParamsPanel::OnActivate() { if (m_current_tab == NULL) - { - //the first time - BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": first time opened, set current tab to print"); - // BBS: open/close tab - //m_current_tab = m_tab_print; - set_active_tab(m_tab_print ? m_tab_print : m_tab_filament); - } + select_default_tab(); Tab* cur_tab = dynamic_cast (m_current_tab); if (cur_tab) cur_tab->OnActivate(); } +void ParamsPanel::select_default_tab() +{ + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": first time opened, set current tab to print"); + // BBS: open/close tab + //m_current_tab = m_tab_print; + set_active_tab(m_tab_print ? m_tab_print : m_tab_filament); +} + +bool ParamsPanel::SettingsPagePrebuild::built() const +{ + Tab* tab = dynamic_cast(m_panel.m_current_tab); + return tab != nullptr && !tab->page_build_pending(); +} + +bool ParamsPanel::SettingsPagePrebuild::build_step() +{ + if (m_panel.m_current_tab == nullptr) { + m_panel.select_default_tab(); + return !built(); + } + Tab* tab = dynamic_cast(m_panel.m_current_tab); + return tab != nullptr && tab->page_build_step(); +} + void ParamsPanel::OnToggled(wxCommandEvent& event) { if (m_mode_region && m_mode_region->GetId() == event.GetId()) { diff --git a/src/slic3r/GUI/ParamsPanel.hpp b/src/slic3r/GUI/ParamsPanel.hpp index 91bf3d2a7e..9f9264b480 100644 --- a/src/slic3r/GUI/ParamsPanel.hpp +++ b/src/slic3r/GUI/ParamsPanel.hpp @@ -30,6 +30,7 @@ #include "wxExtensions.hpp" #include "GUI_Utils.hpp" #include "Widgets/Button.hpp" +#include "Lazy.hpp" class ModeSwitchButton; class SwitchButton; @@ -121,6 +122,22 @@ class ParamsPanel : public wxPanel wxPanel* m_current_tab { nullptr }; + // Builds the selected page's option groups at idle; while no tab is selected yet, + // its first unit selects the default one. + class SettingsPagePrebuild : public LazyBase + { + public: + explicit SettingsPagePrebuild(ParamsPanel& panel) : m_panel(panel) {} + const std::string& name() const override { return m_name; } + bool built() const override; + bool build_step() override; + int prebuild_order() const override { return 0; } + + private: + ParamsPanel& m_panel; + std::string m_name{ "settings_page" }; + } m_settings_page_prebuild{ *this }; + bool m_has_object_config { false }; struct Highlighter @@ -149,6 +166,10 @@ class ParamsPanel : public wxPanel //clear the right page void clear_page(); void OnActivate(); + // The print tab, or the filament tab without one. + void select_default_tab(); + // The settings page's prebuild task. + LazyBase& settings_page_prebuild() { return m_settings_page_prebuild; } void set_active_tab(wxPanel*tab); bool is_active_and_shown_tab(wxPanel*tab); void update_mode(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5a10dcd2a7..5eb36f20f9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -10412,8 +10412,8 @@ void Plater::priv::reset(bool apply_presets_change, bool reload_presets) // Same reason, one level up: the Design tab keeps the editable document, not the Model, so // clearing the recipe alone leaves the tab showing the previous project's feature tree — // and its next edit syncs that tree straight back into the new project. - if (wxGetApp().mainframe != nullptr && wxGetApp().mainframe->m_design_panel != nullptr) - wxGetApp().mainframe->m_design_panel->clear_document(); + if (DesignPanel* design = DesignPanel::if_built()) + design->clear_document(); #endif assemble_view->get_canvas3d()->reset_explosion_ratio(); update(); @@ -13184,17 +13184,17 @@ void Plater::priv::on_tab_selection_changing(wxBookCtrlEvent& e) // Pointer test, not a name lookup: in printer-agents mode this page is TAB_ID_MONITOR_WEB // while the native Device tab holds TAB_ID_MONITOR, and in legacy-web mode it holds // TAB_ID_MONITOR itself. - const bool selecting_web_device_tab = main_frame->m_printer_view && - main_frame->m_tabpanel->GetPage(new_sel) == main_frame->m_printer_view; + const bool selecting_web_device_tab = main_frame->m_printer_view_page && + main_frame->m_tabpanel->GetPage(new_sel) == main_frame->m_printer_view_page; if (selecting_web_device_tab) { // Use the selected discovered machine when the preset has no host. main_frame->load_printer_url(); } else if (new_name == TAB_ID_MONITOR && wxGetApp().preset_bundle != nullptr) { auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config; wxString url = from_u8(PrintHost::get_print_host_webui(&cfg)); - if (main_frame->m_printer_view && url.empty()) { + if (PrinterWebView* view = PrinterWebView::if_built(); view != nullptr && url.empty()) { // It's missing_connection page, reload so that we can replay the gif image - main_frame->m_printer_view->reload(); + view->reload(); } } } @@ -13925,8 +13925,8 @@ void Plater::priv::unbind_canvas_event_handlers() // The Design tab's viewport is a fourth GLCanvas3D on the same shared GL context, owned by // MainFrame rather than by us — same reach as reset() uses for clear_document(). Null until // the tab has been opened once, so most sessions skip it. - if (wxGetApp().mainframe != nullptr && wxGetApp().mainframe->m_design_panel != nullptr) - wxGetApp().mainframe->m_design_panel->unbind_canvas_event_handlers(); + if (DesignPanel* design = DesignPanel::if_built()) + design->unbind_canvas_event_handlers(); #endif } @@ -13939,8 +13939,8 @@ void Plater::priv::reset_canvas_volumes() preview->get_canvas3d()->reset_volumes(); #ifdef SLIC3R_CAD - if (wxGetApp().mainframe != nullptr && wxGetApp().mainframe->m_design_panel != nullptr) - wxGetApp().mainframe->m_design_panel->reset_canvas_volumes(); + if (DesignPanel* design = DesignPanel::if_built()) + design->reset_canvas_volumes(); #endif } @@ -20002,7 +20002,7 @@ int Plater::export_config_3mf(int plate_idx, Export3mfProgressFn proFn) void Plater::send_calibration_job_finished(wxCommandEvent & evt) { p->main_frame->request_select_tab(TAB_ID_CALIBRATION); - auto calibration_panel = p->main_frame->m_calibration; + CalibrationPanel* calibration_panel = CalibrationPanel::ensure(); if (calibration_panel) { auto curr_wizard = static_cast(calibration_panel->get_tabpanel()->GetPage(evt.GetInt())); wxCommandEvent event(EVT_CALIBRATION_JOB_FINISHED); @@ -20034,8 +20034,8 @@ void Plater::print_job_finished(wxCommandEvent &evt) dev->set_selected_machine(evt.GetString().ToStdString()); p->main_frame->request_select_tab(TAB_ID_MONITOR); - //jump to monitor and select device status panel - MonitorPanel* curr_monitor = p->main_frame->m_monitor; + // Selects the status page on a built Device tab; one built by the switch starts there. + MonitorPanel* curr_monitor = MonitorPanel::if_built(); if(curr_monitor) curr_monitor->get_tabpanel()->ChangeSelection(MonitorPanel::PrinterTab::PT_STATUS); } @@ -20775,8 +20775,8 @@ void Plater::update_print_error_info(int code, std::string msg, std::string extr if (p->m_send_to_sdcard_dlg) { p->m_send_to_sdcard_dlg->update_print_error_info(code, msg, extra); } - if (p->main_frame->m_calibration) - p->main_frame->m_calibration->update_print_error_info(code, msg, extra); + if (CalibrationPanel* calibration = CalibrationPanel::if_built()) + calibration->update_print_error_info(code, msg, extra); } wxString Plater::get_project_filename(const wxString& extension) const @@ -21069,7 +21069,8 @@ void Plater::pop_warning_and_go_to_device_page(wxString printer_name, PrinterWar { printer_name.Replace("Bambu Lab", "", false); wxString content; - bool device_page = (wxGetApp().mainframe == nullptr) && (wxGetApp().mainframe->m_monitor->IsShown()); + MainFrame* frame = wxGetApp().mainframe; + bool device_page = frame != nullptr && frame->m_monitor_page->in_book(); if (type == PrinterWarningType::NOT_CONNECTED) { if (device_page) { content = wxString::Format(_L("Printer not connected. Please go to the device page to connect %s before syncing."), diff --git a/src/slic3r/GUI/PrebuildQueue.hpp b/src/slic3r/GUI/PrebuildQueue.hpp new file mode 100644 index 0000000000..c013f53865 --- /dev/null +++ b/src/slic3r/GUI/PrebuildQueue.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include +#include + +#include "Lazy.hpp" + +namespace Slic3r { namespace GUI { + +// Holders to build at idle, ordered by prebuild_order(), run one slice at a time. The +// holders outlive the queue. Main thread only. +class PrebuildQueue +{ +public: + struct Slice + { + std::string name; // the task that ran; empty when nothing was pending + int units{ 0 }; // units run + long long ms{ 0 }; // time spent + bool completed{ false }; // the task has no more units + bool remaining{ false }; // some task is still pending + }; + + // Lower order runs first, equal order in the order added. + void add(LazyBase& task) + { + auto after = std::find_if(m_tasks.begin(), m_tasks.end(), [&](const LazyBase* t) { return t->prebuild_order() > task.prebuild_order(); }); + m_tasks.insert(after, &task); + } + + void clear() { m_tasks.clear(); } + + bool pending() const + { + return std::any_of(m_tasks.begin(), m_tasks.end(), [](const LazyBase* t) { return t->pending(); }); + } + + // The task names in queue order, comma separated. + std::string names() const + { + std::string out; + for (const LazyBase* t : m_tasks) + out += (out.empty() ? "" : ", ") + t->name(); + return out; + } + + // Runs units of the first pending task until it completes, budget_ms of now_ms() have + // passed, or interrupt() is true after a unit; on_unit gets the task name and each + // unit's duration. A task with no work is passed over and stays in the queue, so one + // whose work returns is pending again. + Slice run_slice(int budget_ms, + const std::function& now_ms, + const std::function& interrupt, + const std::function& on_unit = {}) + { + Slice slice; + auto next = std::find_if(m_tasks.begin(), m_tasks.end(), [](const LazyBase* t) { return t->pending(); }); + if (next == m_tasks.end()) + return slice; + // The pointer is copied out, since a unit may add tasks and reallocate m_tasks. + LazyBase* const task = *next; + slice.name = task->name(); + const long long started = now_ms(); + for (;;) { + const long long unit_started = now_ms(); + const bool more = task->build_step(); + const long long now = now_ms(); + ++slice.units; + if (on_unit) + on_unit(slice.name, now - unit_started); + slice.ms = now - started; + if (!more) { + slice.completed = true; + break; + } + if (slice.ms >= budget_ms || interrupt()) + break; + } + slice.remaining = pending(); + return slice; + } + +private: + std::vector m_tasks; +}; + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 001866bfd9..fd5012b5ef 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1044,8 +1044,8 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too if (m_bambu_cloud_checkbox) m_bambu_cloud_checkbox->Enable(!enabled); } else if (param == "hide_login_side_panel") { - if (wxGetApp().mainframe && wxGetApp().mainframe->m_webview) { - wxGetApp().mainframe->m_webview->SendCloudProvidersInfo(); + if (WebViewPanel* home = WebViewPanel::if_built()) { + home->SendCloudProvidersInfo(); } } // ORCA: apply the preview dimming change immediately to the currently loaded preview @@ -1254,9 +1254,8 @@ wxBoxSizer *PreferencesDialog::create_item_bambu_cloud(wxString title, wxString app_config->save(); // Update homepage visibility immediately - auto *mainframe = wxGetApp().mainframe; - if (mainframe && mainframe->m_webview) - mainframe->m_webview->SendCloudProvidersInfo(); + if (WebViewPanel* home = WebViewPanel::if_built()) + home->SendCloudProvidersInfo(); }); m_sizer->Add(cb, 0, wxALIGN_CENTER); diff --git a/src/slic3r/GUI/PrinterWebView.hpp b/src/slic3r/GUI/PrinterWebView.hpp index 8a62ce70a2..1ab1e17932 100644 --- a/src/slic3r/GUI/PrinterWebView.hpp +++ b/src/slic3r/GUI/PrinterWebView.hpp @@ -26,6 +26,7 @@ #include "wx/textctrl.h" #include #include +#include "Lazy.hpp" namespace Slic3r { @@ -34,7 +35,7 @@ namespace GUI { class PrinterWebViewHandler; -class PrinterWebView : public wxPanel { +class PrinterWebView : public wxPanel, public LazyInstance { public: PrinterWebView(wxWindow *parent); virtual ~PrinterWebView(); diff --git a/src/slic3r/GUI/Project.cpp b/src/slic3r/GUI/Project.cpp index 6d1eb0e180..8d87939afc 100644 --- a/src/slic3r/GUI/Project.cpp +++ b/src/slic3r/GUI/Project.cpp @@ -44,6 +44,7 @@ const std::vector license_list = { ProjectPanel::ProjectPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) : wxPanel(parent, id, pos, size, style) { + SetBackgroundColour(*wxWHITE); m_project_home_url = wxString::Format("file://%s/web/model/index.html", from_u8(resources_dir())); wxString strlang = wxGetApp().current_language_code_safe(); if (strlang != "") @@ -67,6 +68,7 @@ ProjectPanel::ProjectPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, m_auxiliary = new AuxiliaryPanel(this); m_auxiliary->Hide(); main_sizer->Add(m_auxiliary, wxSizerFlags().Expand().Proportion(1)); + add_build_steps_of(*m_auxiliary); Bind(EVT_AUXILIARY_DONE, [this](wxCommandEvent& e) { update_model_data();}); SetSizer(main_sizer); diff --git a/src/slic3r/GUI/Project.hpp b/src/slic3r/GUI/Project.hpp index a590212cb7..a22bc44430 100644 --- a/src/slic3r/GUI/Project.hpp +++ b/src/slic3r/GUI/Project.hpp @@ -35,6 +35,7 @@ #include "libslic3r/ProjectTask.hpp" #include "wxExtensions.hpp" #include "Auxiliary.hpp" +#include "Lazy.hpp" #define AUFILE_GREY700 wxColour(107, 107, 107) #define AUFILE_GREY500 wxColour(158, 158, 158) @@ -59,7 +60,7 @@ struct project_file{ std::string size; }; -class ProjectPanel : public wxPanel +class ProjectPanel : public wxPanel, public StagedBuild, public LazyInstance { private: std::atomic m_web_init_completed{false}; @@ -90,7 +91,6 @@ public: void msw_rescale(); void update_model_data(); void clear_model_info(); - void init_auxiliary() { m_auxiliary->init_auxiliary(); } bool Show(bool show); void OnScriptMessage(wxWebViewEvent& evt); diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index 629aef7296..a9767d6c72 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -3470,7 +3470,7 @@ void SelectMachineDialog::navigate_to_timelapse_page() main_frame->jump_to_monitor(); // then switch to Storage (Media) tab inside Monitor - auto* monitor = dynamic_cast(main_frame->m_monitor); + MonitorPanel* monitor = MonitorPanel::if_built(); if (monitor) { auto* tabpanel = monitor->get_tabpanel(); if (tabpanel) { diff --git a/src/slic3r/GUI/StagedBuild.hpp b/src/slic3r/GUI/StagedBuild.hpp new file mode 100644 index 0000000000..8f4c0454c3 --- /dev/null +++ b/src/slic3r/GUI/StagedBuild.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include + +namespace Slic3r { namespace GUI { + +// A panel whose constructor builds the skeleton and queues the rest as steps, run in order +// on the main thread, one at a time. +class StagedBuild +{ +public: + virtual ~StagedBuild() = default; + + bool built() const + { + return m_next_step == m_steps.size() && + std::all_of(m_children.begin(), m_children.end(), [](const StagedBuild* child) { return child->built(); }); + } + + // Runs one step and returns true while more remain. Own steps first, then whatever a + // child queued after its steps were forwarded. + bool build_step() + { + if (m_next_step < m_steps.size()) { + // Copied out, since a step may queue more steps and reallocate m_steps. + auto step = std::move(m_steps[m_next_step++]); + step(); + } else if (StagedBuild* child = unfinished_child()) { + child->build_step(); + } + return !built(); + } + +protected: + void add_build_step(std::function step) { m_steps.push_back(std::move(step)); } + + // Queues one step per step the child has now, and keeps the child so that built() waits + // for any it queues later. + void add_build_steps_of(StagedBuild& child) + { + m_children.push_back(&child); + for (size_t i = child.m_next_step; i < child.m_steps.size(); ++i) + add_build_step([&child] { child.build_step(); }); + } + +private: + StagedBuild* unfinished_child() const + { + auto it = std::find_if(m_children.begin(), m_children.end(), [](const StagedBuild* child) { return !child->built(); }); + return it == m_children.end() ? nullptr : *it; + } + + std::vector> m_steps; + std::vector m_children; + size_t m_next_step{ 0 }; +}; + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index fb0029edc3..218371f0b5 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -1328,18 +1328,21 @@ StatusBasePanel::StatusBasePanel(wxWindow *parent, wxWindowID id, const wxPoint wxBoxSizer *bSizer_left = new wxBoxSizer(wxVERTICAL); - auto m_monitoring_sizer = create_monitoring_page(); - bSizer_left->Add(m_monitoring_sizer, 1, wxEXPAND | wxALL, 0); + // The sizers are nested here so each step only appends to its own. + add_build_step([this, bSizer_left] { + auto m_monitoring_sizer = create_monitoring_page(); + bSizer_left->Add(m_monitoring_sizer, 1, wxEXPAND | wxALL, 0); - auto m_panel_separotor1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); - m_panel_separotor1->SetBackgroundColour(STATUS_PANEL_BG); - m_panel_separotor1->SetMinSize(wxSize(-1, PAGE_SPACING)); - m_panel_separotor1->SetMaxSize(wxSize(-1, PAGE_SPACING)); - m_monitoring_sizer->Add(m_panel_separotor1, 0, wxEXPAND, 0); + auto m_panel_separotor1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_panel_separotor1->SetBackgroundColour(STATUS_PANEL_BG); + m_panel_separotor1->SetMinSize(wxSize(-1, PAGE_SPACING)); + m_panel_separotor1->SetMaxSize(wxSize(-1, PAGE_SPACING)); + m_monitoring_sizer->Add(m_panel_separotor1, 0, wxEXPAND, 0); - m_project_task_panel = new PrintingTaskPanel(this, PrintingTaskType::PRINGINT); - m_project_task_panel->init_bitmaps(); - m_monitoring_sizer->Add(m_project_task_panel, 0, wxALL | wxEXPAND , 0); + m_project_task_panel = new PrintingTaskPanel(this, PrintingTaskType::PRINGINT); + m_project_task_panel->init_bitmaps(); + m_monitoring_sizer->Add(m_project_task_panel, 0, wxALL | wxEXPAND , 0); + }); // auto m_panel_separotor2 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); // m_panel_separotor2->SetBackgroundColour(STATUS_PANEL_BG); @@ -1359,8 +1362,10 @@ StatusBasePanel::StatusBasePanel(wxWindow *parent, wxWindowID id, const wxPoint m_machine_ctrl_panel->SetDoubleBuffered(true); auto m_machine_control = create_machine_control_page(m_machine_ctrl_panel); m_machine_ctrl_panel->SetSizer(m_machine_control); - m_machine_ctrl_panel->Layout(); - m_machine_control->Fit(m_machine_ctrl_panel); + add_build_step([this, m_machine_control] { + m_machine_ctrl_panel->Layout(); + m_machine_control->Fit(m_machine_ctrl_panel); + }); bSizer_status_below->Add(m_machine_ctrl_panel, 0, wxALL, 0); @@ -1375,8 +1380,11 @@ StatusBasePanel::StatusBasePanel(wxWindow *parent, wxWindowID id, const wxPoint m_panel_separotor_bottom->SetBackgroundColour(STATUS_PANEL_BG); bSizer_status->Add(m_panel_separotor_bottom, 0, wxEXPAND | wxALL, 0); - this->SetSizerAndFit(bSizer_status); - this->Layout(); + this->SetSizer(bSizer_status); + add_build_step([this, bSizer_status] { + bSizer_status->SetSizeHints(this); + this->Layout(); + }); } StatusBasePanel::~StatusBasePanel() @@ -1614,16 +1622,24 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) wxBoxSizer *bSizer_control = new wxBoxSizer(wxVERTICAL); - auto temp_axis_ctrl_sizer = create_temp_axis_group(parent); - auto m_filament_load_sizer = create_filament_group(parent); - + // The slot sizers keep each group's place in bSizer_control. + wxBoxSizer *temp_axis_slot = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *filament_slot = new wxBoxSizer(wxVERTICAL); /* ams control box or live nozzle-rack panel (rack printers switch between the two) */ wxSizer *ams_rack_sizer = new wxBoxSizer(wxHORIZONTAL); - ams_rack_sizer->Add(create_ams_group(parent), 0, wxEXPAND | wxLEFT); - m_panel_nozzle_rack = new wgtDeviceNozzleRack(parent); - m_panel_nozzle_rack->Show(false); - ams_rack_sizer->Add(m_panel_nozzle_rack, 0, wxEXPAND | wxLEFT); + add_build_step([this, parent, temp_axis_slot, filament_slot] { + temp_axis_slot->Add(create_temp_axis_group(parent), 0, wxEXPAND); + filament_slot->Add(create_filament_group(parent), 0, wxEXPAND); + }); + add_build_step([this, parent, ams_rack_sizer] { + ams_rack_sizer->Add(create_ams_group(parent), 0, wxEXPAND | wxLEFT); + }); + add_build_step([this, parent, ams_rack_sizer] { + m_panel_nozzle_rack = new wgtDeviceNozzleRack(parent); + m_panel_nozzle_rack->Show(false); + ams_rack_sizer->Add(m_panel_nozzle_rack, 0, wxEXPAND | wxLEFT); + }); m_ams_rack_switch = new SwitchBoard(parent, _L("Filament"), _L("Hotends"), wxSize(FromDIP(126), FromDIP(26))); m_ams_rack_switch->updateState("left"); @@ -1631,12 +1647,12 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) m_ams_rack_switch->Bind(wxCUSTOMEVT_SWITCH_POS, &StatusBasePanel::on_ams_rack_switch, this); bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(8)); - bSizer_control->Add(temp_axis_ctrl_sizer, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8)); + bSizer_control->Add(temp_axis_slot, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8)); bSizer_control->Add(m_ams_rack_switch, 0, wxALIGN_CENTRE|wxTOP, FromDIP(6)); bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(6)); bSizer_control->Add(ams_rack_sizer, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8)); bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(6)); - bSizer_control->Add(m_filament_load_sizer, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8)); + bSizer_control->Add(filament_slot, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8)); bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(4)); bSizer_right->Add(bSizer_control, 1, wxEXPAND | wxALL, 0); @@ -2228,8 +2244,10 @@ void StatusBasePanel::expand_filament_loading(wxMouseEvent& e) m_filament_step->Show(tag_show); Layout(); Fit(); - wxGetApp().mainframe->m_monitor->get_status_panel()->Layout(); - wxGetApp().mainframe->m_monitor->Layout(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) { + monitor->get_status_panel()->Layout(); + monitor->Layout(); + } } void StatusBasePanel::show_ams_group(bool show) @@ -2240,7 +2258,8 @@ void StatusBasePanel::show_ams_group(bool show) m_ams_control->Fit(); Layout(); Fit(); - wxGetApp().mainframe->m_monitor->Layout(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->Layout(); } // On rack printers, don't clobber the rack view when the user has the switch on "Hotends". @@ -2253,7 +2272,8 @@ void StatusBasePanel::show_ams_group(bool show) m_ams_control->Fit(); Layout(); Fit(); - wxGetApp().mainframe->m_monitor->Layout(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) + monitor->Layout(); } } @@ -2277,8 +2297,10 @@ void StatusBasePanel::show_filament_load_group(bool show) Layout(); Fit(); - wxGetApp().mainframe->m_monitor->get_status_panel()->Layout(); - wxGetApp().mainframe->m_monitor->Layout(); + if (MonitorPanel* monitor = MonitorPanel::if_built()) { + monitor->get_status_panel()->Layout(); + monitor->Layout(); + } } } @@ -2403,6 +2425,12 @@ void StatusPanel::update_camera_state(MachineObject* obj) StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name) : StatusBasePanel(parent, id, pos, size, style) +{ + // Wires the controls the base class builds in steps, so it is the last step. + add_build_step([this] { wire_controls(); }); +} + +void StatusPanel::wire_controls() { init_scaled_buttons(); m_buttons.push_back(m_bpButton_z_10); @@ -2514,47 +2542,50 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co StatusPanel::~StatusPanel() { - // Disconnect Events - m_project_task_panel->get_bitmap_thumbnail()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this); - m_project_task_panel->get_partskip_button()->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this); - m_project_task_panel->get_pause_resume_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this); - m_project_task_panel->get_abort_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this); - m_project_task_panel->get_market_scoring_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this); - m_project_task_panel->get_market_retry_buttom()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_retry), NULL, this); - m_project_task_panel->get_clean_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_print_error_clean), NULL, this); + // The controls only exist once the last build step has run. + if (built()) { + // Disconnect Events + m_project_task_panel->get_bitmap_thumbnail()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this); + m_project_task_panel->get_partskip_button()->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this); + m_project_task_panel->get_pause_resume_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this); + m_project_task_panel->get_abort_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this); + m_project_task_panel->get_market_scoring_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this); + m_project_task_panel->get_market_retry_buttom()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_retry), NULL, this); + m_project_task_panel->get_clean_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_print_error_clean), NULL, this); - m_setting_button->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); - m_setting_button->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); - m_tempCtrl_bed->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this); - m_tempCtrl_bed->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this); - m_tempCtrl_nozzle->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); - m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); + m_setting_button->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); + m_setting_button->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); + m_tempCtrl_bed->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this); + m_tempCtrl_bed->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this); + m_tempCtrl_nozzle->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); + m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); - m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); - m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); + m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); + m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); - m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); - /*m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - m_switch_printing_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - m_switch_cham_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);*/ + m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); + /*m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + m_switch_printing_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + m_switch_cham_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);*/ - //m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - //m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + //m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + //m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); + m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); - m_bpButton_xy->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this); - m_bpButton_z_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this); - m_bpButton_z_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this); - m_bpButton_z_down_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_1), NULL, this); - m_bpButton_z_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_10), NULL, this); - m_bpButton_e_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this); - m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this); - m_nozzle_btn_panel->Disconnect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this); - m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); - m_calibration_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); - m_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); - m_safety_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_safety_options), NULL, this); - m_parts_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this); + m_bpButton_xy->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this); + m_bpButton_z_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this); + m_bpButton_z_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this); + m_bpButton_z_down_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_1), NULL, this); + m_bpButton_z_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_10), NULL, this); + m_bpButton_e_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this); + m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this); + m_nozzle_btn_panel->Disconnect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this); + m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); + m_calibration_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); + m_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); + m_safety_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_safety_options), NULL, this); + m_parts_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this); + } // remove warning dialogs if (abort_dlg != nullptr) @@ -5216,7 +5247,9 @@ void StatusPanel::set_default() m_filament_step->Hide(); error_info_reset(); #ifndef __WXGTK__ - SetFocus(); + // Also reached while the panel is built off screen. + if (IsShownOnScreen()) + SetFocus(); #endif } diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 341bb9ab69..d79c3d3915 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -36,6 +36,7 @@ #include "HMS.hpp" #include "PartSkipDialog.hpp" #include "DeviceErrorDialog.hpp" +#include "StagedBuild.hpp" class StepIndicator; @@ -375,7 +376,7 @@ public: void paint(wxPaintEvent&); }; -class StatusBasePanel : public wxScrolledWindow +class StatusBasePanel : public wxScrolledWindow, public StagedBuild { protected: wxBitmap m_item_placeholder; @@ -443,7 +444,7 @@ protected: wxMediaCtrl3 * m_media_ctrl; - MediaPlayCtrl * m_media_play_ctrl; + MediaPlayCtrl * m_media_play_ctrl{nullptr}; Label * m_staticText_printing; wxStaticBitmap *m_bitmap_thumbnail; @@ -629,6 +630,7 @@ class StatusPanel : public StatusBasePanel { private: friend class MonitorPanel; + void wire_controls(); protected: std::shared_ptr m_slice_info_popup; @@ -679,7 +681,7 @@ protected: std::map m_print_connect_types; std::vector