From 3ae7bd04fa93da01e1ead5d90aed0c46625c4f8e Mon Sep 17 00:00:00 2001 From: Kiss Lorand <50251547+kisslorand@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:30:29 +0300 Subject: [PATCH] Fix access violation during travel generation before initial tool selection (#14725) --- src/libslic3r/GCodeWriter.cpp | 23 +++++++++++++---------- src/libslic3r/GCodeWriter.hpp | 3 +++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index a3d8e66ac3..a13d05e1c3 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -110,6 +110,7 @@ void GCodeWriter::set_extruders(std::vector extruder_ids) m_filament_extruders.clear(); //ORCA: Reset current extruder ID and clear pointers to prevent dangling pointers when extruders are recreated. m_curr_extruder_id = -1; + m_cached_extruder_idx = 0; std::fill(m_curr_filament_extruder.begin(), m_curr_filament_extruder.end(), nullptr); m_filament_extruders.reserve(extruder_ids.size()); for (unsigned int extruder_id : extruder_ids) @@ -617,6 +618,7 @@ std::string GCodeWriter::toolchange(unsigned int filament_id) assert(filament_extruder_iter != m_filament_extruders.end() && filament_extruder_iter->id() == filament_id); m_curr_extruder_id = filament_extruder_iter->extruder_id(); m_curr_filament_extruder[m_curr_extruder_id] = &*filament_extruder_iter; + m_cached_extruder_idx = get_extruder_index(this->config, filament_id); // return the toolchange command // if we are running a single-extruder setup, just set the extruder and return nothing @@ -658,7 +660,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com GCodeG1Formatter w; w.emit_xy(point_on_plate); auto speed = m_is_first_layer - ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) : this->config.travel_speed.get_at(m_cached_extruder_idx); w.emit_f(speed * 60.0); //BBS w.emit_comment(GCodeWriter::full_gcode_comment, comment); @@ -744,7 +746,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co // BBS Vec3d dest_point = point; auto travel_speed = - m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) : this->config.travel_speed.get_at(m_cached_extruder_idx); //BBS: a z_hop need to be handle when travel if (std::abs(m_to_lift) > EPSILON) { assert(std::abs(m_lifted) < EPSILON); @@ -841,13 +843,13 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co { //force to move xy first then z after filament change w.emit_xy(Vec2d(point_on_plate.x(), point_on_plate.y())); - w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0); + w.emit_f(this->config.travel_speed.get_at(m_cached_extruder_idx) * 60.0); w.emit_comment(GCodeWriter::full_gcode_comment, comment); out_string = w.string() + _travel_to_z(point_on_plate.z(), comment); } else { GCodeG1Formatter w; w.emit_xyz(point_on_plate); - w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0); + w.emit_f(this->config.travel_speed.get_at(m_cached_extruder_idx) * 60.0); w.emit_comment(GCodeWriter::full_gcode_comment, comment); out_string = w.string(); } @@ -880,10 +882,10 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) { m_pos(2) = z; - double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); + double speed = this->config.travel_speed_z.get_at(m_cached_extruder_idx); if (speed == 0.) { - speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) - : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) + : this->config.travel_speed.get_at(m_cached_extruder_idx); } GCodeG1Formatter w; @@ -897,11 +899,11 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment) { std::string output; - double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); + double speed = this->config.travel_speed_z.get_at(m_cached_extruder_idx); if (speed == 0.) { - speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) - : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) + : this->config.travel_speed.get_at(m_cached_extruder_idx); } if (!this->config.enable_arc_fitting) { // Orca: if arc fitting is disabled, approximate the arc with small linear segments @@ -1261,6 +1263,7 @@ void GCodeWriter::init_extruder(unsigned int filament_id) assert(filament_extruder_iter != m_filament_extruders.end() && filament_extruder_iter->id() == filament_id); m_curr_extruder_id = filament_extruder_iter->extruder_id(); m_curr_filament_extruder[m_curr_extruder_id] = &*filament_extruder_iter; + m_cached_extruder_idx = get_extruder_index(this->config, filament_id); } } diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index d3f419df7c..358356e0e0 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -19,6 +19,7 @@ public: GCodeWriter() : multiple_extruders(false), m_curr_filament_extruder(MAXIMUM_EXTRUDER_NUMBER, nullptr), m_curr_extruder_id (-1), + m_cached_extruder_idx(0), m_single_extruder_multi_material(false), m_last_acceleration(0), m_max_acceleration(0),m_last_travel_acceleration(0), m_max_travel_acceleration(0), m_last_jerk(0), m_max_jerk_x(0), m_max_jerk_y(0), @@ -135,6 +136,8 @@ public: bool m_single_extruder_multi_material; std::vector m_curr_filament_extruder; int m_curr_extruder_id; + // Motion uses the global/base process variant until a filament becomes active. + size_t m_cached_extruder_idx; unsigned int m_last_acceleration; unsigned int m_last_travel_acceleration; std::vector m_max_travel_acceleration;