From c085eb845cc8cd0d3e713d4d44d73dd199da36d3 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 22 Feb 2026 16:13:06 +0800 Subject: [PATCH] Fix machine envelope G-code emitting wrong limits due to broken extruder_id indexing (#12414) print_machine_envelope() used get_extruder_id(extruder_id)*2 to index machine limit arrays that only hold [Normal, Stealth] (2 entries). For multi-extruder setups this went out-of-bounds, causing wrong M201/M203 values in the G-code which then override the estimator's correct limits. Same class of bug as c6d1c11ebb but on the G-code writer side. Changes: - Remove unused extruder_id param from print_machine_envelope() - Use .values.front() for M201/M203, matching M204/M205 in same function - Change get_option_value() fallback from .back() to .front() so any future out-of-bounds index returns Normal mode instead of Stealth --- src/libslic3r/GCode.cpp | 21 ++++++++++----------- src/libslic3r/GCode.hpp | 2 +- src/libslic3r/GCode/GCodeProcessor.cpp | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f4ac0c498a..55b0ee6d29 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2743,7 +2743,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_pa_processor = std::make_unique(*this, tool_ordering.all_extruders()); // Emit machine envelope limits for the Marlin firmware. - this->print_machine_envelope(file, print, initial_extruder_id); + this->print_machine_envelope(file, print); // Disable fan. if (m_config.auxiliary_fan.value && print.config().close_fan_the_first_x_layers.get_at(initial_extruder_id)) { @@ -3808,23 +3808,22 @@ PlaceholderParserIntegration &ppi = m_placeholder_parser_integration; // Print the machine envelope G-code for the Marlin firmware based on the "machine_max_xxx" parameters. // Do not process this piece of G-code by the time estimator, it already knows the values through another sources. -void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print, int extruder_id) +void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print) { - int matched_machine_limit_idx = get_extruder_id(extruder_id) * 2; const auto flavor = print.config().gcode_flavor.value; if ((flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware) && print.config().emit_machine_limits_to_gcode.value == true) { int factor = flavor == gcfRepRapFirmware ? 60 : 1; // RRF M203 and M566 are in mm/min file.write_format("M201 X%d Y%d Z%d E%d\n", - int(print.config().machine_max_acceleration_x.values[matched_machine_limit_idx] + 0.5), - int(print.config().machine_max_acceleration_y.values[matched_machine_limit_idx] + 0.5), - int(print.config().machine_max_acceleration_z.values[matched_machine_limit_idx] + 0.5), - int(print.config().machine_max_acceleration_e.values[matched_machine_limit_idx] + 0.5)); + int(print.config().machine_max_acceleration_x.values.front() + 0.5), + int(print.config().machine_max_acceleration_y.values.front() + 0.5), + int(print.config().machine_max_acceleration_z.values.front() + 0.5), + int(print.config().machine_max_acceleration_e.values.front() + 0.5)); file.write_format("M203 X%d Y%d Z%d E%d\n", - int(print.config().machine_max_speed_x.values[matched_machine_limit_idx] * factor + 0.5), - int(print.config().machine_max_speed_y.values[matched_machine_limit_idx] * factor + 0.5), - int(print.config().machine_max_speed_z.values[matched_machine_limit_idx] * factor + 0.5), - int(print.config().machine_max_speed_e.values[matched_machine_limit_idx] * factor + 0.5)); + int(print.config().machine_max_speed_x.values.front() * factor + 0.5), + int(print.config().machine_max_speed_y.values.front() * factor + 0.5), + int(print.config().machine_max_speed_z.values.front() * factor + 0.5), + int(print.config().machine_max_speed_e.values.front() * factor + 0.5)); // Now M204 - acceleration. This one is quite hairy thanks to how Marlin guys care about // Legacy Marlin should export travel acceleration the same as printing acceleration. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 30ad964038..96c15a5df8 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -640,7 +640,7 @@ private: double calc_max_volumetric_speed(const double layer_height, const double line_width, const std::string co_str); std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1); bool _needSAFC(const ExtrusionPath &path); - void print_machine_envelope(GCodeOutputStream& file, Print& print, int extruder_id); + void print_machine_envelope(GCodeOutputStream& file, Print& print); void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 5d0ff2860e..e2eda8d36b 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -124,7 +124,7 @@ static void set_option_value(ConfigOptionFloats& option, size_t id, float value) static float get_option_value(const ConfigOptionFloats& option, size_t id) { return option.values.empty() ? 0.0f : - ((id < option.values.size()) ? static_cast(option.values[id]) : static_cast(option.values.back())); + ((id < option.values.size()) ? static_cast(option.values[id]) : static_cast(option.values.front())); } static float estimated_acceleration_distance(float initial_rate, float target_rate, float acceleration)