From afc37568435710ef7edd2b5b6a6b292fc9f6bcf9 Mon Sep 17 00:00:00 2001 From: goofoo Date: Wed, 8 Apr 2026 00:08:35 -0400 Subject: [PATCH] =?UTF-8?q?fix+feat:=20Snapmaker=20U1=20=E2=80=94=205=20bu?= =?UTF-8?q?g=20fixes=20and=200.6mm=20/=20mixed-nozzle=20profiles=20(#12244?= =?UTF-8?q?=20#12390=20#12652=20#12073=20#12797=20#11424)=20(#12824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build_all.yml | 1 + resources/profiles/Snapmaker.json | 28 ++++++++++ .../machine/Snapmaker U1 (0.4 nozzle).json | 48 ++++++++++++++++- .../Snapmaker U1 (0.4+0.6 nozzle).json | 30 +++++++++++ .../machine/Snapmaker U1 (0.6 nozzle).json | 30 +++++++++++ .../Snapmaker/machine/Snapmaker U1.json | 4 +- ...andard @Snapmaker U1 (0.4+0.6 nozzle).json | 32 ++++++++++++ ...0 Standard @Snapmaker U1 (0.6 nozzle).json | 25 +++++++++ ...0.30 Draft @Snapmaker U1 (0.6 nozzle).json | 29 +++++++++++ ...xtra Draft @Snapmaker U1 (0.6 nozzle).json | 30 +++++++++++ .../process/fdm_process_U1_0.6_common.json | 16 ++++++ src/libslic3r/GCodeWriter.cpp | 16 +++++- src/slic3r/GUI/FilamentMapDialog.cpp | 8 +++ src/slic3r/GUI/GLCanvas3D.cpp | 4 +- src/slic3r/GUI/PartPlate.cpp | 51 +++++++++++++++---- 15 files changed, 337 insertions(+), 15 deletions(-) create mode 100644 resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4+0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/machine/Snapmaker U1 (0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/process/0.30 Draft @Snapmaker U1 (0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/process/0.40 Extra Draft @Snapmaker U1 (0.6 nozzle).json create mode 100644 resources/profiles/Snapmaker/process/fdm_process_U1_0.6_common.json diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 107dcdc29e..2a0f78c6dd 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -160,6 +160,7 @@ jobs: runner: ubuntu-24.04-arm # Don't run scheduled builds on forks; skip entirely on self-hosted runners if: ${{ !cancelled() && !vars.SELF_HOSTED && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }} + runs-on: ${{ matrix.variant.runner }} env: date: diff --git a/resources/profiles/Snapmaker.json b/resources/profiles/Snapmaker.json index 458e17f7d6..16093772f1 100644 --- a/resources/profiles/Snapmaker.json +++ b/resources/profiles/Snapmaker.json @@ -454,6 +454,26 @@ "name": "0.28 Extra Draft @Snapmaker U1 (0.4 nozzle)", "sub_path": "process/0.28 Extra Draft @Snapmaker U1 (0.4 nozzle).json" }, + { + "name": "fdm_process_U1_0.6_common", + "sub_path": "process/fdm_process_U1_0.6_common.json" + }, + { + "name": "0.20 Standard @Snapmaker U1 (0.6 nozzle)", + "sub_path": "process/0.20 Standard @Snapmaker U1 (0.6 nozzle).json" + }, + { + "name": "0.30 Draft @Snapmaker U1 (0.6 nozzle)", + "sub_path": "process/0.30 Draft @Snapmaker U1 (0.6 nozzle).json" + }, + { + "name": "0.40 Extra Draft @Snapmaker U1 (0.6 nozzle)", + "sub_path": "process/0.40 Extra Draft @Snapmaker U1 (0.6 nozzle).json" + }, + { + "name": "0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle)", + "sub_path": "process/0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle).json" + }, { "name": "0.06 Standard @Snapmaker Artisan (0.2 nozzle)", "sub_path": "process/0.06 Standard @Snapmaker Artisan (0.2 nozzle).json" @@ -1530,6 +1550,14 @@ "name": "Snapmaker U1 (0.4 nozzle)", "sub_path": "machine/Snapmaker U1 (0.4 nozzle).json" }, + { + "name": "Snapmaker U1 (0.6 nozzle)", + "sub_path": "machine/Snapmaker U1 (0.6 nozzle).json" + }, + { + "name": "Snapmaker U1 (0.4+0.6 nozzle)", + "sub_path": "machine/Snapmaker U1 (0.4+0.6 nozzle).json" + }, { "name": "Snapmaker A250 BKit (0.2 nozzle)", "sub_path": "machine/Snapmaker A250 BKit (0.2 nozzle).json" diff --git a/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4 nozzle).json b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4 nozzle).json index 6422735955..d7a68179b7 100644 --- a/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4 nozzle).json +++ b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4 nozzle).json @@ -29,6 +29,38 @@ "0" ], "machine_end_gcode": " PRINT_END\nTIMELAPSE_STOP", + "machine_max_acceleration_extruding": [ + "25000", + "25000" + ], + "machine_max_acceleration_retracting": [ + "5000", + "5000" + ], + "machine_max_acceleration_travel": [ + "25000", + "25000" + ], + "machine_max_acceleration_x": [ + "25000", + "25000" + ], + "machine_max_acceleration_y": [ + "25000", + "25000" + ], + "machine_max_acceleration_z": [ + "500", + "200" + ], + "machine_max_jerk_x": [ + "9", + "9" + ], + "machine_max_jerk_y": [ + "9", + "9" + ], "machine_max_jerk_z": [ "3", "0.4" @@ -37,10 +69,21 @@ "30", "25" ], + "machine_max_speed_x": [ + "1000", + "200" + ], + "machine_max_speed_y": [ + "1000", + "200" + ], "machine_max_speed_z": [ "20", "12" ], + "resonance_avoidance": "1", + "min_resonance_avoidance_speed": "40", + "max_resonance_avoidance_speed": "90", "machine_start_gcode": "SET_PRINT_AUTO_BED_LEVELING ENABLE=1\nSET_TIME_LAPSE_CAMERA ENABLE=1\n;===== date: 20251222 =====================\n\nPRINT_START\nDEFECT_DETECTION_START\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count}\nSET_PRINT_STATS_INFO CURRENT_LAYER=0\nTIMELAPSE_START\nM140 S{bed_temperature_initial_layer_single}\nM104 T{initial_extruder} S140\nM204 S10000\n\nG28 X Y\n;===== 床面异物检测 ========\nT{initial_extruder}\nG90\nDEFECT_DETECTION_DETECT_BED\n;===== 取放头检测 =================\nSM_PRINT_CHECK_SWITCH_EXTRUDER\n\n;===== 自动进料 & 挤出流量 & 预挤出 ======================\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=1 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=0\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=0\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=2 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=1\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=1\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=3 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=2\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=2\nSM_PRINT_AUTO_FEED EXTRUDER=3\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=3\nM104 S0 T0 A0\nM104 S0 T1 A0\nM104 S0 T2 A0\nM104 S0 T3 A0\nM104 T{initial_extruder} S{nozzle_temperature[initial_extruder] - 90}\n\n;===== 粗回零 =================\nT{initial_extruder}\nM106 S255\nM106 P2 S0\nMOVE_TO_DISCARD_FILAMENT_POSITION\nM109 T{initial_extruder} S{nozzle_temperature[initial_extruder] - 90}\nROUGHLY_CLEAN_NOZZLE_WITH_DISCARD\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nG28 Z I140 J140\n\n;===== 检测钢板 =================\nDETECT_BED_PLATE\n\n;===== 深度清洁喷嘴 =================\nG90\nG0 Z5 F10000\nMOVE_TO_DISCARD_FILAMENT_POSITION\nM109 S{nozzle_temperature[initial_extruder] - 50}\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_1\nM104 S{nozzle_temperature[initial_extruder] - 90}\nG0 Z5 F10000\nMOVE_TO_DISCARD_FILAMENT_POSITION\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_2\n\n;===== 精回零 =================\nM106 S255\nM109 S{nozzle_temperature[initial_extruder] - 90}\nM190 S{bed_temperature_initial_layer_single}\nM107 P2\nG90\nG0 Z5 F10000\nG28 Z\n\n;===== 热床调平 =================\n; Always pass `ADAPTIVE_MARGIN=0` because Orca has already handled `adaptive_bed_mesh_margin` internally\n; Make sure to set ADAPTIVE to 0 otherwise Klipper will use it's own adaptive bed mesh logic\nBED_MESH_CALIBRATE mesh_min={adaptive_bed_mesh_min[0]},{adaptive_bed_mesh_min[1]} mesh_max={adaptive_bed_mesh_max[0]},{adaptive_bed_mesh_max[1]} ALGORITHM=[bed_mesh_algo] PROBE_COUNT={bed_mesh_probe_count[0]},{bed_mesh_probe_count[1]} ADAPTIVE=0 ADAPTIVE_MARGIN=0\n; Original upstream: BED_MESH_CALIBRATE PROBE_COUNT=11,11\n\n;===== 画起始线 =================\nG90\nG1 Z1.5\nG0 X10 Y3 Z2 F18000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nM83\nG1 X110 E15 F360\nG1 Z1.5\n\nG90\nM106 S0", "machine_tool_change_time": "5", "max_layer_height": [ @@ -180,8 +223,9 @@ "Auto Lift" ], "enable_filament_ramming": "0", - "extruder_clearance_height_to_rod": "27.5", - "extruder_clearance_radius": "72.5", + "extruder_clearance_height_to_rod": "60", + "extruder_clearance_height_to_lid": "130", + "extruder_clearance_radius": "80", "machine_load_filament_time": "0", "machine_unload_filament_time": "0", "before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\nTIMELAPSE_TAKE_FRAME\nDEFECT_DETECTION_DETECT", diff --git a/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4+0.6 nozzle).json b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4+0.6 nozzle).json new file mode 100644 index 0000000000..9443194857 --- /dev/null +++ b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.4+0.6 nozzle).json @@ -0,0 +1,30 @@ +{ + "type": "machine", + "setting_id": "SM_U1_04_06", + "name": "Snapmaker U1 (0.4+0.6 nozzle)", + "from": "system", + "instantiation": "true", + "inherits": "fdm_U1", + "printer_model": "Snapmaker U1", + "printer_variant": "0.4+0.6", + "default_print_profile": "0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle)", + "max_layer_height": [ + "0.32", + "0.32", + "0.48", + "0.48" + ], + "min_layer_height": [ + "0.08", + "0.08", + "0.12", + "0.12" + ], + "nozzle_diameter": [ + "0.4", + "0.4", + "0.6", + "0.6" + ], + "nozzle_type": "stainless_steel" +} diff --git a/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.6 nozzle).json b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.6 nozzle).json new file mode 100644 index 0000000000..8371971207 --- /dev/null +++ b/resources/profiles/Snapmaker/machine/Snapmaker U1 (0.6 nozzle).json @@ -0,0 +1,30 @@ +{ + "type": "machine", + "setting_id": "SM_U1_06", + "name": "Snapmaker U1 (0.6 nozzle)", + "from": "system", + "instantiation": "true", + "inherits": "fdm_U1", + "printer_model": "Snapmaker U1", + "printer_variant": "0.6", + "default_print_profile": "0.20 Standard @Snapmaker U1 (0.6 nozzle)", + "max_layer_height": [ + "0.48", + "0.48", + "0.48", + "0.48" + ], + "min_layer_height": [ + "0.12", + "0.12", + "0.12", + "0.12" + ], + "nozzle_diameter": [ + "0.6", + "0.6", + "0.6", + "0.6" + ], + "nozzle_type": "stainless_steel" +} diff --git a/resources/profiles/Snapmaker/machine/Snapmaker U1.json b/resources/profiles/Snapmaker/machine/Snapmaker U1.json index 027d088e57..1856c25a78 100644 --- a/resources/profiles/Snapmaker/machine/Snapmaker U1.json +++ b/resources/profiles/Snapmaker/machine/Snapmaker U1.json @@ -7,5 +7,5 @@ "model_id": "797581801", "bed_model": "Snapmaker U1_bed.stl", "bed_texture": "Snapmaker U1_texture.svg", - "nozzle_diameter": "0.4" -} \ No newline at end of file + "nozzle_diameter": "0.4;0.4+0.6;0.6" +} diff --git a/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle).json b/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle).json new file mode 100644 index 0000000000..3d05198376 --- /dev/null +++ b/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle).json @@ -0,0 +1,32 @@ +{ + "type": "process", + "name": "0.20 Standard @Snapmaker U1 (0.4+0.6 nozzle)", + "inherits": "fdm_process_U1_0.20", + "from": "system", + "setting_id": "GP004_0406_020", + "instantiation": "true", + "description": "Standard profile for the Snapmaker U1 mixed-nozzle configuration (T0/T1 = 0.4 mm, T2/T3 = 0.6 mm). Line widths are expressed as percentages of nozzle diameter so they scale correctly per tool. Use T0/T1 for detail work and outer walls; use T2/T3 for fast infill or large structural features.", + "compatible_printers": [ + "Snapmaker U1 (0.4+0.6 nozzle)" + ], + "line_width": "105%", + "outer_wall_line_width": "105%", + "inner_wall_line_width": "112%", + "initial_layer_line_width": "125%", + "sparse_infill_line_width": "105%", + "internal_solid_infill_line_width": "105%", + "support_line_width": "105%", + "top_surface_line_width": "105%", + "smooth_coefficient": "150", + "overhang_totally_speed": "50", + "ooze_prevention": "1", + "slowdown_for_curled_perimeters": "0", + "standby_temperature_delta": "-150", + "wipe_tower_filament": "0", + "preheat_time": "30", + "wipe_tower_cone_angle": "15", + "prime_tower_brim_width": "5", + "initial_layer_print_height": "0.25", + "top_shell_layers": "5", + "bottom_shell_layers": "3" +} diff --git a/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.6 nozzle).json b/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.6 nozzle).json new file mode 100644 index 0000000000..283524ba0a --- /dev/null +++ b/resources/profiles/Snapmaker/process/0.20 Standard @Snapmaker U1 (0.6 nozzle).json @@ -0,0 +1,25 @@ +{ + "type": "process", + "name": "0.20 Standard @Snapmaker U1 (0.6 nozzle)", + "inherits": "fdm_process_U1_0.6_common", + "from": "system", + "setting_id": "GP004_06_020", + "instantiation": "true", + "description": "Standard 0.2 mm layer height profile for the Snapmaker U1 with 0.6 mm nozzles. Balances print speed and surface quality for everyday prints.", + "layer_height": "0.20", + "smooth_coefficient": "150", + "overhang_totally_speed": "50", + "compatible_printers": [ + "Snapmaker U1 (0.6 nozzle)" + ], + "ooze_prevention": "1", + "slowdown_for_curled_perimeters": "0", + "standby_temperature_delta": "-150", + "wipe_tower_filament": "0", + "preheat_time": "30", + "wipe_tower_cone_angle": "15", + "prime_tower_brim_width": "5", + "initial_layer_print_height": "0.25", + "top_shell_layers": "4", + "bottom_shell_layers": "3" +} diff --git a/resources/profiles/Snapmaker/process/0.30 Draft @Snapmaker U1 (0.6 nozzle).json b/resources/profiles/Snapmaker/process/0.30 Draft @Snapmaker U1 (0.6 nozzle).json new file mode 100644 index 0000000000..dac47d0a6b --- /dev/null +++ b/resources/profiles/Snapmaker/process/0.30 Draft @Snapmaker U1 (0.6 nozzle).json @@ -0,0 +1,29 @@ +{ + "type": "process", + "name": "0.30 Draft @Snapmaker U1 (0.6 nozzle)", + "inherits": "fdm_process_U1_0.6_common", + "from": "system", + "setting_id": "GP004_06_030", + "instantiation": "true", + "description": "Fast draft profile for the Snapmaker U1 with 0.6 mm nozzles. 0.3 mm layer height for quick prototypes and functional parts.", + "layer_height": "0.30", + "smooth_coefficient": "80", + "overhang_totally_speed": "40", + "compatible_printers": [ + "Snapmaker U1 (0.6 nozzle)" + ], + "ooze_prevention": "1", + "slowdown_for_curled_perimeters": "0", + "standby_temperature_delta": "-150", + "wipe_tower_filament": "0", + "preheat_time": "30", + "wipe_tower_cone_angle": "15", + "prime_tower_brim_width": "5", + "initial_layer_print_height": "0.30", + "top_shell_layers": "3", + "bottom_shell_layers": "3", + "outer_wall_speed": "220", + "inner_wall_speed": "330", + "sparse_infill_speed": "300", + "internal_solid_infill_speed": "280" +} diff --git a/resources/profiles/Snapmaker/process/0.40 Extra Draft @Snapmaker U1 (0.6 nozzle).json b/resources/profiles/Snapmaker/process/0.40 Extra Draft @Snapmaker U1 (0.6 nozzle).json new file mode 100644 index 0000000000..9e2966c9d3 --- /dev/null +++ b/resources/profiles/Snapmaker/process/0.40 Extra Draft @Snapmaker U1 (0.6 nozzle).json @@ -0,0 +1,30 @@ +{ + "type": "process", + "name": "0.40 Extra Draft @Snapmaker U1 (0.6 nozzle)", + "inherits": "fdm_process_U1_0.6_common", + "from": "system", + "setting_id": "GP004_06_040", + "instantiation": "true", + "description": "Maximum-speed profile for the Snapmaker U1 with 0.6 mm nozzles. 0.4 mm layer height for rapid prototyping where surface finish is not critical.", + "layer_height": "0.40", + "smooth_coefficient": "80", + "overhang_totally_speed": "30", + "compatible_printers": [ + "Snapmaker U1 (0.6 nozzle)" + ], + "ooze_prevention": "1", + "slowdown_for_curled_perimeters": "0", + "standby_temperature_delta": "-150", + "wipe_tower_filament": "0", + "preheat_time": "30", + "wipe_tower_cone_angle": "15", + "prime_tower_brim_width": "5", + "initial_layer_print_height": "0.35", + "top_shell_layers": "3", + "bottom_shell_layers": "3", + "outer_wall_speed": "220", + "inner_wall_speed": "330", + "sparse_infill_speed": "320", + "internal_solid_infill_speed": "300", + "wall_loops": "2" +} diff --git a/resources/profiles/Snapmaker/process/fdm_process_U1_0.6_common.json b/resources/profiles/Snapmaker/process/fdm_process_U1_0.6_common.json new file mode 100644 index 0000000000..4f52fa516b --- /dev/null +++ b/resources/profiles/Snapmaker/process/fdm_process_U1_0.6_common.json @@ -0,0 +1,16 @@ +{ + "type": "process", + "name": "fdm_process_U1_0.6_common", + "inherits": "fdm_process_U1_common", + "from": "system", + "instantiation": "false", + "line_width": "0.62", + "outer_wall_line_width": "0.62", + "inner_wall_line_width": "0.62", + "initial_layer_line_width": "0.72", + "sparse_infill_line_width": "0.62", + "internal_solid_infill_line_width": "0.62", + "support_line_width": "0.62", + "top_surface_line_width": "0.62", + "compatible_printers": [] +} diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 1aff72daeb..ef6ff54e5e 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -30,7 +30,21 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config) m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; bool use_mach_limits = print_config.gcode_flavor.value == gcfMarlinLegacy || print_config.gcode_flavor.value == gcfMarlinFirmware || print_config.gcode_flavor.value == gcfKlipper || print_config.gcode_flavor.value == gcfRepRapFirmware; - m_max_acceleration = std::lrint(use_mach_limits ? print_config.machine_max_acceleration_extruding.values.front() : 0); + if (use_mach_limits) { + // For Klipper, SET_VELOCITY_LIMIT ACCEL= applies to all moves, so the effective cap + // is the minimum of the extruding limit and the per-axis X/Y limits. + // This ensures user-configured Motion Ability limits are honoured (#12244). + unsigned int extruding_limit = std::lrint(print_config.machine_max_acceleration_extruding.values.front()); + if (print_config.gcode_flavor.value == gcfKlipper) { + unsigned int x_limit = std::lrint(print_config.machine_max_acceleration_x.values.front()); + unsigned int y_limit = std::lrint(print_config.machine_max_acceleration_y.values.front()); + if (x_limit > 0) extruding_limit = std::min(extruding_limit, x_limit); + if (y_limit > 0) extruding_limit = std::min(extruding_limit, y_limit); + } + m_max_acceleration = extruding_limit; + } else { + m_max_acceleration = 0; + } m_max_travel_acceleration = static_cast( std::round((use_mach_limits && supports_separate_travel_acceleration(print_config.gcode_flavor.value)) ? print_config.machine_max_acceleration_travel.values.front() : diff --git a/src/slic3r/GUI/FilamentMapDialog.cpp b/src/slic3r/GUI/FilamentMapDialog.cpp index f765e94aa6..957b2b9d0e 100644 --- a/src/slic3r/GUI/FilamentMapDialog.cpp +++ b/src/slic3r/GUI/FilamentMapDialog.cpp @@ -46,6 +46,14 @@ bool try_pop_up_before_slice(bool is_slice_all, Plater* plater_ref, PartPlate* p if (nozzle_diameters->size() <= 1) return true; + // The filament-grouping dialog is specifically designed for BBL dual-nozzle printers + // (e.g. H2D) where filaments must be assigned to a left or right nozzle. + // For toolchangers (≥3 tools) and all non-BBL printers the dialog is irrelevant and + // confusing; skip it entirely so slicing proceeds without interruption. (#12390) + PresetBundle* preset = wxGetApp().preset_bundle; + if (!preset || !preset->is_bbl_vendor() || nozzle_diameters->size() != 2) + return true; + bool sync_plate = true; std::vector filament_colors = full_config.option("filament_colour")->values; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5e23a9d4ae..2c8285720b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -9714,7 +9714,9 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) wxString region = L"en"; if (language.find("zh") == 0) region = L"zh"; - wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.bambulab.com/%s/filament-acc/filament/h2d-pla-and-petg-mutual-support", region)); + // Use the generic dual-nozzle PLA+PETG guide rather than the H2D-specific page + // so the link is relevant for all dual-extrusion printers, not just Bambu H2D. (#12073) + wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.bambulab.com/%s/filament-acc/filament/pla-and-petg-dual-extrusion", region)); return false; }); } diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 37baa25a5f..2fa4ab7f56 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1871,26 +1871,59 @@ bool PartPlate::check_mixture_of_pla_and_petg(const DynamicPrintConfig &config) bool has_pla = false; bool has_petg = false; - std::vector used_filaments = get_extruders(true); // 1 base + // On a toolchanger (machine_tool_change_time > 0) each filament slot maps to a + // separate physical nozzle: only one nozzle is ever mounted or heated at a time, so + // there is no cross-nozzle contamination between PLA and PETG. Track which physical + // nozzle each material is on; warn only when PLA and PETG would pass through the + // *same* nozzle. + // + // NOTE: if MMU-on-toolchanger support is added (#10586), the nozzle-mapping logic + // will need to be revisited because multiple filaments may then share one tool slot. + bool is_toolchanger = false; + auto *tool_change_time = config.option("machine_tool_change_time"); + if (tool_change_time && tool_change_time->value > 0) + is_toolchanger = true; + + // nozzle index → whether it carries PLA / PETG + std::map nozzle_has_pla; + std::map nozzle_has_petg; + + std::vector used_filaments = get_extruders(true); // 1-based if (!used_filaments.empty()) { + const auto *filament_types = config.option("filament_type"); for (auto filament_idx : used_filaments) { - int filament_id = filament_idx - 1; - if (filament_id < config.option("filament_type")->values.size()) { - std::string filament_type = config.option("filament_type")->values.at(filament_id); - if (filament_type == "PLA") + int filament_id = filament_idx - 1; + if (filament_id < (int)filament_types->values.size()) { + const std::string &filament_type = filament_types->values[filament_id]; + if (filament_type == "PLA") { has_pla = true; - if (filament_type == "PETG") + nozzle_has_pla[filament_id] = true; + } + if (filament_type == "PETG") { has_petg = true; + nozzle_has_petg[filament_id] = true; + } } else { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " check error:array bound"; } } } - if (has_pla && has_petg) - return false; + if (!has_pla || !has_petg) + return true; // no mixture — no warning - return true; + if (is_toolchanger) { + // Warn only if any single nozzle slot carries both PLA and PETG (e.g. future MMU + // on toolchanger). On a pure toolchanger each slot is independent, so this loop + // will never fire and the warning is correctly suppressed. (#12073) + for (const auto &kv : nozzle_has_pla) { + if (nozzle_has_petg.count(kv.first)) + return false; // same nozzle → warn + } + return true; // different nozzles → safe, no warning + } + + return false; // non-toolchanger with both PLA and PETG → warn } bool PartPlate::check_mixture_filament_compatible(const DynamicPrintConfig &config, std::string &error_msg)