From a1a90d7c833801d8126c98d497673a41ff4c286f Mon Sep 17 00:00:00 2001
From: Kiss Lorand <50251547+kisslorand@users.noreply.github.com>
Date: Mon, 8 Jun 2026 15:27:37 +0300
Subject: [PATCH] Fix junction deviation and jerk settings behavior (#14004)
* Fix junction deviation and jerk settings behavior
Process settings now follow the selected printer's junction deviation
configuration. When machine_max_junction_deviation is enabled,
default_junction_deviation is shown and jerk settings are hidden. When
junction deviation is disabled, jerk settings are restored and
default_junction_deviation is hidden.
Fix a validation issue where junction deviation mismatch warnings could
be reported even when machine_max_junction_deviation was set to 0.
Warnings now apply only when junction deviation is active and point
directly to default_junction_deviation.
Also simplify Motion ability page visibility checks by reusing local
firmware-flavor booleans.
* GUI tweak
- separate Junction Deviation segment
- JD and Jerk stay visible
---
resources/images/param_junction_deviation.svg | 10 +++++
src/libslic3r/Print.cpp | 9 ++--
src/slic3r/GUI/ConfigManipulation.cpp | 45 +++++++++++--------
src/slic3r/GUI/Tab.cpp | 36 +++++++++------
4 files changed, 62 insertions(+), 38 deletions(-)
create mode 100644 resources/images/param_junction_deviation.svg
diff --git a/resources/images/param_junction_deviation.svg b/resources/images/param_junction_deviation.svg
new file mode 100644
index 0000000000..4b3b81fdd5
--- /dev/null
+++ b/resources/images/param_junction_deviation.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 0325f1b97b..0d58e2dc00 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -1836,15 +1836,12 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
}
}
-
- // Check junction deviation
- // Orca: Only marlin FW supports max junction deviation. Dont display warning if firmware is not supporting it.
- const bool support_max_junction_deviation = ( m_config.gcode_flavor == gcfMarlinFirmware);
- if (warning_key.empty() && m_default_object_config.default_junction_deviation.value > max_junction_deviation && support_max_junction_deviation) {
+ // check junction deviation
+ else if (m_default_object_config.default_junction_deviation.value > max_junction_deviation) {
warning->string = L( "Junction deviation setting exceeds the printer's maximum value (machine_max_junction_deviation).\n"
"Orca will automatically cap the junction deviation to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the machine_max_junction_deviation value in your printer's configuration to get higher limits.");
- warning->opt_key = warning_key;
+ warning->opt_key = "default_junction_deviation";
}
// check acceleration
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index 66587f3805..a0840c028b 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -571,7 +571,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
{
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
- auto gcflavor = preset_bundle->printers.get_edited_preset().config.option>("gcode_flavor")->value;
+ const GCodeFlavor gcflavor = preset_bundle->printers.get_edited_preset().config.option>("gcode_flavor")->value;
+
+ // Orca: use booleans to avoid repeated comparisons with enum values
+ const bool gcf_is_marlin_firmware = gcflavor == GCodeFlavor::gcfMarlinFirmware;
+ const bool gcf_is_klipper = gcflavor == GCodeFlavor::gcfKlipper;
bool have_volumetric_extrusion_rate_slope = config->option("max_volumetric_extrusion_rate_slope")->value > 0;
float have_volumetric_extrusion_rate_slope_segment_length = config->option("max_volumetric_extrusion_rate_slope_segment_length")->value;
@@ -675,23 +679,28 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"})
toggle_field(el, have_default_acceleration);
- bool machine_supports_junction_deviation = false;
- if (gcflavor == gcfMarlinFirmware) {
- if (const auto *machine_jd = preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")) {
- machine_supports_junction_deviation = !machine_jd->values.empty() && machine_jd->values.front() > 0.0;
- }
- }
- toggle_line("default_junction_deviation", gcflavor == gcfMarlinFirmware);
- if (machine_supports_junction_deviation) {
- toggle_field("default_junction_deviation", true);
- toggle_field("default_jerk", false);
- for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "initial_layer_travel_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"})
+ const bool junction_deviation_enabled =
+ gcf_is_marlin_firmware &&
+ [&]() {
+ const auto *machine_jd = preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation");
+ return machine_jd && !machine_jd->values.empty() && machine_jd->values.front() > 0.0;
+ }();
+
+ toggle_line("default_junction_deviation", gcf_is_marlin_firmware);
+ toggle_field("default_junction_deviation", junction_deviation_enabled);
+ toggle_field("default_jerk", !junction_deviation_enabled);
+
+ const std::initializer_list jerk_options = {
+ "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk",
+ "initial_layer_travel_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"
+ };
+
+ if (junction_deviation_enabled) {
+ for (auto el : jerk_options)
toggle_line(el, false);
} else {
- toggle_field("default_junction_deviation", false);
- toggle_field("default_jerk", true);
- bool have_default_jerk = config->has("default_jerk") && config->opt_float("default_jerk") > 0;
- for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "initial_layer_travel_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"}) {
+ const bool have_default_jerk = config->has("default_jerk") && config->opt_float("default_jerk") > 0;
+ for (auto el : jerk_options) {
toggle_line(el, true);
toggle_field(el, have_default_jerk);
}
@@ -905,8 +914,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_field("wipe_speed",!is_role_based_wipe_speed);
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
- toggle_line(el, gcflavor == gcfKlipper);
- if(gcflavor == gcfKlipper)
+ toggle_line(el, gcf_is_klipper);
+ if(gcf_is_klipper)
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
bool have_make_overhang_printable = config->opt_bool("make_overhang_printable");
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 8d745b9caa..978528f3b3 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -2559,8 +2559,10 @@ void TabPrint::build()
optgroup->append_single_option_line("accel_to_decel_enable", "speed_settings_acceleration");
optgroup->append_single_option_line("accel_to_decel_factor", "speed_settings_acceleration");
- optgroup = page->new_optgroup(L("Jerk(XY)"), L"param_jerk", 15);
+ optgroup = page->new_optgroup(L("Junction Deviation"), L"param_junction_deviation", 15);
optgroup->append_single_option_line("default_junction_deviation", "speed_settings_jerk_xy#junction-deviation");
+
+ optgroup = page->new_optgroup(L("Jerk(XY)"), L"param_jerk", 15);
optgroup->append_single_option_line("default_jerk", "speed_settings_jerk_xy#default");
optgroup->append_single_option_line("outer_wall_jerk", "speed_settings_jerk_xy#outer-wall");
optgroup->append_single_option_line("inner_wall_jerk", "speed_settings_jerk_xy#inner-wall");
@@ -5448,8 +5450,8 @@ void TabPrinter::toggle_options()
for (auto el : {"use_firmware_retraction", "use_relative_e_distances", "support_multi_bed_types", "pellet_modded_printer", "bed_mesh_max", "bed_mesh_min", "bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "thumbnails"})
toggle_line(el, !is_BBL_printer);
- auto gcf = m_config->option>("gcode_flavor")->value;
- toggle_line("enable_power_loss_recovery", is_BBL_printer || gcf == gcfMarlinFirmware);
+ bool gcf_is_marlin_firmware = m_config->option>("gcode_flavor")->value == GCodeFlavor::gcfMarlinFirmware;
+ toggle_line("enable_power_loss_recovery", is_BBL_printer || gcf_is_marlin_firmware);
const bool support_parallel_printheads = printer_cfg.opt_bool("support_parallel_printheads");
toggle_line("parallel_printheads_count", support_parallel_printheads);
@@ -5581,18 +5583,25 @@ void TabPrinter::toggle_options()
if (m_active_page->title() == L("Motion ability")) {
auto gcf = m_config->option>("gcode_flavor")->value;
update_input_shaper_menu(gcf);
+
+ // Orca: use booleans to avoid repeated comparisons with enum values
+ const bool gcf_is_marlin_legacy = gcf == GCodeFlavor::gcfMarlinLegacy;
+ const bool gcf_is_marlin_firmware = gcf == GCodeFlavor::gcfMarlinFirmware;
+ const bool gcf_is_klipper = gcf == GCodeFlavor::gcfKlipper;
+ const bool gcf_is_reprap_firmware = gcf == GCodeFlavor::gcfRepRapFirmware;
+
bool silent_mode = m_config->opt_bool("silent_mode");
int max_field = silent_mode ? 2 : 1;
for (int i = 0; i < max_field; ++i)
- toggle_option("machine_max_acceleration_travel", gcf != gcfMarlinLegacy && gcf != gcfKlipper, i);
- toggle_line("machine_max_acceleration_travel", gcf != gcfMarlinLegacy && gcf != gcfKlipper);
+ toggle_option("machine_max_acceleration_travel", !gcf_is_marlin_legacy && !gcf_is_klipper, i);
+ toggle_line("machine_max_acceleration_travel", !gcf_is_marlin_legacy && !gcf_is_klipper);
for (int i = 0; i < max_field; ++i)
- toggle_option("machine_max_junction_deviation", gcf == gcfMarlinFirmware, i);
- toggle_line("machine_max_junction_deviation", gcf == gcfMarlinFirmware);
+ toggle_option("machine_max_junction_deviation", gcf_is_marlin_firmware, i);
+ toggle_line("machine_max_junction_deviation", gcf_is_marlin_firmware);
// Check if junction deviation value is non-zero and firmware is Marlin
- bool enable_jerk = gcf != gcfMarlinFirmware;
- if (gcf == gcfMarlinFirmware) {
+ bool enable_jerk = !gcf_is_marlin_firmware;
+ if (gcf_is_marlin_firmware) {
const auto *junction_deviation = m_config->option("machine_max_junction_deviation");
if (junction_deviation != nullptr) {
const auto &values = junction_deviation->values;
@@ -5608,14 +5617,14 @@ void TabPrinter::toggle_options()
toggle_option("machine_max_jerk_e", enable_jerk, i);
}
- bool emittable_limits = m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfMarlinLegacy || m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfMarlinFirmware || m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfRepRapFirmware;
+ bool emittable_limits = gcf_is_marlin_legacy || gcf_is_marlin_firmware || gcf_is_reprap_firmware;
toggle_option("emit_machine_limits_to_gcode", emittable_limits);
bool resonance_avoidance = m_config->opt_bool("resonance_avoidance");
toggle_option("min_resonance_avoidance_speed", resonance_avoidance);
toggle_option("max_resonance_avoidance_speed", resonance_avoidance);
- bool input_shaping_compatible = m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfMarlinFirmware || m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfRepRapFirmware;
+ bool input_shaping_compatible = gcf_is_marlin_firmware || gcf_is_reprap_firmware;
for (auto is : {"input_shaping_emit", "input_shaping_type", "input_shaping_freq_x", "input_shaping_freq_y",
"input_shaping_damp_x", "input_shaping_damp_y"})
@@ -5625,12 +5634,11 @@ void TabPrinter::toggle_options()
bool emit_machine_limits_to_gcode = m_config->opt_bool("emit_machine_limits_to_gcode");
toggle_option("input_shaping_emit", emit_machine_limits_to_gcode);
bool input_shaping_emit = emit_machine_limits_to_gcode && m_config->opt_bool("input_shaping_emit");
- bool reprap = m_config->opt_enum("gcode_flavor") == GCodeFlavor::gcfRepRapFirmware;
toggle_option("input_shaping_type", input_shaping_emit);
toggle_option("input_shaping_freq_x", input_shaping_emit);
- toggle_option("input_shaping_freq_y", input_shaping_emit && !reprap);
+ toggle_option("input_shaping_freq_y", input_shaping_emit && !gcf_is_reprap_firmware);
toggle_option("input_shaping_damp_x", input_shaping_emit);
- toggle_option("input_shaping_damp_y", input_shaping_emit && !reprap);
+ toggle_option("input_shaping_damp_y", input_shaping_emit && !gcf_is_reprap_firmware);
}
}