From 7fa6175b4fbb230d26d3fa1d77cbe3964e7de1fb Mon Sep 17 00:00:00 2001 From: yw4z Date: Mon, 22 Dec 2025 20:30:03 +0300 Subject: [PATCH 1/8] Compact Printer Selection UI - part 3 (#11676) * init * Update ImageDPIFrame.cpp * Update Plater.cpp * update * update * Update PresetBundle.cpp * ensure 0.25 returned as 0.25 instead 0.2 * Merge branch 'main' into compact-printer-selection-UI-part-3 * Merge branch 'main' into compact-printer-selection-UI-part-3 * Merge branch 'main' into compact-printer-selection-UI-part-3 --- src/libslic3r/PresetBundle.cpp | 5 ++++- src/slic3r/GUI/ImageDPIFrame.cpp | 8 ++++++++ src/slic3r/GUI/Plater.cpp | 31 +++++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index c123cf53d0..b3efae168f 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -2751,6 +2751,8 @@ Preset *PresetBundle::get_similar_printer_preset(std::string printer_model, std: { if (printer_model.empty()) printer_model = printers.get_selected_preset().config.opt_string("printer_model"); + if (printer_model.empty()) // ORCA ensure a compatible model exist. fixes switches to blank preset if preset has no inherited value + return nullptr; auto printer_variant_old = printers.get_selected_preset().config.opt_string("printer_variant"); std::map printer_presets; for (auto &preset : printers.m_presets) { @@ -2761,7 +2763,8 @@ Preset *PresetBundle::get_similar_printer_preset(std::string printer_model, std: } if (printer_presets.empty()) return nullptr; - auto prefer_printer = printers.get_selected_preset().name; + auto prefer_printer = printers.get_selected_preset().alias; //.name ORCA use alias instead "name" for calling system presets. otherwise nozzle combo will not change printer presets if they custom named + if (!printer_variant.empty()) boost::replace_all(prefer_printer, printer_variant_old, printer_variant); else if (auto n = prefer_printer.find(printer_variant_old); n != std::string::npos) diff --git a/src/slic3r/GUI/ImageDPIFrame.cpp b/src/slic3r/GUI/ImageDPIFrame.cpp index 06c3f59c3f..2133f18784 100644 --- a/src/slic3r/GUI/ImageDPIFrame.cpp +++ b/src/slic3r/GUI/ImageDPIFrame.cpp @@ -29,6 +29,14 @@ ImageDPIFrame::ImageDPIFrame() #ifdef __APPLE__ SetWindowStyleFlag(GetWindowStyleFlag() | wxSTAY_ON_TOP); #endif + + // ORCA add border + Bind(wxEVT_PAINT, [this](wxPaintEvent& evt) { + wxPaintDC dc(this); + dc.SetPen(StateColor::darkModeColorFor(wxColour("#DBDBDB"))); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); + }); m_sizer_main = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ff784d4528..cc67ee11fd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -220,9 +220,14 @@ wxDEFINE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent); static string get_diameter_string(float diameter) { - std::ostringstream stream; - stream << std::fixed << std::setprecision(1) << diameter; - return stream.str(); + std::ostringstream stream; // ORCA ensure 0.25 returned as 0.25. previous code returned as 0.2 because of std::setprecision(1) + stream << std::fixed << std::setprecision(2) << diameter; // Use 2 decimals to capture 0.25 / 0.15 reliably + std::string s = stream.str(); + if (s.find('.') != std::string::npos) { // Remove trailing zeros, but keep at least one decimal if needed + s.erase(s.find_last_not_of('0') + 1); + if (s.back() == '.') s += '0'; // Ensure "1." → "1.0" + } + return s; } bool Plater::has_illegal_filename_characters(const wxString& wxs_name) @@ -1232,7 +1237,8 @@ bool Sidebar::priv::switch_diameter(bool single) } auto preset = wxGetApp().preset_bundle->get_similar_printer_preset({}, diameter.ToStdString()); if (preset == nullptr) { - MessageDialog dlg(this->plater, "", ""); + // ORCA add a text. this appears when user tries to change nozzle value but config doesnt have a inherited or compatible preset + MessageDialog dlg(this->plater, _L("Configuration incompatible"), _L("Warning"), wxICON_WARNING | wxOK); dlg.ShowModal(); return false; } @@ -2538,9 +2544,18 @@ void Sidebar::update_presets(Preset::Type preset_type) p->layout_printer(preset_bundle.use_bbl_network(), isBBL && is_dual_extruder); auto diameters = wxGetApp().preset_bundle->printers.diameters_of_selected_printer(); auto diameter = printer_preset.config.opt_string("printer_variant"); - auto update_extruder_diameter = [&diameters, &diameter](ExtruderGroup & extruder) { + auto update_extruder_diameter = [&diameters, &diameter, &nozzle_diameter](int extruder_index,ExtruderGroup & extruder) { extruder.combo_diameter->Clear(); int select = -1; + // ORCA if user defined a custom nozzle in printer config select it instead inherited one. this will show correct nozzle diameter in combobox if its exist in nozzle diameters list + auto nozzle_dia = get_diameter_string(nozzle_diameter->values[extruder_index]); + if(nozzle_dia != diameter && std::find(diameters.begin(), diameters.end(), nozzle_dia) != diameters.end()) + diameter = nozzle_dia; + // ORCA try to add nozzle diameter from config if list is empty. fixes blank nozzle combo box when preset has no alias + if(diameters[0].empty() && !nozzle_dia.empty()){ + diameters[0] = nozzle_dia; + diameter = nozzle_dia; + } for (size_t i = 0; i < diameters.size(); ++i) { if (diameters[i] == diameter) select = extruder.combo_diameter->GetCount(); @@ -2554,14 +2569,14 @@ void Sidebar::update_presets(Preset::Type preset_type) AMSCountPopupWindow::UpdateAMSCount(0, p->left_extruder); AMSCountPopupWindow::UpdateAMSCount(1, p->right_extruder); //if (!p->is_switching_diameter) { - update_extruder_diameter(*p->left_extruder); - update_extruder_diameter(*p->right_extruder); + update_extruder_diameter(0, *p->left_extruder); + update_extruder_diameter(1, *p->right_extruder); //} p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, PRINTER_THUMBNAIL_SIZE.GetHeight())); } else { AMSCountPopupWindow::UpdateAMSCount(0, p->single_extruder); //if (!p->is_switching_diameter) - update_extruder_diameter(*p->single_extruder); + update_extruder_diameter(0, *p->single_extruder); // ORCA sync unified nozzle combo box p->combo_nozzle_dia->Clear(); From f08cae6c5a537aa8fc7a6008d041e70dd9a42a37 Mon Sep 17 00:00:00 2001 From: Kuran Kaname Date: Tue, 23 Dec 2025 06:55:55 +0200 Subject: [PATCH 2/8] Adjust resonance avoidance speed calculation (#11462) * Adjust resonance avoidance speed calculation * Only adjust if it's strictly below max * If the speed is over half of the set speed range, use the max speed to prevent slowdowns Signed-off-by: Kuran Kaname * update comment --------- Signed-off-by: Kuran Kaname Co-authored-by: SoftFever --- src/libslic3r/GCode.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 048a428e40..eae1d1711a 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6186,10 +6186,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, ); } - // if still in avoidance mode and under “max”, clamp to “min” - if (m_resonance_avoidance - && speed <= m_config.max_resonance_avoidance_speed.value) { - speed = std::min(speed, m_config.min_resonance_avoidance_speed.value); + // if still in avoidance mode and under "max", adjust speed: + // - speeds in lower half of range: clamp down to "min" + // - speeds in upper half of range: boost up to "max" if (m_resonance_avoidance && speed < m_config.max_resonance_avoidance_speed.value) { + if (speed < m_config.min_resonance_avoidance_speed.value + + ((m_config.max_resonance_avoidance_speed.value - m_config.min_resonance_avoidance_speed.value) / 2)) { + speed = std::min(speed, m_config.min_resonance_avoidance_speed.value); + } else { + speed = m_config.max_resonance_avoidance_speed.value; + } } // reset flag for next segment From baf5f286c3a0699e967e2437527c4d8914944dfe Mon Sep 17 00:00:00 2001 From: Brandon Wees Date: Mon, 22 Dec 2025 23:56:53 -0500 Subject: [PATCH 3/8] feat: update CORE One profiles for to Prusa 2.4.2 (#11453) * feat: update CORE One profiles for to Prusa 2.4.2 * fix: top surface acceleration * fix: top surface acceleration duplicates * fix: incorrect overhang speed mappings * fix: duplicate keys --------- Co-authored-by: Noisyfox --- .../Prusa/process/0.05mm DETAIL @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.07mm DETAIL @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.10mm FAST DETAIL @CORE One 0.4.json | 5 ++++- .../Prusa/process/0.10mm STRUCTURAL @CORE One 0.5.json | 6 +++--- .../Prusa/process/0.12mm SPEED @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.12mm STRUCTURAL @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.12mm STRUCTURAL @CORE One 0.3.json | 5 ++++- .../Prusa/process/0.15mm SPEED @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.15mm SPEED @CORE One 0.4.json | 5 +++-- .../Prusa/process/0.15mm SPEED @CORE One HF 0.4.json | 5 +++-- .../Prusa/process/0.15mm STRUCTURAL @CORE One 0.25.json | 5 ++++- .../Prusa/process/0.15mm STRUCTURAL @CORE One 0.4.json | 2 +- .../Prusa/process/0.15mm STRUCTURAL @CORE One 0.5.json | 2 +- .../Prusa/process/0.15mm STRUCTURAL @CORE One 0.6.json | 9 +++++---- .../Prusa/process/0.16mm SPEED @CORE One 0.3.json | 5 ++++- .../Prusa/process/0.16mm STRUCTURAL @CORE One 0.3.json | 5 ++++- .../Prusa/process/0.20mm SOLUBLE FULL @CORE One 0.4.json | 7 +++++-- .../process/0.20mm SOLUBLE INTERFACE @CORE One 0.4.json | 7 +++++-- .../Prusa/process/0.20mm SPEED @CORE One 0.3.json | 5 ++++- .../Prusa/process/0.20mm SPEED @CORE One 0.4.json | 5 +++-- .../Prusa/process/0.20mm SPEED @CORE One 0.5.json | 2 +- .../Prusa/process/0.20mm SPEED @CORE One 0.6.json | 9 ++++++--- .../Prusa/process/0.20mm SPEED @CORE One HF 0.4.json | 7 ++++--- .../Prusa/process/0.20mm SPEED @CORE One HF 0.5.json | 2 +- .../Prusa/process/0.20mm SPEED @CORE One HF 0.6.json | 4 ++-- .../Prusa/process/0.20mm STRUCTURAL @CORE One 0.3.json | 5 ++++- .../Prusa/process/0.20mm STRUCTURAL @CORE One 0.4.json | 2 +- .../Prusa/process/0.20mm STRUCTURAL @CORE One 0.5.json | 2 +- .../Prusa/process/0.20mm STRUCTURAL @CORE One 0.6.json | 2 +- .../Prusa/process/0.25mm SPEED @CORE One 0.5.json | 2 +- .../Prusa/process/0.25mm SPEED @CORE One 0.6.json | 9 ++++++--- .../Prusa/process/0.25mm SPEED @CORE One HF 0.4.json | 9 +++++---- .../Prusa/process/0.25mm SPEED @CORE One HF 0.5.json | 2 +- .../Prusa/process/0.25mm SPEED @CORE One HF 0.6.json | 4 ++-- .../Prusa/process/0.25mm STRUCTURAL @CORE One 0.5.json | 2 +- .../Prusa/process/0.25mm STRUCTURAL @CORE One 0.6.json | 2 +- .../process/0.25mm STRUCTURAL @CORE One HF 0.4.json | 2 +- .../Prusa/process/0.28mm DRAFT @CORE One HF 0.4.json | 2 +- .../Prusa/process/0.30mm DETAIL @CORE One 0.8.json | 7 ++++--- .../Prusa/process/0.30mm SPEED @CORE One HF 0.8.json | 4 ++-- .../process/0.30mm STRUCTURAL @CORE One HF 0.8.json | 7 +++---- .../Prusa/process/0.32mm SPEED @CORE One 0.6.json | 4 ++-- .../Prusa/process/0.32mm SPEED @CORE One HF 0.5.json | 2 +- .../Prusa/process/0.32mm SPEED @CORE One HF 0.6.json | 9 ++++----- .../Prusa/process/0.32mm STRUCTURAL @CORE One 0.6.json | 2 +- .../process/0.32mm STRUCTURAL @CORE One HF 0.5.json | 2 +- .../process/0.32mm STRUCTURAL @CORE One HF 0.6.json | 2 +- .../Prusa/process/0.40mm QUALITY @CORE One 0.8.json | 4 ++-- .../Prusa/process/0.40mm SPEED @CORE One HF 0.6.json | 9 ++++----- .../Prusa/process/0.40mm SPEED @CORE One HF 0.8.json | 8 +++++--- .../process/0.40mm STRUCTURAL @CORE One HF 0.6.json | 2 +- .../process/0.40mm STRUCTURAL @CORE One HF 0.8.json | 7 +++---- .../Prusa/process/0.55mm DRAFT @CORE One 0.8.json | 5 +++-- .../Prusa/process/0.55mm SPEED @CORE One HF 0.8.json | 4 ++-- 54 files changed, 152 insertions(+), 98 deletions(-) diff --git a/resources/profiles/Prusa/process/0.05mm DETAIL @CORE One 0.25.json b/resources/profiles/Prusa/process/0.05mm DETAIL @CORE One 0.25.json index 90282356ee..5a5e94e124 100644 --- a/resources/profiles/Prusa/process/0.05mm DETAIL @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.05mm DETAIL @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "gap_infill_speed": "45", + "small_perimeter_speed": "45", + "outer_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.07mm DETAIL @CORE One 0.25.json b/resources/profiles/Prusa/process/0.07mm DETAIL @CORE One 0.25.json index aa1fb6b9f7..cda4e3096b 100644 --- a/resources/profiles/Prusa/process/0.07mm DETAIL @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.07mm DETAIL @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "gap_infill_speed": "45", + "small_perimeter_speed": "45", + "outer_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.10mm FAST DETAIL @CORE One 0.4.json b/resources/profiles/Prusa/process/0.10mm FAST DETAIL @CORE One 0.4.json index d481f3139d..b2c2ca9528 100644 --- a/resources/profiles/Prusa/process/0.10mm FAST DETAIL @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.10mm FAST DETAIL @CORE One 0.4.json @@ -13,5 +13,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "100", "initial_layer_speed": "45", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4", + "small_perimeter_speed": "145", + "inner_wall_speed": "145", + "outer_wall_speed": "145" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.10mm STRUCTURAL @CORE One 0.5.json b/resources/profiles/Prusa/process/0.10mm STRUCTURAL @CORE One 0.5.json index f5f6a460b0..df335dbe67 100644 --- a/resources/profiles/Prusa/process/0.10mm STRUCTURAL @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.10mm STRUCTURAL @CORE One 0.5.json @@ -4,9 +4,9 @@ "inherits": "0.10mm STRUCTURAL @MK4S 0.5", "from": "system", "instantiation": "true", - "inner_wall_speed": "80", - "small_perimeter_speed": "45", - "outer_wall_speed": "45", + "inner_wall_speed": "70", + "small_perimeter_speed": "50", + "outer_wall_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.12mm SPEED @CORE One 0.25.json b/resources/profiles/Prusa/process/0.12mm SPEED @CORE One 0.25.json index 69ef541dae..3fc92e8b42 100644 --- a/resources/profiles/Prusa/process/0.12mm SPEED @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.12mm SPEED @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "small_perimeter_speed": "150", + "outer_wall_speed": "150", + "inner_wall_speed": "150" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.25.json b/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.25.json index a61d130cb5..ec754dc350 100644 --- a/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "gap_infill_speed": "45", + "small_perimeter_speed": "45", + "outer_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.3.json b/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.3.json index 35b0d2c525..101e7f0968 100644 --- a/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.3.json +++ b/resources/profiles/Prusa/process/0.12mm STRUCTURAL @CORE One 0.3.json @@ -12,5 +12,8 @@ "initial_layer_infill_speed": "60", "initial_layer_speed": "45", "top_surface_acceleration": "1500", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3", + "small_perimeter_speed": "45", + "inner_wall_speed": "70", + "outer_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.25.json b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.25.json index 8e5f0cab2d..4600a136a8 100644 --- a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "small_perimeter_speed": "150", + "inner_wall_speed": "150", + "outer_wall_speed": "150" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.4.json b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.4.json index 2c3b531050..e08b21a26f 100644 --- a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.15mm SPEED @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -16,5 +16,6 @@ "internal_solid_infill_acceleration": "6000", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "support_threshold_angle": "35" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One HF 0.4.json b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One HF 0.4.json index fa9fb8c30c..50ad496cd2 100644 --- a/resources/profiles/Prusa/process/0.15mm SPEED @CORE One HF 0.4.json +++ b/resources/profiles/Prusa/process/0.15mm SPEED @CORE One HF 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.15mm SPEED @MK4S HF0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_1_4_speed": "50", "overhang_3_4_speed": "60%", "sparse_infill_speed": "300", "travel_speed": "350", @@ -18,5 +18,6 @@ "internal_solid_infill_acceleration": "6000", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "support_threshold_angle": "35" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.25.json b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.25.json index 55e9dc654c..51886f189e 100644 --- a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.25.json +++ b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.25.json @@ -10,5 +10,8 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "45", "initial_layer_speed": "25", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.25", + "gap_infill_speed": "45", + "small_perimeter_speed": "45", + "outer_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.4.json b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.4.json index fd2d410e48..017b232df4 100644 --- a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.15mm STRUCTURAL @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "sparse_infill_speed": "120", "travel_speed": "350", "travel_acceleration": "7000", diff --git a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.5.json b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.5.json index 2cecda0dd0..765d0efa49 100644 --- a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.15mm STRUCTURAL @MK4S 0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.6.json b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.6.json index 2f58de84e9..0024001fd9 100644 --- a/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.15mm STRUCTURAL @CORE One 0.6.json @@ -4,9 +4,9 @@ "inherits": "0.15mm STRUCTURAL @MK4S 0.6", "from": "system", "instantiation": "true", - "inner_wall_speed": "80", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "inner_wall_speed": "70", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -18,5 +18,6 @@ "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.6", "inner_wall_acceleration": "2500", "outer_wall_acceleration": "1500", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "gap_infill_speed": "70" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.16mm SPEED @CORE One 0.3.json b/resources/profiles/Prusa/process/0.16mm SPEED @CORE One 0.3.json index d0ca7859df..15096ebd6b 100644 --- a/resources/profiles/Prusa/process/0.16mm SPEED @CORE One 0.3.json +++ b/resources/profiles/Prusa/process/0.16mm SPEED @CORE One 0.3.json @@ -13,5 +13,8 @@ "initial_layer_infill_speed": "60", "initial_layer_speed": "45", "top_surface_acceleration": "1500", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3", + "small_perimeter_speed": "160", + "inner_wall_speed": "160", + "outer_wall_speed": "160" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.16mm STRUCTURAL @CORE One 0.3.json b/resources/profiles/Prusa/process/0.16mm STRUCTURAL @CORE One 0.3.json index 192682e5b7..4e11371cfe 100644 --- a/resources/profiles/Prusa/process/0.16mm STRUCTURAL @CORE One 0.3.json +++ b/resources/profiles/Prusa/process/0.16mm STRUCTURAL @CORE One 0.3.json @@ -12,5 +12,8 @@ "initial_layer_infill_speed": "60", "initial_layer_speed": "45", "top_surface_acceleration": "1500", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3", + "small_perimeter_speed": "50", + "inner_wall_speed": "70", + "outer_wall_speed": "50" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SOLUBLE FULL @CORE One 0.4.json b/resources/profiles/Prusa/process/0.20mm SOLUBLE FULL @CORE One 0.4.json index 3fe89b38a6..7e0f0042c0 100644 --- a/resources/profiles/Prusa/process/0.20mm SOLUBLE FULL @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.20mm SOLUBLE FULL @CORE One 0.4.json @@ -4,12 +4,15 @@ "inherits": "0.20mm SOLUBLE FULL @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4 and printer_notes!~/.*HF_NOZZLE.*/", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", "support_interface_top_layers": "3", "initial_layer_infill_speed": "100", - "initial_layer_speed": "45" + "initial_layer_speed": "45", + "small_perimeter_speed": "50", + "inner_wall_speed": "70", + "outer_wall_speed": "50" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SOLUBLE INTERFACE @CORE One 0.4.json b/resources/profiles/Prusa/process/0.20mm SOLUBLE INTERFACE @CORE One 0.4.json index 49c4c28280..222663644c 100644 --- a/resources/profiles/Prusa/process/0.20mm SOLUBLE INTERFACE @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.20mm SOLUBLE INTERFACE @CORE One 0.4.json @@ -4,12 +4,15 @@ "inherits": "0.20mm SOLUBLE INTERFACE @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4 and printer_notes!~/.*HF_NOZZLE.*/", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", "support_interface_top_layers": "3", "initial_layer_infill_speed": "100", - "initial_layer_speed": "45" + "initial_layer_speed": "45", + "small_perimeter_speed": "50", + "inner_wall_speed": "70", + "outer_wall_speed": "50" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.3.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.3.json index df4d8e80cc..0f0cc78362 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.3.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.3.json @@ -13,5 +13,8 @@ "initial_layer_infill_speed": "60", "initial_layer_speed": "45", "top_surface_acceleration": "1500", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3", + "small_perimeter_speed": "160", + "inner_wall_speed": "160", + "outer_wall_speed": "160" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.4.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.4.json index 9171ec4b21..79cd06680f 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.20mm SPEED @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -16,5 +16,6 @@ "internal_solid_infill_acceleration": "6000", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "support_threshold_angle": "35" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.5.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.5.json index e7299809ea..20d64e324c 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.20mm SPEED @MK4S 0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.6.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.6.json index 78446c1687..1bbd442a02 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One 0.6.json @@ -4,8 +4,8 @@ "inherits": "0.20mm SPEED @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -17,5 +17,8 @@ "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.6 and printer_notes!~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "small_perimeter_speed": "130", + "inner_wall_speed": "130", + "outer_wall_speed": "130" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.4.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.4.json index 96433e26e8..5b9b42f34c 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.4.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.4.json @@ -4,8 +4,8 @@ "inherits": "0.20mm SPEED @MK4S HF0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", - "overhang_3_4_speed": "60%", + "overhang_3_4_speed": "50", + "overhang_4_4_speed": "70%", "sparse_infill_speed": "300", "travel_speed": "350", "travel_acceleration": "7000", @@ -18,5 +18,6 @@ "internal_solid_infill_acceleration": "6000", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "support_threshold_angle": "35" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.5.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.5.json index 3ad26d4548..c7324713ea 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.5.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.20mm SPEED @MK4S HF0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.6.json index 204f356661..8cb0eb8f1c 100644 --- a/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.20mm SPEED @CORE One HF 0.6.json @@ -4,8 +4,8 @@ "inherits": "0.20mm SPEED @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.3.json b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.3.json index e7dd110d1d..d9b1a2ef54 100644 --- a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.3.json +++ b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.3.json @@ -12,5 +12,8 @@ "initial_layer_infill_speed": "60", "initial_layer_speed": "45", "top_surface_acceleration": "1500", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.3", + "small_perimeter_speed": "50", + "inner_wall_speed": "70", + "outer_wall_speed": "50" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.4.json b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.4.json index 95d97fea4e..a139f2cd4f 100644 --- a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.4.json +++ b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.20mm STRUCTURAL @MK4S 0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.5.json b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.5.json index c6fba65551..57c2968e0d 100644 --- a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.20mm STRUCTURAL @MK4S 0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.6.json b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.6.json index 5445f967b5..9bbd5097c8 100644 --- a/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.20mm STRUCTURAL @CORE One 0.6.json @@ -4,7 +4,7 @@ "inherits": "0.20mm STRUCTURAL @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", + "overhang_3_4_speed": "30", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.5.json b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.5.json index bfe931bc62..cb087eb345 100644 --- a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.25mm SPEED @MK4S 0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.6.json b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.6.json index 4cd0500e7b..621c94e9d8 100644 --- a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One 0.6.json @@ -4,8 +4,8 @@ "inherits": "0.25mm SPEED @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -17,5 +17,8 @@ "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.6 and printer_notes!~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "small_perimeter_speed": "75", + "inner_wall_speed": "95", + "outer_wall_speed": "75" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.4.json b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.4.json index b0b066e261..634c502f73 100644 --- a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.4.json +++ b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.4.json @@ -4,8 +4,8 @@ "inherits": "0.25mm SPEED @MK4S HF0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", - "overhang_3_4_speed": "60%", + "overhang_3_4_speed": "50", + "overhang_4_4_speed": "70%", "sparse_infill_speed": "300", "travel_speed": "350", "travel_acceleration": "7000", @@ -13,10 +13,11 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "100", "initial_layer_speed": "45", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4 and printer_notes=~/.*HF_NOZZLE.*/", +"compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.4 and printer_notes=~/.*HF_NOZZLE.*/", "sparse_infill_acceleration": "7000", "internal_solid_infill_acceleration": "6000", "inner_wall_acceleration": "6000", "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "top_surface_acceleration": "2000", + "support_threshold_angle": "35" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.5.json b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.5.json index 20634c06e1..268891fb46 100644 --- a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.5.json +++ b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.25mm SPEED @MK4S HF0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.6.json index 493f82b29b..bb26e69f5d 100644 --- a/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.25mm SPEED @CORE One HF 0.6.json @@ -4,8 +4,8 @@ "inherits": "0.25mm SPEED @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.5.json b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.5.json index a89610e3ee..c4d22efeb2 100644 --- a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.5.json +++ b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.25mm STRUCTURAL @MK4S 0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.6.json b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.6.json index 5418273bb2..96a614266d 100644 --- a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One 0.6.json @@ -4,7 +4,7 @@ "inherits": "0.25mm STRUCTURAL @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", + "overhang_3_4_speed": "30", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One HF 0.4.json b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One HF 0.4.json index 6392a2c0f7..978f3f94d0 100644 --- a/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One HF 0.4.json +++ b/resources/profiles/Prusa/process/0.25mm STRUCTURAL @CORE One HF 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.25mm STRUCTURAL @MK4S HF0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.28mm DRAFT @CORE One HF 0.4.json b/resources/profiles/Prusa/process/0.28mm DRAFT @CORE One HF 0.4.json index a1f896b3c0..e493e19467 100644 --- a/resources/profiles/Prusa/process/0.28mm DRAFT @CORE One HF 0.4.json +++ b/resources/profiles/Prusa/process/0.28mm DRAFT @CORE One HF 0.4.json @@ -4,7 +4,7 @@ "inherits": "0.28mm DRAFT @MK4S HF0.4", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "support_threshold_angle": "35", "outer_wall_acceleration": "3000", "inner_wall_acceleration": "6000", diff --git a/resources/profiles/Prusa/process/0.30mm DETAIL @CORE One 0.8.json b/resources/profiles/Prusa/process/0.30mm DETAIL @CORE One 0.8.json index 0ecac72e60..db88957c69 100644 --- a/resources/profiles/Prusa/process/0.30mm DETAIL @CORE One 0.8.json +++ b/resources/profiles/Prusa/process/0.30mm DETAIL @CORE One 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.30mm DETAIL @MK4S 0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", - "top_surface_speed": "2000", + "overhang_3_4_speed": "35", + "top_surface_acceleration": "2000", "inner_wall_acceleration": "2500", "internal_solid_infill_acceleration": "5000", "sparse_infill_acceleration": "7000", @@ -15,5 +15,6 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "55", "initial_layer_speed": "45", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes!~/.*HF_NOZZLE.*/" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes!~/.*HF_NOZZLE.*/", + "gap_infill_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.30mm SPEED @CORE One HF 0.8.json b/resources/profiles/Prusa/process/0.30mm SPEED @CORE One HF 0.8.json index 8477a7c0f9..d4be25be9a 100644 --- a/resources/profiles/Prusa/process/0.30mm SPEED @CORE One HF 0.8.json +++ b/resources/profiles/Prusa/process/0.30mm SPEED @CORE One HF 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.30mm SPEED @MK4S HF0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", - "top_surface_speed": "2000", + "overhang_3_4_speed": "45", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.30mm STRUCTURAL @CORE One HF 0.8.json b/resources/profiles/Prusa/process/0.30mm STRUCTURAL @CORE One HF 0.8.json index d8cb0916af..7426aa3a21 100644 --- a/resources/profiles/Prusa/process/0.30mm STRUCTURAL @CORE One HF 0.8.json +++ b/resources/profiles/Prusa/process/0.30mm STRUCTURAL @CORE One HF 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.30mm STRUCTURAL @MK4S HF0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "40", - "top_surface_speed": "2000", + "overhang_3_4_speed": "40", + "top_surface_acceleration": "2000", "support_speed": "100", "support_interface_speed": "55%", "travel_speed": "350", @@ -18,6 +18,5 @@ "sparse_infill_acceleration": "6000", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes=~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "2500", - "outer_wall_acceleration": "1500", - "top_surface_acceleration": "2000" + "outer_wall_acceleration": "1500" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One 0.6.json b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One 0.6.json index 549b62c466..8b4b7511b1 100644 --- a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One 0.6.json @@ -4,8 +4,8 @@ "inherits": "0.32mm SPEED @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", - "overhang_3_4_speed": "70%", + "overhang_3_4_speed": "30", + "overhang_4_4_speed": "70%", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.5.json b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.5.json index 1471abb700..55594a5dd2 100644 --- a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.5.json +++ b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.32mm SPEED @MK4S HF0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "50", + "overhang_3_4_speed": "50", "support_interface_speed": "50%", "travel_speed": "350", "travel_acceleration": "7000", diff --git a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.6.json index e9bde33023..533da07e95 100644 --- a/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.32mm SPEED @CORE One HF 0.6.json @@ -4,9 +4,9 @@ "inherits": "0.32mm SPEED @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", - "overhang_3_4_speed": "70%", - "top_surface_speed": "2000", + "overhang_3_4_speed": "35", + "overhang_4_4_speed": "70%", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -17,6 +17,5 @@ "sparse_infill_acceleration": "7000", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.6 and printer_notes=~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "6000", - "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "outer_wall_acceleration": "3000" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One 0.6.json b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One 0.6.json index e52aa90a5f..a652b7097c 100644 --- a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One 0.6.json +++ b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One 0.6.json @@ -4,7 +4,7 @@ "inherits": "0.32mm STRUCTURAL @MK4S 0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "30", + "overhang_3_4_speed": "30", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.5.json b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.5.json index a1f851d518..7fb4500b02 100644 --- a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.5.json +++ b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.5.json @@ -4,7 +4,7 @@ "inherits": "0.32mm STRUCTURAL @MK4S HF0.5", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", + "overhang_3_4_speed": "45", "support_speed": "120", "support_interface_speed": "50%", "travel_speed": "350", diff --git a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.6.json index 2a3f2ce950..887768ee8e 100644 --- a/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.32mm STRUCTURAL @CORE One HF 0.6.json @@ -4,7 +4,7 @@ "inherits": "0.32mm STRUCTURAL @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", + "overhang_3_4_speed": "35", "support_speed": "110", "support_interface_speed": "50%", "travel_speed": "350", diff --git a/resources/profiles/Prusa/process/0.40mm QUALITY @CORE One 0.8.json b/resources/profiles/Prusa/process/0.40mm QUALITY @CORE One 0.8.json index 4567cd1dd7..a92c5eb3dd 100644 --- a/resources/profiles/Prusa/process/0.40mm QUALITY @CORE One 0.8.json +++ b/resources/profiles/Prusa/process/0.40mm QUALITY @CORE One 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.40mm QUALITY @MK4S 0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", - "top_surface_speed": "2000", + "overhang_3_4_speed": "35", + "top_surface_acceleration": "2000", "inner_wall_acceleration": "2500", "internal_solid_infill_acceleration": "5000", "sparse_infill_acceleration": "7000", diff --git a/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.6.json index e0b870c9ad..bb913bcabd 100644 --- a/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.6.json @@ -4,9 +4,9 @@ "inherits": "0.40mm SPEED @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", - "overhang_3_4_speed": "70%", - "top_surface_speed": "2000", + "overhang_3_4_speed": "35", + "overhang_4_4_speed": "70%", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -17,6 +17,5 @@ "sparse_infill_acceleration": "7000", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.6 and printer_notes=~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "6000", - "outer_wall_acceleration": "3000", - "top_surface_acceleration": "2000" + "outer_wall_acceleration": "3000" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.8.json b/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.8.json index 142556619a..7e6f2c156c 100644 --- a/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.8.json +++ b/resources/profiles/Prusa/process/0.40mm SPEED @CORE One HF 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.40mm SPEED @MK4S HF0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", - "top_surface_speed": "2000", + "overhang_3_4_speed": "45", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -14,5 +14,7 @@ "initial_layer_speed": "45", "internal_solid_infill_acceleration": "5000", "sparse_infill_acceleration": "7000", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes=~/.*HF_NOZZLE.*/" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes=~/.*HF_NOZZLE.*/", + "small_perimeter_speed": "85", + "outer_wall_speed": "85" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.6.json b/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.6.json index adfba858f2..fe8697d887 100644 --- a/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.6.json +++ b/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.6.json @@ -4,7 +4,7 @@ "inherits": "0.40mm STRUCTURAL @MK4S HF0.6", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "35", + "overhang_3_4_speed": "35", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", diff --git a/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.8.json b/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.8.json index e651c26ce3..6fbe39f6ba 100644 --- a/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.8.json +++ b/resources/profiles/Prusa/process/0.40mm STRUCTURAL @CORE One HF 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.40mm STRUCTURAL @MK4S HF0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "40", - "top_surface_speed": "2000", + "overhang_3_4_speed": "40", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", @@ -16,6 +16,5 @@ "sparse_infill_acceleration": "6000", "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes=~/.*HF_NOZZLE.*/", "inner_wall_acceleration": "2500", - "outer_wall_acceleration": "1500", - "top_surface_acceleration": "2000" + "outer_wall_acceleration": "1500" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.55mm DRAFT @CORE One 0.8.json b/resources/profiles/Prusa/process/0.55mm DRAFT @CORE One 0.8.json index 6037cbdbda..5d350f3738 100644 --- a/resources/profiles/Prusa/process/0.55mm DRAFT @CORE One 0.8.json +++ b/resources/profiles/Prusa/process/0.55mm DRAFT @CORE One 0.8.json @@ -4,7 +4,7 @@ "inherits": "0.55mm DRAFT @MK4S 0.8", "from": "system", "instantiation": "true", - "top_surface_speed": "2000", + "top_surface_acceleration": "2000", "inner_wall_acceleration": "2500", "internal_solid_infill_acceleration": "5000", "sparse_infill_acceleration": "7000", @@ -14,5 +14,6 @@ "support_interface_top_layers": "3", "initial_layer_infill_speed": "55", "initial_layer_speed": "45", - "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes!~/.*HF_NOZZLE.*/" + "compatible_printers_condition": "printer_notes=~/.*PRINTER_MODEL_COREONE.*/ and nozzle_diameter[0]==0.8 and printer_notes!~/.*HF_NOZZLE.*/", + "inner_wall_speed": "45" } \ No newline at end of file diff --git a/resources/profiles/Prusa/process/0.55mm SPEED @CORE One HF 0.8.json b/resources/profiles/Prusa/process/0.55mm SPEED @CORE One HF 0.8.json index 11b159f114..f9270671a2 100644 --- a/resources/profiles/Prusa/process/0.55mm SPEED @CORE One HF 0.8.json +++ b/resources/profiles/Prusa/process/0.55mm SPEED @CORE One HF 0.8.json @@ -4,8 +4,8 @@ "inherits": "0.55mm SPEED @MK4S HF0.8", "from": "system", "instantiation": "true", - "overhang_2_4_speed": "45", - "top_surface_speed": "2000", + "overhang_3_4_speed": "45", + "top_surface_acceleration": "2000", "travel_speed": "350", "travel_acceleration": "7000", "default_acceleration": "3000", From 3c47b60063cce89c25de1437e13436bb29399c6b Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 23 Dec 2025 19:48:21 +0800 Subject: [PATCH 4/8] fix a build error --- src/libslic3r/GCode.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index eae1d1711a..707dadd9f9 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6188,7 +6188,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // if still in avoidance mode and under "max", adjust speed: // - speeds in lower half of range: clamp down to "min" - // - speeds in upper half of range: boost up to "max" if (m_resonance_avoidance && speed < m_config.max_resonance_avoidance_speed.value) { + // - speeds in upper half of range: boost up to "max" + if (m_resonance_avoidance && speed < m_config.max_resonance_avoidance_speed.value) { if (speed < m_config.min_resonance_avoidance_speed.value + ((m_config.max_resonance_avoidance_speed.value - m_config.min_resonance_avoidance_speed.value) / 2)) { speed = std::min(speed, m_config.min_resonance_avoidance_speed.value); From 0aac0478e769af0e016cad2f9c1f9a0df93720f1 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Tue, 23 Dec 2025 23:44:43 +0800 Subject: [PATCH 5/8] GCode Macro: Fix placeholder parser bugs and enable tests (#11485) * Support creating vector variable * Add tests for placeholder parser variables * Fix placeholder line width substitution & tests * Enable PlaceholderParser tests * fix build errors --------- Co-authored-by: SoftFever --- scripts/run_unit_tests.sh | 2 +- src/libslic3r/PlaceholderParser.cpp | 13 +- tests/libslic3r/test_placeholder_parser.cpp | 176 +++++++++++++++++--- 3 files changed, 157 insertions(+), 34 deletions(-) diff --git a/scripts/run_unit_tests.sh b/scripts/run_unit_tests.sh index 081467b300..292c6c9d3f 100755 --- a/scripts/run_unit_tests.sh +++ b/scripts/run_unit_tests.sh @@ -9,4 +9,4 @@ ROOT_DIR="$(dirname "$0")/.." cd "${ROOT_DIR}" || exit 1 -ctest --test-dir build/tests --output-junit "$(pwd)/ctest_results.xml" --output-on-failure -j +ctest --test-dir build/tests -L "Http|PlaceholderParser" --output-junit "$(pwd)/ctest_results.xml" --output-on-failure -j diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 92e4210f3c..f03a5cee38 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -1045,8 +1045,8 @@ namespace client case coFloatOrPercent: { std::string opt_key(opt.it_range.begin(), opt.it_range.end()); - if (boost::ends_with(opt_key, "extrusion_width")) { - // Extrusion width supports defaults and a complex graph of dependencies. + if (boost::ends_with(opt_key, "line_width")) { + // Line width supports defaults and a complex graph of dependencies. output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast(ctx->current_extruder_id))); } else if (! static_cast(opt.opt)->percent) { // Not a percent, just return the value. @@ -1060,8 +1060,8 @@ namespace client const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over); if (opt_parent == nullptr) ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range); - if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) { - // Extrusion width supports defaults and a complex graph of dependencies. + if (boost::ends_with(opt_def->ratio_over, "line_width")) { + // Line width supports defaults and a complex graph of dependencies. assert(opt_parent->type() == coFloatOrPercent); v *= Flow::extrusion_width(opt_def->ratio_over, static_cast(opt_parent), *ctx, static_cast(ctx->current_extruder_id)); break; @@ -2197,9 +2197,8 @@ namespace client initializer_list(_r1)[px::bind(&MyContext::vector_variable_new_from_initializer_list, _r1, _a, _b, _1)] // Process it before conditional_expression, as conditional_expression requires a vector reference to be augmented with an index. // Only process such variable references, which return a naked vector variable. - // Orca todo: following code cause strange build errors with MSVC C++17 - // | eps(px::bind(&MyContext::could_be_vector_variable_reference, _b)) >> - // variable_reference(_r1)[px::val(qi::_pass) = px::bind(&MyContext::vector_variable_new_from_copy, _r1, _a, _b, _1)] + | eps(px::bind(&MyContext::could_be_vector_variable_reference, _b)) >> + variable_reference(_r1)[qi::_pass = px::bind(&MyContext::vector_variable_new_from_copy, _r1, _a, _b, _1)] // Would NOT consume '(' conditional_expression ')' because such value was consumed with the expression above. | conditional_expression(_r1) [px::bind(&MyContext::scalar_variable_new_from_scalar_expression, _r1, _a, _b, _1)] diff --git a/tests/libslic3r/test_placeholder_parser.cpp b/tests/libslic3r/test_placeholder_parser.cpp index 2394aad4bf..93c848b3a2 100644 --- a/tests/libslic3r/test_placeholder_parser.cpp +++ b/tests/libslic3r/test_placeholder_parser.cpp @@ -14,40 +14,22 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { { "nozzle_diameter", "0.6;0.6;0.6;0.6" }, { "nozzle_temperature", "357;359;363;378" } }); - // To let the PlaceholderParser throw when referencing initial_layer_line_width if it is set to percent, as the PlaceholderParser does not know + // To test the "min_width_top_surface" over "inner_wall_line_width". + config.option("inner_wall_line_width")->value = 150.; + config.option("inner_wall_line_width")->percent = true; + // To let the PlaceholderParser throw when referencing scarf_joint_speed if it is set to percent, as the PlaceholderParser does not know // a percent to what. - config.option("initial_layer_line_width")->value = 50.; - config.option("initial_layer_line_width")->percent = true; + config.option("scarf_joint_speed")->value = 50.; + config.option("scarf_joint_speed")->percent = true; parser.apply_config(config); parser.set("foo", 0); parser.set("bar", 2); parser.set("num_extruders", 4); - SECTION("nested config options (legacy syntax)") { REQUIRE(parser.process("[nozzle_temperature_[foo]]") == "357"); } + SECTION("nested config options (legacy syntax)") { REQUIRE(parser.process("[nozzle_temperature[foo]]") == "357"); } SECTION("array reference") { REQUIRE(parser.process("{nozzle_temperature[foo]}") == "357"); } - SECTION("whitespaces and newlines are maintained") { REQUIRE(parser.process("test [ nozzle_temperature_ [foo] ] \n hu") == "test 357 \n hu"); } - - // Test the "coFloatOrPercent" and "xxx_width" substitutions. - - // FIXME: Don't know what exactly this referred to in Prusaslicer or - // whether it should apply to Orca or not. - // {outer_wall_line_width} returns as its default value, 0. - // SECTION("outer_wall_line_width") { REQUIRE(std::stod(parser.process("{outer_wall_line_width}")) == Catch::Approx(0.67500001192092896)); } - SECTION("support_object_xy_distance") { REQUIRE(std::stod(parser.process("{support_object_xy_distance}")) == Catch::Approx(0.35)); } - // initial_layer_line_width ratio over nozzle_diameter. - // FIXME: either something else which correctly calculates a ratio should be here, - // or something else should be found for for the REQUIRE_THROWS - // SECTION("initial_layer_line_width") { REQUIRE(std::stod(parser.process("{initial_layer_line_width}")) == Catch::Approx(0.9)); } - // small_perimeter_speed ratio over outer_wall_speed - SECTION("small_perimeter_speed") { REQUIRE(std::stod(parser.process("{small_perimeter_speed}")) == Catch::Approx(30.)); } - // infill_wall_overlap over inner_wall_line_width - // FIXME: Shouldn't this return the calculated value and not the percentage 15? - // SECTION("infill_wall_overlap") { REQUIRE(std::stod(parser.process("{infill_wall_overlap}")) == Catch::Approx(0.16875)); } - - // If initial_layer_line_width is set to percent, then it is applied over respective extrusion types by overriding their respective speeds. - // The PlaceholderParser has no way to know which extrusion type the caller has in mind, therefore it throws. - SECTION("initial_layer_line_width throws failed to resolve the ratio_over dependencies") { REQUIRE_THROWS(parser.process("{initial_layer_line_width}")); } + SECTION("whitespaces and newlines are maintained") { REQUIRE(parser.process("test [ nozzle_temperature [foo] ] \n hu") == "test 357 \n hu"); } // Test the math expressions. SECTION("math: 2*3") { REQUIRE(parser.process("{2*3}") == "6"); } @@ -84,6 +66,20 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(13.)); } SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(20.)); } + // Test the "coFloatOrPercent" and "xxx_line_width" substitutions. + // min_width_top_surface ratio_over inner_wall_line_width. + SECTION("line_width") { REQUIRE(std::stod(parser.process("{line_width}")) == Catch::Approx(0.67500001192092896)); } + SECTION("min_width_top_surface") { REQUIRE(std::stod(parser.process("{min_width_top_surface}")) == Catch::Approx(2.7)); } + // Orca: this one is not coFloatOrPercent + //SECTION("support_object_xy_distance") { REQUIRE(std::stod(parser.process("{support_object_xy_distance}")) == Catch::Approx(0.3375)); } + // small_perimeter_speed over outer_wall_speed + SECTION("small_perimeter_speed") { REQUIRE(std::stod(parser.process("{small_perimeter_speed}")) == Catch::Approx(30.)); } + // infill_anchor over sparse_infill_line_width + SECTION("infill_anchor") { REQUIRE(std::stod(parser.process("{infill_anchor}")) == Catch::Approx(2.7)); } + // If scarf_joint_speed is set to percent, then it is applied over respective extrusion types by overriding their respective speeds. + // The PlaceholderParser has no way to know which extrusion type the caller has in mind, therefore it throws. + SECTION("scarf_joint_speed") { REQUIRE_THROWS(parser.process("{scarf_joint_speed}")); } + // Test the boolean expression parser. auto boolean_expression = [&parser](const std::string& templ) { return parser.evaluate_boolean_expression(templ, parser.config()); }; @@ -116,3 +112,131 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { SECTION("complex expression2") { REQUIRE(boolean_expression("printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.6 and num_extruders>1)")); } SECTION("complex expression3") { REQUIRE(! boolean_expression("printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.3 and num_extruders>1)")); } } + +SCENARIO("Placeholder parser variables", "[PlaceholderParser]") { + PlaceholderParser parser; + auto config = DynamicPrintConfig::full_print_config(); + + config.set_deserialize_strict({ + { "filament_notes", "testnotes" }, + { "enable_pressure_advance", "1" }, + { "nozzle_diameter", "0.6;0.6;0.6;0.6" }, + { "nozzle_temperature", "357;359;363;378" } + }); + + PlaceholderParser::ContextData context_with_global_dict; + context_with_global_dict.global_config = std::make_unique(); + + SECTION("create an int local variable") { REQUIRE(parser.process("{local myint = 33+2}{myint}", 0, nullptr, nullptr, nullptr) == "35"); } + SECTION("create a string local variable") { REQUIRE(parser.process("{local mystr = \"mine\" + \"only\" + \"mine\"}{mystr}", 0, nullptr, nullptr, nullptr) == "mineonlymine"); } + SECTION("create a bool local variable") { REQUIRE(parser.process("{local mybool = 1 + 1 == 2}{mybool}", 0, nullptr, nullptr, nullptr) == "true"); } + SECTION("create an int global variable") { REQUIRE(parser.process("{global myint = 33+2}{myint}", 0, nullptr, nullptr, &context_with_global_dict) == "35"); } + SECTION("create a string global variable") { REQUIRE(parser.process("{global mystr = \"mine\" + \"only\" + \"mine\"}{mystr}", 0, nullptr, nullptr, &context_with_global_dict) == "mineonlymine"); } + SECTION("create a bool global variable") { REQUIRE(parser.process("{global mybool = 1 + 1 == 2}{mybool}", 0, nullptr, nullptr, &context_with_global_dict) == "true"); } + + SECTION("create an int local variable and overwrite it") { REQUIRE(parser.process("{local myint = 33+2}{myint = 12}{myint}", 0, nullptr, nullptr, nullptr) == "12"); } + SECTION("create a string local variable and overwrite it") { REQUIRE(parser.process("{local mystr = \"mine\" + \"only\" + \"mine\"}{mystr = \"yours\"}{mystr}", 0, nullptr, nullptr, nullptr) == "yours"); } + SECTION("create a bool local variable and overwrite it") { REQUIRE(parser.process("{local mybool = 1 + 1 == 2}{mybool = false}{mybool}", 0, nullptr, nullptr, nullptr) == "false"); } + SECTION("create an int global variable and overwrite it") { REQUIRE(parser.process("{global myint = 33+2}{myint = 12}{myint}", 0, nullptr, nullptr, &context_with_global_dict) == "12"); } + SECTION("create a string global variable and overwrite it") { REQUIRE(parser.process("{global mystr = \"mine\" + \"only\" + \"mine\"}{mystr = \"yours\"}{mystr}", 0, nullptr, nullptr, &context_with_global_dict) == "yours"); } + SECTION("create a bool global variable and overwrite it") { REQUIRE(parser.process("{global mybool = 1 + 1 == 2}{mybool = false}{mybool}", 0, nullptr, nullptr, &context_with_global_dict) == "false"); } + + SECTION("create an int local variable and redefine it") { REQUIRE(parser.process("{local myint = 33+2}{local myint = 12}{myint}", 0, nullptr, nullptr, nullptr) == "12"); } + SECTION("create a string local variable and redefine it") { REQUIRE(parser.process("{local mystr = \"mine\" + \"only\" + \"mine\"}{local mystr = \"yours\"}{mystr}", 0, nullptr, nullptr, nullptr) == "yours"); } + SECTION("create a bool local variable and redefine it") { REQUIRE(parser.process("{local mybool = 1 + 1 == 2}{local mybool = false}{mybool}", 0, nullptr, nullptr, nullptr) == "false"); } + SECTION("create an int global variable and redefine it") { REQUIRE(parser.process("{global myint = 33+2}{global myint = 12}{myint}", 0, nullptr, nullptr, &context_with_global_dict) == "12"); } + SECTION("create a string global variable and redefine it") { REQUIRE(parser.process("{global mystr = \"mine\" + \"only\" + \"mine\"}{global mystr = \"yours\"}{mystr}", 0, nullptr, nullptr, &context_with_global_dict) == "yours"); } + SECTION("create a bool global variable and redefine it") { REQUIRE(parser.process("{global mybool = 1 + 1 == 2}{global mybool = false}{mybool}", 0, nullptr, nullptr, &context_with_global_dict) == "false"); } + + SECTION("create an ints local variable with repeat()") { REQUIRE(parser.process("{local myint = repeat(2*3, 4*6)}{myint[5]}", 0, nullptr, nullptr, nullptr) == "24"); } + SECTION("create a strings local variable with repeat()") { REQUIRE(parser.process("{local mystr = repeat(2*3, \"mine\" + \"only\" + \"mine\")}{mystr[5]}", 0, nullptr, nullptr, nullptr) == "mineonlymine"); } + SECTION("create a bools local variable with repeat()") { REQUIRE(parser.process("{local mybool = repeat(5, 1 + 1 == 2)}{mybool[4]}", 0, nullptr, nullptr, nullptr) == "true"); } + SECTION("create an ints global variable with repeat()") { REQUIRE(parser.process("{global myint = repeat(2*3, 4*6)}{myint[5]}", 0, nullptr, nullptr, &context_with_global_dict) == "24"); } + SECTION("create a strings global variable with repeat()") { REQUIRE(parser.process("{global mystr = repeat(2*3, \"mine\" + \"only\" + \"mine\")}{mystr[5]}", 0, nullptr, nullptr, &context_with_global_dict) == "mineonlymine"); } + SECTION("create a bools global variable with repeat()") { REQUIRE(parser.process("{global mybool = repeat(5, 1 + 1 == 2)}{mybool[4]}", 0, nullptr, nullptr, &context_with_global_dict) == "true"); } + + SECTION("create an ints local variable with initializer list") { REQUIRE(parser.process("{local myint = (2*3, 4*6, 5*5)}{myint[1]}", 0, nullptr, nullptr, nullptr) == "24"); } + SECTION("create a strings local variable with initializer list") { REQUIRE(parser.process("{local mystr = (2*3, \"mine\" + \"only\" + \"mine\", 8)}{mystr[1]}", 0, nullptr, nullptr, nullptr) == "mineonlymine"); } + SECTION("create a bools local variable with initializer list") { REQUIRE(parser.process("{local mybool = (3*3 == 8, 1 + 1 == 2)}{mybool[1]}", 0, nullptr, nullptr, nullptr) == "true"); } + SECTION("create an ints global variable with initializer list") { REQUIRE(parser.process("{global myint = (2*3, 4*6, 5*5)}{myint[1]}", 0, nullptr, nullptr, &context_with_global_dict) == "24"); } + SECTION("create a strings global variable with initializer list") { REQUIRE(parser.process("{global mystr = (2*3, \"mine\" + \"only\" + \"mine\", 8)}{mystr[1]}", 0, nullptr, nullptr, &context_with_global_dict) == "mineonlymine"); } + SECTION("create a bools global variable with initializer list") { REQUIRE(parser.process("{global mybool = (2*3 == 8, 1 + 1 == 2, 5*5 != 33)}{mybool[1]}", 0, nullptr, nullptr, &context_with_global_dict) == "true"); } + + SECTION("create an ints local variable by a copy") { REQUIRE(parser.process("{local myint = nozzle_temperature}{myint[0]}", 0, &config, nullptr, nullptr) == "357"); } + SECTION("create a strings local variable by a copy") { REQUIRE(parser.process("{local mystr = filament_notes}{mystr[0]}", 0, &config, nullptr, nullptr) == "testnotes"); } + SECTION("create a bools local variable by a copy") { REQUIRE(parser.process("{local mybool = enable_pressure_advance}{mybool[0]}", 0, &config, nullptr, nullptr) == "true"); } + SECTION("create an ints global variable by a copy") { REQUIRE(parser.process("{global myint = nozzle_temperature}{myint[0]}", 0, &config, nullptr, &context_with_global_dict) == "357"); } + SECTION("create a strings global variable by a copy") { REQUIRE(parser.process("{global mystr = filament_notes}{mystr[0]}", 0, &config, nullptr, &context_with_global_dict) == "testnotes"); } + SECTION("create a bools global variable by a copy") { REQUIRE(parser.process("{global mybool = enable_pressure_advance}{mybool[0]}", 0, &config, nullptr, &context_with_global_dict) == "true"); } + + SECTION("create an ints local variable by a copy and overwrite it") { + REQUIRE(parser.process("{local myint = nozzle_temperature}{myint = repeat(2*3, 4*6)}{myint[5]}", 0, &config, nullptr, nullptr) == "24"); + REQUIRE(parser.process("{local myint = nozzle_temperature}{myint = (2*3, 4*6)}{myint[1]}", 0, &config, nullptr, nullptr) == "24"); + REQUIRE(parser.process("{local myint = nozzle_temperature}{myint = (1)}{myint = nozzle_temperature}{myint[0]}", 0, &config, nullptr, nullptr) == "357"); + } + SECTION("create a strings local variable by a copy and overwrite it") { + REQUIRE(parser.process("{local mystr = filament_notes}{mystr = repeat(2*3, \"mine\" + \"only\" + \"mine\")}{mystr[5]}", 0, &config, nullptr, nullptr) == "mineonlymine"); + REQUIRE(parser.process("{local mystr = filament_notes}{mystr = (2*3, \"mine\" + \"only\" + \"mine\")}{mystr[1]}", 0, &config, nullptr, nullptr) == "mineonlymine"); + REQUIRE(parser.process("{local mystr = filament_notes}{mystr = (2*3, \"mine\" + \"only\" + \"mine\")}{mystr = filament_notes}{mystr[0]}", 0, &config, nullptr, nullptr) == "testnotes"); + } + SECTION("create a bools local variable by a copy and overwrite it") { + REQUIRE(parser.process("{local mybool = enable_pressure_advance}{mybool = repeat(2*3, true)}{mybool[5]}", 0, &config, nullptr, nullptr) == "true"); + REQUIRE(parser.process("{local mybool = enable_pressure_advance}{mybool = (false, true)}{mybool[1]}", 0, &config, nullptr, nullptr) == "true"); + REQUIRE(parser.process("{local mybool = enable_pressure_advance}{mybool = (false, false)}{mybool = enable_pressure_advance}{mybool[0]}", 0, &config, nullptr, nullptr) == "true"); + } + + SECTION("size() of a non-empty vector returns the right size") { REQUIRE(parser.process("{local myint = (0, 1, 2, 3)}{size(myint)}", 0, nullptr, nullptr, nullptr) == "4"); } + SECTION("size() of a an empty vector returns the right size") { REQUIRE(parser.process("{local myint = (0);myint=();size(myint)}", 0, nullptr, nullptr, nullptr) == "0"); } + SECTION("empty() of a non-empty vector returns false") { REQUIRE(parser.process("{local myint = (0, 1, 2, 3)}{empty(myint)}", 0, nullptr, nullptr, nullptr) == "false"); } + SECTION("empty() of a an empty vector returns true") { REQUIRE(parser.process("{local myint = (0);myint=();empty(myint)}", 0, nullptr, nullptr, nullptr) == "true"); } + + SECTION("nested if with new variables") { + std::string script = + "{if 1 == 1}{local myints = (5, 4, 3, 2, 1)}{else}{local myfloats = (1., 2., 3., 4., 5., 6., 7.)}{endif}" + "{myints[1]},{size(myints)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "4,5"); + } + SECTION("nested if with new variables 2") { + std::string script = + "{if 1 == 0}{local myints = (5, 4, 3, 2, 1)}{else}{local myfloats = (1., 2., 3., 4., 5., 6., 7.)}{endif}" + "{size(myfloats)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7"); + } + SECTION("nested if with new variables 2, mixing }{ with ;") { + std::string script = + "{if 1 == 0 then local myints = (5, 4, 3, 2, 1);else;local myfloats = (1., 2., 3., 4., 5., 6., 7.);endif}" + "{size(myfloats)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7"); + } + SECTION("nested if with new variables, two level") { + std::string script = + "{if 1 == 1}{if 2 == 3}{nejaka / haluz}{else}{local myints = (6, 5, 4, 3, 2, 1)}{endif}{else}{if zase * haluz}{else}{local myfloats = (1., 2., 3., 4., 5., 6., 7.)}{endif}{endif}" + "{size(myints)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6"); + } + SECTION("if with empty block and ;") { + std::string script = + "{if false then else;local myfloats = (1., 2., 3., 4., 5., 6., 7.);endif}" + "{size(myfloats)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7"); + } + SECTION("nested if with new variables, two level, mixing }{ with ;") { + std::string script = + "{if 1 == 1 then if 2 == 3}nejaka / haluz{else local myints = (6, 5, 4, 3, 2, 1) endif else if zase * haluz then else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif endif}" + "{size(myints)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6"); + } + SECTION("nested if with new variables, two level, mixing }{ with ; 2") { + std::string script = + "{if 1 == 1 then if 2 == 3 then nejaka / haluz else}{local myints = (6, 5, 4, 3, 2, 1)}{endif else if zase * haluz then else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif endif}" + "{size(myints)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6"); + } + SECTION("nested if with new variables, two level, mixing }{ with ; 3") { + std::string script = + "{if 1 == 1 then if 2 == 3 then nejaka / haluz else}{local myints = (6, 5, 4, 3, 2, 1)}{endif else}{if zase * haluz}{else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif}{endif}" + "{size(myints)}"; + REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6"); + } + SECTION("if else completely empty") { REQUIRE(parser.process("{if false then elsif false then else endif}", 0, nullptr, nullptr, nullptr) == ""); } +} From b1d659bad5829693ff42fc855a17490dff639e67 Mon Sep 17 00:00:00 2001 From: Kiss Lorand <50251547+kisslorand@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:06:29 +0200 Subject: [PATCH 6/8] FIX: Refresh filament setting overrides on preset change (#11712) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refresh filament setting overrides on preset change The filament “Setting Overrides” page derives its UI state from multiple configs (filament, printer, process), but this derived state was not recomputed during preset reloads. As a result, override widgets could reflect stale values until the page was revisited or a user interaction triggered an update. Recompute the filament setting overrides as part of TabFilament::reload_config(), keeping the derived UI in sync with the active preset immediately after reload. --- src/slic3r/GUI/Tab.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ab3a43ab4e..fd8ede92d2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -4143,6 +4143,9 @@ void TabFilament::reload_config() this->compatible_widget_reload(m_compatible_printers); this->compatible_widget_reload(m_compatible_prints); Tab::reload_config(); + + // Recompute derived override UI from the newly loaded config + update_filament_overrides_page(&m_preset_bundle->printers.get_edited_preset().config); } //void TabFilament::update_volumetric_flow_preset_hints() From a240478c306998def94fffdf4934be799d66acb8 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:43:14 +0100 Subject: [PATCH 7/8] make support speed visible independent of support state (#10916) --- src/slic3r/GUI/ConfigManipulation.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 60828cedcf..8254afda2d 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -774,10 +774,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co // Orca: Force solid support interface when using support ironing toggle_field("support_interface_spacing", have_support_material && have_support_interface && !has_support_ironing); - bool have_skirt_height = have_skirt && - (config->opt_int("skirt_height") > 1 || config->opt_enum("draft_shield") != dsEnabled); - toggle_line("support_speed", have_support_material || have_skirt_height); - toggle_line("support_interface_speed", have_support_material && have_support_interface); +// see issue #10915 +// bool have_skirt_height = have_skirt && +// (config->opt_int("skirt_height") > 1 || config->opt_enum("draft_shield") != dsEnabled); +// toggle_line("support_speed", have_support_material || have_skirt_height); +// toggle_line("support_interface_speed", have_support_material && have_support_interface); // BBS //toggle_field("support_material_synchronize_layers", have_support_soluble); From 506fde8f86fbf25bc4c445ef8f8d59966c7dc307 Mon Sep 17 00:00:00 2001 From: Rodrigo Faselli <162915171+RF47@users.noreply.github.com> Date: Tue, 23 Dec 2025 17:53:09 -0300 Subject: [PATCH 8/8] Clipper 2 multiline Infill (#11435) * Grid non-crossing for multiline cleaning Replaced negative offset logic with surface contraction to reduce overlap with perimeters. center the infill filltriangles update triangles preallocate memory Update FillRectilinear.cpp Update FillRectilinear.cpp overlapp adjustment Fix Crash Update FillRectilinear.cpp density tunning density tunning fine tunning reserve polilines Grid non-crossing for multiline Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com> Co-Authored-By: discip <53649486+discip@users.noreply.github.com> * Improve multiline fill offset and polyline closure Changed offset type from jtRound to jtMiter in multiline_fill for better geometry. Updated polyline conversion to require at least 3 points and ensured polylines are closed if not already. Updated FillGyroid, FillTpmsD, and FillTpmsFK to pass the 'close' argument to multiline_fill. cleaning FillAdaptive Noncross Only use clipper if worth it safeguard fix overlap Update FillRectilinear.cpp FilllRectilineal multiline clipper Update FillRectilinear.cpp FilllRectilineal multiline clipper Update FillRectilinear.cpp Update FillRectilinear.cpp fix 3d honeycomb Simplify polylines Update FillBase.cpp Update FillBase.cpp cleaning Improved Multiline Function This ensures `multiline_fill()` will correctly generate multiline infill with closed loop polylines if the input infill line is a closedloop polyline. This ensures that the multiline infill doesn't have little gaps or overlaps at the "closed point" of the original infill line. This changes how the tangent is calculated for the first and last points in a polyline if the first and last points are the same, making it a closed loop. Instead of just using the first or last line segment, it uses the line segment between the points before the last point and after the first point, the same way that all the other poly-line mid points are handled. It also uses eigen vector operations to calculate the points instead of explicitly calculating the x and y values. This is probably faster, and if not then it is at least more concise. Hibrid Multiline Function Update FillRectilinear.cpp Update FillRectilinear.cpp Update FillRectilinear.cpp Update FillRectilinear.cpp clipperutils multiline hibrido Update FillBase.cpp Update FillBase.cpp Update FillBase.cpp multiline hibrido arc tolerance multiline con union Update FillBase.cpp Update FillBase.cpp Update FillBase.cpp Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com> Co-Authored-By: Donovan Baarda * Switch multiline offset logic to Clipper2 Replaces Clipper-based multiline offset logic in FillBase.cpp with Clipper2, using InflatePaths and Union for offsetting and merging. Adds new conversion utilities in Clipper2Utils for handling Paths64 to Polygons/Polylines and updates headers accordingly. * Refactor multiline_fill to always use Clipper2 logic Removed the 'use_clipper' parameter from multiline_fill and updated all callers to use the new signature. The function now consistently applies Clipper2-based offset logic for multiline infill, simplifying the code and ensuring uniform behavior across fill patterns. * Change offset join type to Round in multiline_fill Replaces the Miter join type with Round in the InflatePaths call within multiline_fill. For smotther print travels. * Increase max infill multiline to 10 Raised the maximum allowed value for the 'Fill Multiline' infill parameter from 5 to 10 to support more lines in infill patterns. * Refactor multiline_fill to optimize offset logic Replaces manual conversion of polylines to Clipper2 paths with Slic3rPolylines_to_Paths64 and filters short paths using std::remove_if. Uses ClipperOffset for path inflation and streamlines merging and conversion to polylines, improving performance and code clarity. * half iteration because is bucle * Funciona 1 Refactored the multiline_fill function to streamline the insertion of center lines by directly checking for odd line counts and removing redundant logic. This improves code clarity and reduces unnecessary checks. * Refactor multiline_fill for improved offset logic Reworked the multiline_fill function to simplify and clarify the logic for generating multiple offset lines. The new implementation computes offsets more explicitly for odd and even cases, creates a fresh ClipperOffset for each band, and improves conversion between Clipper2 paths and polylines. This enhances maintainability and correctness of the multiline fill generation. * Quartercubic multiline * fillplanePath fix bounding box Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com> * fillconcentric multiline Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com> * Update FillBase.hpp * cleaning * Refactor multiline_fill to clean polylines and reuse offsetter Invalid polylines with less than two points are now removed before processing. The ClipperOffset object is created once and reused for each offset, improving efficiency and code clarity. trigger build * Optimize Filltrapezoidal Refactored the trapezoidal fill pattern generation to precompute base row templates and reuse them with vertical translation, reducing redundant computations and improving code clarity. This change enhances performance and maintainability by avoiding repeated construction of row patterns within loops. * Replace push_back with emplace_back for Polyline points Updated Polyline point insertion from push_back to emplace_back for efficiency and clarity. Also refactored row copying logic to avoid in-place modification, improving code readability and safety. * Update FillRectilinear.cpp * Reserve space for poliline points * Union not needed * Update FillRectilinear.cpp * unused functions * compactado Update FillRectilinear.cpp * Adjust minimum rows for better performance * Update FillRectilinear.cpp --------- Co-authored-by: Ian Bassi <12130714+ianalexis@users.noreply.github.com> Co-authored-by: discip <53649486+discip@users.noreply.github.com> Co-authored-by: Donovan Baarda Co-authored-by: Ian Bassi --- src/libslic3r/Clipper2Utils.cpp | 5 + src/libslic3r/Clipper2Utils.hpp | 3 + src/libslic3r/Fill/Fill3DHoneycomb.cpp | 4 + src/libslic3r/Fill/FillAdaptive.cpp | 45 ++-- src/libslic3r/Fill/FillBase.cpp | 108 ++++---- src/libslic3r/Fill/FillConcentric.cpp | 13 +- src/libslic3r/Fill/FillHoneycomb.cpp | 2 +- src/libslic3r/Fill/FillPlanePath.cpp | 12 +- src/libslic3r/Fill/FillRectilinear.cpp | 325 +++++++++++++++++++++++-- src/libslic3r/Fill/FillRectilinear.hpp | 1 + src/libslic3r/PrintConfig.cpp | 2 +- src/slic3r/GUI/ConfigManipulation.cpp | 4 +- 12 files changed, 428 insertions(+), 96 deletions(-) diff --git a/src/libslic3r/Clipper2Utils.cpp b/src/libslic3r/Clipper2Utils.cpp index 9f1f678a9c..12fd867500 100644 --- a/src/libslic3r/Clipper2Utils.cpp +++ b/src/libslic3r/Clipper2Utils.cpp @@ -35,6 +35,11 @@ Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const Container& in) return out; } +Clipper2Lib::Paths64 Slic3rPolylines_to_Paths64(const Polylines& in) +{ + return Slic3rPoints_to_Paths64(in); +} + Points Path64ToPoints(const Clipper2Lib::Path64& path64) { Points points; diff --git a/src/libslic3r/Clipper2Utils.hpp b/src/libslic3r/Clipper2Utils.hpp index c5485ad1bd..54b48d6bd7 100644 --- a/src/libslic3r/Clipper2Utils.hpp +++ b/src/libslic3r/Clipper2Utils.hpp @@ -4,9 +4,12 @@ #include "ExPolygon.hpp" #include "Polygon.hpp" #include "Polyline.hpp" +#include "clipper2/clipper.h" namespace Slic3r { +Clipper2Lib::Paths64 Slic3rPolylines_to_Paths64(const Slic3r::Polylines& in); +Slic3r::Polylines Paths64_to_polylines(const Clipper2Lib::Paths64& in); Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip); Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip); ExPolygons union_ex_2(const Polygons &expolygons); diff --git a/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/src/libslic3r/Fill/Fill3DHoneycomb.cpp index 34a1ff1b50..de4aaeacd3 100644 --- a/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -200,6 +200,10 @@ void Fill3DHoneycomb::_fill_surface_single( if (std::abs(infill_angle) >= EPSILON) expolygon.rotate(-infill_angle); BoundingBox bb = expolygon.contour.bounding_box(); + // Expand the bounding box to avoid artifacts at the edges + coord_t expand = 5 * (scale_(this->spacing)); + bb.offset(expand); + // Note: with equally-scaled X/Y/Z, the pattern will create a vertically-stretched // truncated octahedron; so Z is pre-adjusted first by scaling by sqrt(2) coordf_t zScale = sqrt(2); diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index ed3bfcf0a0..69748ae9c6 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -1371,42 +1371,47 @@ void Filler::_fill_surface_single( all_polylines.reserve(lines.size()); std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; }); - // Apply multiline offset if needed - multiline_fill(all_polylines, params, spacing); + // Apply multiline offset if needed + multiline_fill(all_polylines, params, spacing); // Crop all polylines all_polylines = intersection_pl(std::move(all_polylines), expolygon); #endif } - // After intersection_pl some polylines with only one line are split into more lines - for (Polyline &polyline : all_polylines) { - //FIXME assert that all the points are collinear and in between the start and end point. - if (polyline.points.size() > 2) - polyline.points.erase(polyline.points.begin() + 1, polyline.points.end() - 1); - } -// assert(has_no_collinear_lines(all_polylines)); + if (params.multiline == 1) { + // After intersection_pl some polylines with only one line are split into more lines + for (Polyline& polyline : all_polylines) { + // FIXME assert that all the points are collinear and in between the start and end point. + if (polyline.points.size() > 2) + polyline.points.erase(polyline.points.begin() + 1, polyline.points.end() - 1); + } + // assert(has_no_collinear_lines(all_polylines)); #ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT - { - static int iRun = 0; - export_infill_lines_to_svg(expolygon, all_polylines, debug_out_path("FillAdaptive-initial-%d.svg", iRun++)); - } + { + static int iRun = 0; + export_infill_lines_to_svg(expolygon, all_polylines, debug_out_path("FillAdaptive-initial-%d.svg", iRun++)); + } #endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */ - const auto hook_length = coordf_t(std::min(std::numeric_limits::max(), scale_(params.anchor_length))); - const auto hook_length_max = coordf_t(std::min(std::numeric_limits::max(), scale_(params.anchor_length_max))); + const auto hook_length = coordf_t(std::min(std::numeric_limits::max(), scale_(params.anchor_length))); + const auto hook_length_max = coordf_t(std::min(std::numeric_limits::max(), scale_(params.anchor_length_max))); Polylines all_polylines_with_hooks = all_polylines.size() > 1 ? connect_lines_using_hooks(std::move(all_polylines), expolygon, this->spacing, hook_length, hook_length_max) : std::move(all_polylines); #ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT - { - static int iRun = 0; - export_infill_lines_to_svg(expolygon, all_polylines_with_hooks, debug_out_path("FillAdaptive-hooks-%d.svg", iRun++)); - } + { + static int iRun = 0; + export_infill_lines_to_svg(expolygon, all_polylines_with_hooks, debug_out_path("FillAdaptive-hooks-%d.svg", iRun++)); + } #endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */ - chain_or_connect_infill(std::move(all_polylines_with_hooks), expolygon, polylines_out, this->spacing, params); + chain_or_connect_infill(std::move(all_polylines_with_hooks), expolygon, polylines_out, this->spacing, params); + } else { + // if multiline is > 1 infill is ready to connect + chain_or_connect_infill(std::move(all_polylines), expolygon, polylines_out, this->spacing, params); + } #ifdef ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT { diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 3a9412119f..c585329079 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -3,6 +3,7 @@ #include #include "../ClipperUtils.hpp" +#include "../Clipper2Utils.hpp" #include "../EdgeGrid.hpp" #include "../Geometry.hpp" #include "../Geometry/Circle.hpp" @@ -2699,60 +2700,77 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const Polygons &boun connect_base_support(std::move(infill_ordered), polygons_src, bbox, polylines_out, spacing, params); } -//Fill Multiline +// Fill Multiline -Clipper2 version void multiline_fill(Polylines& polylines, const FillParams& params, float spacing) { - if (params.multiline > 1) { - const int n_lines = params.multiline; - const int n_polylines = static_cast(polylines.size()); - Polylines all_polylines; - all_polylines.reserve(n_lines * n_polylines); + if (params.multiline <= 1) + return; - const float center = (n_lines - 1) / 2.0f; + const int n_lines = params.multiline; + const int n_polylines = static_cast(polylines.size()); + Polylines all_polylines; + all_polylines.reserve(n_lines * n_polylines); - for (int line = 0; line < n_lines; ++line) { - float offset = scale_((static_cast(line) - center) * spacing); + // Remove invalid polylines + polylines.erase(std::remove_if(polylines.begin(), polylines.end(), + [](const Polyline& p) { return p.size() < 2; }), + polylines.end()); - for (const Polyline& pl : polylines) { - const size_t n = pl.points.size(); - if (n < 2) { - all_polylines.emplace_back(pl); - continue; - } + if (polylines.empty()) + return; + // Convert source polylines to Clipper2 paths + Clipper2Lib::Paths64 subject_paths = Slic3rPolylines_to_Paths64(polylines); - Points new_points; - new_points.reserve(n); - for (size_t i = 0; i < n; ++i) { - Vec2f tangent; - // For the first and last point, if the polyline is a - // closed loop, get the tangent from the points on either - // side of the join, otherwise just use the first or last - // line. - if (i == 0) { - if (pl.points[0] == pl.points[n-1]) { - tangent = (pl.points[1] - pl.points[n-2]).template cast().normalized(); - } else { - tangent = (pl.points[1] - pl.points[0]).template cast().normalized(); - } - } else if (i == n - 1) { - if (pl.points[0] == pl.points[n-1]) { - tangent = (pl.points[1] - pl.points[n-2]).template cast().normalized(); - } else { - tangent = (pl.points[n-1] - pl.points[n-2]).template cast().normalized(); - } - } else - tangent = (pl.points[i+1] - pl.points[i-1]).template cast().normalized(); - Vec2f normal(-tangent.y(), tangent.x()); + const double miter_limit = 2.0; + const int rings = n_lines / 2; - Point p = pl.points[i] + (normal * offset).template cast(); - new_points.push_back(p); - } + // Compute offsets (in units of spacing) + std::vector offsets; + offsets.reserve(n_lines); - all_polylines.emplace_back(std::move(new_points)); - } - } - polylines = std::move(all_polylines); + if (n_lines % 2 != 0) { + // Odd: center line at offset = 0 + offsets.push_back(0.0); + + for (int i = 1; i <= rings; ++i) + offsets.push_back(i * spacing); + } else { + // Even: no center, start at 0.5 * spacing + double start = 0.5 * spacing; + for (int i = 0; i < rings; ++i) + offsets.push_back(start + i * spacing); } + + // Process each offset + Clipper2Lib::ClipperOffset offsetter(miter_limit); + offsetter.AddPaths(subject_paths, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Round); + + for (double t : offsets) { + if (t == 0.0) { + // Center line (only applies when n_lines is odd) + all_polylines.insert(all_polylines.end(), polylines.begin(), polylines.end()); + continue; + } + + // ClipperOffset with current offset distance (union is not needed here) + Clipper2Lib::Paths64 offset_paths; + offsetter.Execute(scale_(t), offset_paths); + if (offset_paths.empty()) + continue; + + // Convert back to polylines + Polylines new_polylines = Paths64_to_polylines(offset_paths); + + for (Polyline& pl : new_polylines) { + if (pl.points.size() < 3) + continue; + if (pl.points.front() != pl.points.back()) + pl.points.push_back(pl.points.front()); + all_polylines.emplace_back(std::move(pl)); + } + } + + polylines = std::move(all_polylines); } } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp index 93a54a0739..4f2a0b8970 100644 --- a/src/libslic3r/Fill/FillConcentric.cpp +++ b/src/libslic3r/Fill/FillConcentric.cpp @@ -19,7 +19,7 @@ void FillConcentric::_fill_surface_single( // no rotation is supported for this infill pattern BoundingBox bounding_box = expolygon.contour.bounding_box(); - coord_t min_spacing = scale_(this->spacing); + coord_t min_spacing = scale_(this->spacing) * params.multiline; coord_t distance = coord_t(min_spacing / params.density); if (params.density > 0.9999f && !params.dont_adjust) { @@ -27,8 +27,12 @@ void FillConcentric::_fill_surface_single( this->spacing = unscale(distance); } - Polygons loops = to_polygons(expolygon); - ExPolygons last { std::move(expolygon) }; + // Contract surface polygon by half line width to avoid excesive overlap with perimeter + ExPolygons contracted = offset_ex(expolygon, -float(scale_(0.5 * (params.multiline - 1) * this->spacing ))); + + Polygons loops = to_polygons(contracted); + + ExPolygons last { std::move(contracted) }; while (! last.empty()) { last = offset2_ex(last, -(distance + min_spacing/2), +min_spacing/2); append(loops, to_polygons(last)); @@ -46,6 +50,9 @@ void FillConcentric::_fill_surface_single( last_pos = polylines_out.back().last_point(); } + // Apply multiline offset if needed + multiline_fill(polylines_out, params, spacing); + // clip the paths to prevent the extruder from getting exactly on the first point of the loop // Keep valid paths only. size_t j = iPathFirst; diff --git a/src/libslic3r/Fill/FillHoneycomb.cpp b/src/libslic3r/Fill/FillHoneycomb.cpp index e750425a82..a595cdb664 100644 --- a/src/libslic3r/Fill/FillHoneycomb.cpp +++ b/src/libslic3r/Fill/FillHoneycomb.cpp @@ -74,7 +74,7 @@ void FillHoneycomb::_fill_surface_single( } } // Apply multiline offset if needed - multiline_fill(all_polylines, params, 1.1 * spacing); + multiline_fill(all_polylines, params, spacing); all_polylines = intersection_pl(std::move(all_polylines), expolygon); chain_or_connect_infill(std::move(all_polylines), expolygon, polylines_out, this->spacing, params); diff --git a/src/libslic3r/Fill/FillPlanePath.cpp b/src/libslic3r/Fill/FillPlanePath.cpp index 6044ba43a2..b4681d05f9 100644 --- a/src/libslic3r/Fill/FillPlanePath.cpp +++ b/src/libslic3r/Fill/FillPlanePath.cpp @@ -81,6 +81,9 @@ void FillPlanePath::_fill_surface_single( BoundingBox snug_bounding_box = get_extents(expolygon).inflated(SCALED_EPSILON); + // Expand the bounding box to avoid artifacts at the edges + snug_bounding_box.offset(scale_(this->spacing)*params.multiline); + // Rotated bounding box of the area to fill in with the pattern. BoundingBox bounding_box = align ? // Sparse infill needs to be aligned across layers. Align infill across layers using the object's bounding box. @@ -97,7 +100,7 @@ void FillPlanePath::_fill_surface_single( Polyline polyline; { - auto distance_between_lines = scaled(this->spacing) / params.density; + auto distance_between_lines = scaled(this->spacing) * params.multiline / params.density; auto min_x = coord_t(ceil(coordf_t(bounding_box.min.x()) / distance_between_lines)); auto min_y = coord_t(ceil(coordf_t(bounding_box.min.y()) / distance_between_lines)); auto max_x = coord_t(ceil(coordf_t(bounding_box.max.x()) / distance_between_lines)); @@ -117,8 +120,13 @@ void FillPlanePath::_fill_surface_single( } } + Polylines polylines = {polyline}; + + // Apply multiline offset if needed + multiline_fill(polylines, params, spacing); + if (polyline.size() >= 2) { - Polylines polylines = intersection_pl(polyline, expolygon); + polylines = intersection_pl(std::move(polylines), expolygon); if (!polylines.empty()) { Polylines chained; if (params.dont_connect() || params.density > 0.5) { diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index cfb9c32300..775b3e8b42 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -3000,7 +3000,7 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar params.density /= double(sweep_params.size()); assert(params.density > 0.0001f && params.density <= 1.f); - ExPolygonWithOffset poly_with_offset_base(surface->expolygon, 0, float(scale_(this->overlap - 0.5 * this->spacing))); + ExPolygonWithOffset poly_with_offset_base(surface->expolygon, 0, float(scale_(this->overlap + 0.5 * params.multiline * this->spacing)));//increase offset to crop infill lines when using multiline infill if (poly_with_offset_base.n_contours == 0) // Not a single infill line fits. return true; @@ -3012,19 +3012,24 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar for (const SweepParams &sweep : sweep_params) { // Rotate polygons so that we can work with vertical lines here float angle = rotate_vector.first + sweep.angle_base; - //Fill Multiline - for (int i = 0; i < params.multiline; ++i) { - coord_t group_offset = i * line_spacing; - coord_t internal_offset = (i - (params.multiline - 1) / 2.0f) * line_width; - coord_t total_offset = group_offset + internal_offset; - coord_t pattern_shift = scale_(sweep.pattern_shift + unscale_(total_offset)); - make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, -angle), rotate_vector.second.rotated(-angle), angle, - line_width + coord_t(SCALED_EPSILON), line_spacing, pattern_shift, fill_lines); - } + make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, -angle), rotate_vector.second.rotated(-angle), angle, + line_width + coord_t(SCALED_EPSILON), line_spacing, coord_t(scale_(sweep.pattern_shift)), fill_lines); } + + // Apply multiline offset if needed + multiline_fill(fill_lines, params, spacing); + + // Contract surface polygon by half line width to avoid excesive overlap with perimeter + ExPolygons contracted = offset_ex(surface->expolygon, -float(scale_(0.5 * this->spacing))); + + // if contraction results in empty polygon, use original surface + const ExPolygon &intersection_surface = contracted.empty() ? surface->expolygon : contracted.front(); -if ((params.pattern == ipLateralLattice || params.pattern == ipLateralHoneycomb ) && params.multiline >1 ) + // Intersect polylines with perimeter + fill_lines = intersection_pl(std::move(fill_lines), intersection_surface); + + if ((params.pattern == ipLateralLattice || params.pattern == ipLateralHoneycomb ) && params.multiline >1 ) remove_overlapped(fill_lines, line_width); if (!fill_lines.empty()) { @@ -3033,7 +3038,260 @@ if ((params.pattern == ipLateralLattice || params.pattern == ipLateralHoneycomb fill_lines = chain_polylines(std::move(fill_lines)); append(polylines_out, std::move(fill_lines)); } else - connect_infill(std::move(fill_lines), poly_with_offset_base.polygons_outer, get_extents(surface->expolygon.contour), polylines_out, this->spacing, params); + connect_infill(std::move(fill_lines), intersection_surface, polylines_out, this->spacing, params); + } + + return true; +} + +bool FillRectilinear::fill_surface_trapezoidal( + const Surface* surface, + FillParams params, + const std::initializer_list& sweep_params, + Polylines& polylines_out, + int Pattern_type) // 0=grid, 1=triangular +{ + assert(params.multiline > 1); + + Polylines polylines; + + // Common parameters + const coord_t d1 = coord_t(scale_(this->spacing)) * params.multiline; // Infill total wall thickness + + // Pattern-specific parameters + coord_t period; + double base_angle; + std::pair rotate_vector = this->_infill_direction(surface); + + if (Pattern_type == 0) { + // Grid pattern parameters + period = coord_t((2.0 * d1 / params.density) * std::sqrt(2.0)); + base_angle = rotate_vector.first + M_PI_4; // 45 + } else { + // Triangular pattern parameters + period = coord_t(( 2.0 * d1 / params.density) * std::sqrt(3.0)); + base_angle = rotate_vector.first + M_PI_2; //90 + } + + // Obtain the expolygon and rotate to align with pattern base angle + ExPolygon expolygon = surface->expolygon; + if (std::abs(base_angle) >= EPSILON) { + expolygon.rotate(-base_angle, rotate_vector.second); + } + + // Use extended object bounding box for consistent pattern across layers + BoundingBox bb = this->extended_object_bounding_box(); + + switch (Pattern_type) { + case 0: // Grid / Trapezoidal + { + // Generate a non-crossing trapezoidal pattern to avoid overextrusion at intersections when `multiline > 1`. + // P1--P2 + // / \ + // P0/ \P3__P4 + // + // P1x-P2x=P3x-P4x=d1 + // P0y-P1y=P2y-P3y=d2 + + const coord_t d2 = coord_t(0.5 * period - d1); + + // Align bounding box to the grid + bb.merge(align_to_grid(bb.min, Point(period, period))); + const coord_t xmin = bb.min.x(); + const coord_t xmax = bb.max.x(); + const coord_t ymin = bb.min.y(); + const coord_t ymax = bb.max.y(); + + // Create the two base row patterns once + Polyline base_row_normal; + base_row_normal.points.reserve(((xmax - xmin) / period + 1) * 5); // 5 points per trapezoid + Polyline base_row_flipped; + base_row_flipped.points.reserve(((xmax - xmin) / period + 1) * 5); // 5 points per trapezoid + + // Build complete rows from xmin to xmax + for (coord_t x = xmin; x < xmax; x += period) { + // Normal row + base_row_normal.points.emplace_back(Point(x, d1 / 2)); // P0 + base_row_normal.points.emplace_back(Point(x + d1, d1 / 2)); // P1 + base_row_normal.points.emplace_back(Point(x + d1 + d2, d1 / 2 + d2)); // P2 + base_row_normal.points.emplace_back(Point(x + 2 * d1 + d2, d1 / 2 + d2)); // P3 + base_row_normal.points.emplace_back(Point(x + 2 * d1 + 2 * d2, d1 / 2)); // P4 + } + + // Flipped row (mirrored vertically) + base_row_flipped.points = base_row_normal.points; + for (auto& p : base_row_flipped.points) { + p.y() = period / 2 - p.y(); + } + + // Pre-allocate polylines + const size_t estimated_rows = ((ymax - ymin) / (period / 2) + 1); + polylines.reserve(estimated_rows); + + bool flip_vertical = false; + + // Now just copy and translate vertically + for (coord_t y = ymin; y < ymax; y += period / 2) { + Polyline pl_row = flip_vertical ? base_row_flipped : base_row_normal; + + // Translate all points vertically + for (Point& p : pl_row.points) { + p.y() += y; + } + + polylines.emplace_back(std::move(pl_row)); + flip_vertical = !flip_vertical; + } + + // transpose points for odd layers + if (layer_id % 2 == 1) { + for (Polyline& pl : polylines) { + for (Point& p : pl.points) { + std::swap(p.x(), p.y()); + p.x() += d1 / 2; + p.y() -= d1 / 2; + } + } + } + break; + } + + case 1: // Triangular + { + // Generate a non-crossing trapezoidal pattern with a base line below. + // P1-P2 + // / \ + // P0/ \P3_P4 + // ---------------- + // P1x-P2x=P3x-P4x=d2 + // P0y-P1y=P2y-P3y=h-2d1 + // + + // Triangular pattern density adjustment: + const coord_t d2_tri = coord_t(2.0 / std::sqrt(3.0) * d1); + const coord_t h = coord_t(0.5 * std::sqrt(3.0) * period); // height of triangle + + // Align bounding box to the grid + bb.merge(align_to_grid(bb.center(), Point(period,h))); + const int layer_mod = layer_id % 3; + const double angle = layer_mod * 2.0 * M_PI / 3.0; + + const Point rotation_center = bb.center(); + const coord_t half_w = bb.size().x() / 2; + const coord_t half_h = bb.size().y() / 2; + + // Compute how many full periods fit in each direction + const coord_t num_periods_x = coord_t(std::ceil(half_w / double(period))); + coord_t num_periods_y =coord_t(std::ceil(half_h / double(h))); + // Ensure an even number of rows so the pattern stays centered + if ((num_periods_y % 2) != 0) + ++num_periods_y; + + // Compute aligned limits (symmetric around the origin) + const coord_t x_min_aligned = -num_periods_x * period; + const coord_t x_max_aligned = num_periods_x * period; + const coord_t y_min_aligned = -num_periods_y * h; + const coord_t y_max_aligned = num_periods_y * h; + + // Pre-allocate estimated number of polylines + const size_t estimated_rows = (y_max_aligned - y_min_aligned) / h + 2; + const size_t estimated_polylines = (estimated_rows + 1) * 2; // base line + trapezoid line per row + polylines.reserve(estimated_polylines); + + // Create the two base row templates once + Polyline base_line_template; + base_line_template.points.reserve(2); // 2 points for base line + Polyline trapezoid_row_normal; + trapezoid_row_normal.points.reserve(((x_max_aligned - x_min_aligned) / period + 1) * 5); // 5 points per trapezoid + Polyline trapezoid_row_shifted; + trapezoid_row_shifted.points.reserve(((x_max_aligned - x_min_aligned) / period + 1) * 5); // 5 points per trapezoid + // Build base line template (from x_min_aligned to x_max_aligned) + base_line_template.points.emplace_back(Point(x_min_aligned, 0)); + base_line_template.points.emplace_back(Point(x_max_aligned, 0)); + + // Build complete trapezoid rows once + // Normal row (no shift) + for (coord_t x = x_min_aligned; x < x_max_aligned; x += period) { + trapezoid_row_normal.points.emplace_back(Point(x + d2_tri / 2, d1)); // P0 + trapezoid_row_normal.points.emplace_back(Point(x + period / 2 - d2_tri / 2, h - d1)); // P1 + trapezoid_row_normal.points.emplace_back(Point(x + period / 2 + d2_tri / 2, h - d1)); // P2 + trapezoid_row_normal.points.emplace_back(Point(x + period - d2_tri / 2, d1)); // P3 + trapezoid_row_normal.points.emplace_back(Point(x + period, d1)); // P4 + } + + // Shifted row (mirrored vertically) + trapezoid_row_shifted.points = trapezoid_row_normal.points; + for (auto& p : trapezoid_row_shifted.points) + p.y() = h - p.y(); + + bool shift_row = false; + + // Generate pattern by copying and translating templates vertically + for (coord_t y = y_min_aligned; y < y_max_aligned; y += h) { + // Base line - copy and translate + Polyline base_line = base_line_template; + for (Point& p : base_line.points) { + p.y() += y; + } + polylines.emplace_back(std::move(base_line)); + + // Trapezoid line - copy and translate the appropriate template + Polyline trapezoid_line = shift_row ? trapezoid_row_shifted : trapezoid_row_normal; + for (Point& p : trapezoid_line.points) { + p.y() += y; + } + + if (!trapezoid_line.points.empty()) { + polylines.emplace_back(std::move(trapezoid_line)); + } + + shift_row = !shift_row; + } + + // Rotate around origin (0,0) + if (layer_mod) + for (auto& pl : polylines) + pl.rotate(angle, Point(0,0)); + + break; + } + + default: + // Handle unknown pattern type + break; + } + + // Apply multiline fill + multiline_fill(polylines, params, spacing); + + // Contract surface polygon by half line width to avoid excesive overlap with perimeter + ExPolygons contracted = offset_ex(expolygon, -float(scale_(0.5 * this->spacing))); + + // if contraction results in empty polygon, use original surface + const ExPolygon &intersection_surface = contracted.empty() ? expolygon : contracted.front(); + + // Intersect polylines with offset expolygon + polylines = intersection_pl(std::move(polylines), intersection_surface); + + // Remove very short segments that may cause connection issues + const double minlength = scale_(0.8 * this->spacing); + if (minlength > 0 && !polylines.empty()) { + polylines.erase(std::remove_if(polylines.begin(), polylines.end(), + [minlength](const Polyline& pl) { return pl.length() < minlength; }), + polylines.end()); + } + + // Connect infill lines using offset expolygon + int infill_start_idx = polylines_out.size(); + if (!polylines.empty()) { + Slic3r::Fill::chain_or_connect_infill(std::move(polylines), intersection_surface, polylines_out, this->spacing, params); + + // Rotate back the infill lines to original orientation + if (std::abs(base_angle) >= EPSILON) { + for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it) { + it->rotate(base_angle, rotate_vector.second); + } + } } return true; @@ -3077,15 +3335,27 @@ Polylines FillMonotonicLine::fill_surface(const Surface* surface, const FillPara Polylines FillGrid::fill_surface(const Surface *surface, const FillParams ¶ms) { Polylines polylines_out; - if (! this->fill_surface_by_multilines( - surface, params, - { { 0.f, 0.f }, { float(M_PI / 2.), 0.f } }, - polylines_out)) - BOOST_LOG_TRIVIAL(error) << "FillGrid::fill_surface() failed to fill a region."; - if (this->layer_id % 2 == 1) - for (int i = 0; i < polylines_out.size(); i++) - std::reverse(polylines_out[i].begin(), polylines_out[i].end()); + if (params.multiline > 1) { + // Experimental trapezoidal grid + if (!this->fill_surface_trapezoidal( + surface, params, + { { 0.f, 0.f }, { float(M_PI / 2.), 0.f } }, + polylines_out,0)) + BOOST_LOG_TRIVIAL(error) << "FillGrid::fill_surface_trapezoidal() failed."; + + } else { + if (!this->fill_surface_by_multilines( + surface, params, + { { 0.f, 0.f }, { float(M_PI / 2.), 0.f } }, + polylines_out)) + BOOST_LOG_TRIVIAL(error) << "FillGrid::fill_surface() failed to fill a region."; + + + if (this->layer_id % 2 == 1) + for (int i = 0; i < polylines_out.size(); i++) + std::reverse(polylines_out[i].begin(), polylines_out[i].end()); + } return polylines_out; } @@ -3108,12 +3378,23 @@ Polylines FillLateralLattice::fill_surface(const Surface *surface, const FillPar Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms){ Polylines polylines_out; + if (params.multiline > 1) { + // Experimental trapezoidal grid + if (!this->fill_surface_trapezoidal( + surface, params, + { { 0.f, 0.f }, { float(M_PI / 2.), 0.f } }, + polylines_out,1)) + BOOST_LOG_TRIVIAL(error) << "FillGrid::fill_surface_trapezoidal() failed."; + + } else { if (! this->fill_surface_by_multilines( surface, params, { { 0.f, 0.f }, { float(M_PI / 3.), 0.f }, { float(2. * M_PI / 3.), 0. } }, polylines_out)) BOOST_LOG_TRIVIAL(error) << "FillTriangles::fill_surface() failed to fill a region."; + } return polylines_out; + } Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶ms) @@ -3144,8 +3425,8 @@ Polylines FillQuarterCubic::fill_surface(const Surface* surface, const FillParam using namespace boost::math::float_constants; Polylines polylines_out; - coord_t line_width = coord_t(scale_(this->spacing)); - coord_t period = coord_t(scale_(this->spacing) / params.density) * 4; + coord_t line_width = coord_t(scale_(this->spacing)) * params.multiline; + coord_t period = coord_t(scale_(this->spacing) *params.multiline / params.density) * 4; // First half tetrahedral fill double pattern_z_shift = 0.0; diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp index 3e4f3cf92f..126cbe3a15 100644 --- a/src/libslic3r/Fill/FillRectilinear.hpp +++ b/src/libslic3r/Fill/FillRectilinear.hpp @@ -29,6 +29,7 @@ protected: float pattern_shift; }; bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list &sweep_params, Polylines &polylines_out); + bool fill_surface_trapezoidal(const Surface *surface, FillParams params, const std::initializer_list &sweep_params, Polylines &polylines_out,int Pattern_type); // The extended bounding box of the whole object that covers any rotation of every layer. BoundingBox extended_object_bounding_box() const; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 2fb29fc2cd..37fc895411 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2733,7 +2733,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Fill Multiline"); def->tooltip = L("Using multiple lines for the infill pattern, if supported by infill pattern."); def->min = 1; - def->max = 5; // Maximum number of lines for infill pattern + def->max = 10; // Maximum number of lines for infill pattern def->set_default_value(new ConfigOptionInt(1)); def = this->add("sparse_infill_pattern", coEnum); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 8254afda2d..38bc2cb7c9 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -604,8 +604,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co // Infill patterns that support multiline infill. InfillPattern pattern = config->opt_enum("sparse_infill_pattern"); - bool have_multiline_infill_pattern = pattern == ipGyroid || pattern == ipGrid || pattern == ipRectilinear || pattern == ipTpmsD || pattern == ipTpmsFK || pattern == ipCrossHatch || pattern == ipHoneycomb || pattern == ipLateralLattice || pattern == ipLateralHoneycomb || - pattern == ipCubic || pattern == ipStars || pattern == ipAlignedRectilinear || pattern == ipLightning || pattern == ip3DHoneycomb || pattern == ipAdaptiveCubic || pattern == ipSupportCubic; + bool have_multiline_infill_pattern = pattern == ipGyroid || pattern == ipGrid || pattern == ipRectilinear || pattern == ipTpmsD || pattern == ipTpmsFK || pattern == ipCrossHatch || pattern == ipHoneycomb || pattern == ipLateralLattice || pattern == ipLateralHoneycomb || pattern == ipConcentric || + pattern == ipCubic || pattern == ipStars || pattern == ipAlignedRectilinear || pattern == ipLightning || pattern == ip3DHoneycomb || pattern == ipAdaptiveCubic || pattern == ipSupportCubic|| pattern == ipTriangles || pattern == ipQuarterCubic|| pattern == ipArchimedeanChords || pattern == ipHilbertCurve || pattern == ipOctagramSpiral; // If there is infill, enable/disable fill_multiline according to whether the pattern supports multiline infill. if (have_infill) {