From f18bf8b73c26a79ae797e3cc321fd592d0a38e96 Mon Sep 17 00:00:00 2001 From: Raul Date: Sat, 29 Nov 2025 17:42:17 -0800 Subject: [PATCH 1/5] port prusa features: consistent surface cooling and short travel acceleration --- src/libslic3r/GCode.cpp | 32 ++++- src/libslic3r/GCode/CoolingBuffer.cpp | 128 +++++++++++++++++- src/libslic3r/GCode/GCodeEditor.cpp | 7 + src/libslic3r/GCode/GCodeEditor.hpp | 185 +++++++++++++++++++++++++- src/libslic3r/GCodeWriter.cpp | 39 +++++- src/libslic3r/GCodeWriter.hpp | 6 + src/libslic3r/Preset.cpp | 4 +- src/libslic3r/PrintConfig.cpp | 50 +++++++ src/libslic3r/PrintConfig.hpp | 10 ++ src/slic3r/GUI/OptionsGroup.cpp | 25 ++++ src/slic3r/GUI/Tab.cpp | 13 ++ 11 files changed, 482 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3355feb36b..ebe9dc5d6e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2717,11 +2717,16 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato for (auto value : m_config.travel_acceleration.values) { travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); } + std::vector short_travel_accelerations; + for (auto value : m_config.short_travel_acceleration.values) { + short_travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); + } std::vector first_layer_travel_accelerations; for (auto value : m_config.initial_layer_travel_acceleration.values) { first_layer_travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); } m_writer.set_travel_acceleration(travel_accelerations); + m_writer.set_short_travel_acceleration(short_travel_accelerations); m_writer.set_first_layer_travel_acceleration(first_layer_travel_accelerations); // OrcaSlicer: calib if (print.calib_params().mode == CalibMode::Calib_PA_Line) { @@ -6352,6 +6357,23 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string // use G1 because we rely on paths being straight (G0 may make round paths) if (travel.size() >= 2) { + // Determine if we should use short travel acceleration + // This helps reduce VFA (Vertical Fine Artifacts) by using lower acceleration + // for short travels near external perimeters + bool use_short_travel_accel = false; + if (!this->on_first_layer()) { + // Check if short travel acceleration is enabled (value > 0) + unsigned int extruder_id = m_writer.filament()->id(); + auto& short_accel = m_writer.get_short_travel_acceleration(); + if (extruder_id < short_accel.size() && short_accel[extruder_id] > 0) { + // Use short travel acceleration for external perimeters with short travel distance + double travel_length = unscaled(travel.length()); + double min_travel = FILAMENT_CONFIG(retraction_minimum_travel); + use_short_travel_accel = (role == erExternalPerimeter || role == erOverhangPerimeter) && + travel_length < min_travel; + } + } + // OrcaSlicer if (this->on_first_layer()) { if (m_config.default_jerk.value > 0 && m_config.initial_layer_jerk.value > 0 && !this->is_BBL_Printer()) @@ -6362,13 +6384,13 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string if (m_spiral_vase) { // No lazy z lift for spiral vase mode for (size_t i = 1; i < travel.size(); ++i) - gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment); + gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment, use_short_travel_accel); } else { if (travel.size() == 2) { // No extra movements emitted by avoid_crossing_perimeters, simply move to the end point with z change const auto &dest2d = this->point_to_gcode(travel.points.back()); Vec3d dest3d(dest2d(0), dest2d(1), z == DBL_MAX ? m_nominal_z : z); - gcode += m_writer.travel_to_xyz(dest3d, comment); + gcode += m_writer.travel_to_xyz(dest3d, comment, use_short_travel_accel); } else { // Extra movements emitted by avoid_crossing_perimeters, lift the z to normal height at the beginning, then apply the z // ratio at the last point @@ -6377,15 +6399,15 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string // Lift to normal z at beginning Vec2d dest2d = this->point_to_gcode(travel.points[i]); Vec3d dest3d(dest2d(0), dest2d(1), m_nominal_z); - gcode += m_writer.travel_to_xyz(dest3d, comment); + gcode += m_writer.travel_to_xyz(dest3d, comment, use_short_travel_accel); } else if (z != DBL_MAX && i == travel.size() - 1) { // Apply z_ratio for the very last point Vec2d dest2d = this->point_to_gcode(travel.points[i]); Vec3d dest3d(dest2d(0), dest2d(1), z); - gcode += m_writer.travel_to_xyz(dest3d, comment); + gcode += m_writer.travel_to_xyz(dest3d, comment, use_short_travel_accel); } else { // For all points in between, no z change - gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment ); + gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment, use_short_travel_accel); } } } diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 87e1937dfc..857c05740e 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -101,6 +101,88 @@ static inline float extruder_range_slow_down_proportional(std::vector::iterator it_begin, + std::vector::iterator it_end, + float time_stretch, + AdjustableFeatureType additional_slowdown_features) +{ + if (time_stretch <= 0.f) + return 0.f; + + // Slow down. Try to equalize the feedrates for the allowed feature types. + std::vector by_min_print_speed(it_begin, it_end); + + // Find the highest adjustable feedrate among the extruders for allowed features. + float feedrate = 0.f; + for (PerExtruderAdjustments *adj : by_min_print_speed) { + adj->idx_line_begin = 0; + adj->idx_line_end = 0; + for (size_t i = 0; i < adj->n_lines_adjustable; ++i) { + const CoolingLine &line = adj->lines[i]; + if (line.adjustable(additional_slowdown_features) && line.feedrate > feedrate) + feedrate = line.feedrate; + } + } + + if (feedrate == 0.f) + return time_stretch; // No adjustable features found + + // Sort by slow_down_min_speed, maximum speed first. + std::sort(by_min_print_speed.begin(), by_min_print_speed.end(), + [](const PerExtruderAdjustments *p1, const PerExtruderAdjustments *p2) { + return p1->slow_down_min_speed > p2->slow_down_min_speed; + }); + + // Slow down, fast moves first. + for (auto adj = by_min_print_speed.begin(); adj != by_min_print_speed.end();) { + float feedrate_limit = (*adj)->slow_down_min_speed; + float time_stretch_max = 0.f; + + for (auto it = adj; it != by_min_print_speed.end(); ++it) + time_stretch_max += (*it)->time_stretch_when_slowing_down_to_feedrate(feedrate_limit, additional_slowdown_features); + + if (time_stretch_max >= time_stretch) { + // We can achieve the required time stretch by slowing down to some feedrate above feedrate_limit + // Binary search for the right feedrate + float feedrate_high = feedrate; + float feedrate_low = feedrate_limit; + for (int iter = 0; iter < 20; ++iter) { + float feedrate_mid = (feedrate_high + feedrate_low) / 2.f; + float stretch = 0.f; + for (auto it = adj; it != by_min_print_speed.end(); ++it) + stretch += (*it)->time_stretch_when_slowing_down_to_feedrate(feedrate_mid, additional_slowdown_features); + if (stretch < time_stretch) + feedrate_high = feedrate_mid; + else + feedrate_low = feedrate_mid; + if (std::abs(stretch - time_stretch) < 0.01f) + break; + } + for (auto it = adj; it != by_min_print_speed.end(); ++it) + (*it)->slow_down_to_feedrate(feedrate_low, additional_slowdown_features); + return 0.f; // Time stretch achieved + } else { + // Slow down to minimum for these features + time_stretch -= time_stretch_max; + for (auto it = adj; it != by_min_print_speed.end(); ++it) + (*it)->slow_down_to_feedrate(feedrate_limit, additional_slowdown_features); + } + + // Skip extruders with nearly the same slow_down_min_speed + auto next = adj; + for (++next; next != by_min_print_speed.end() && (*next)->slow_down_min_speed > (*adj)->slow_down_min_speed - EPSILON; ++next) + ; + adj = next; + } + + return time_stretch; // Return remaining time stretch that couldn't be achieved +} + // Slow down an extruder range to slow_down_layer_time. // Return the total time for the complete layer. static inline void extruder_range_slow_down_non_proportional(std::vector::iterator it_begin, @@ -184,13 +266,33 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector 0) { by_slowdown_time.emplace_back(&adj); + + // For ConsistentSurface logic, prepare the non-adjustable segments + if (adj.cooling_slowdown_logic == cslConsistentSurface) { + any_consistent_surface = true; + // Initialize adjustable fields for all lines + for (CoolingLine &line : adj.lines) { + if (line.type & CoolingLine::TYPE_ADJUSTABLE) { + line.adjustable_length = line.length; + line.adjustable_time = line.time; + line.adjustable_time_max = line.time_max; + } + } + // Create non-adjustable segments at the end of perimeter loops + adj.create_non_adjustable_segments(adj.cooling_perimeter_transition_distance); + } + if (!m_cooling_logic_proportional) // sorts the lines, also sets adj.time_non_adjustable adj.sort_lines_by_decreasing_feedrate(); @@ -214,10 +316,28 @@ float CoolingBuffer::calculate_layer_slowdown(std::vectortime_maximum; if (max_time > slow_down_layer_time) { - if (m_cooling_logic_proportional) + float time_stretch = slow_down_layer_time - total; + + // Check if this extruder uses ConsistentSurface logic + if (adj.cooling_slowdown_logic == cslConsistentSurface) { + // ConsistentSurface: Two-phase slowdown + // Phase 1: Try slowing down only non-external perimeter features (infill, internal perimeters) + float remaining = extruder_range_slow_down_consistent_surface( + cur_begin, by_slowdown_time.end(), time_stretch, AdjustableFeatureType::None); + + // Phase 2: If still not enough time, allow external perimeter and first internal slowdown + if (remaining > 0.f) { + extruder_range_slow_down_consistent_surface( + cur_begin, by_slowdown_time.end(), remaining, + AdjustableFeatureType::ExternalPerimeters | AdjustableFeatureType::FirstInternalPerimeters); + } + } else if (m_cooling_logic_proportional) { + // Uniform cooling with proportional slowdown extruder_range_slow_down_proportional(cur_begin, by_slowdown_time.end(), elapsed_time_total0, total, slow_down_layer_time); - else - extruder_range_slow_down_non_proportional(cur_begin, by_slowdown_time.end(), slow_down_layer_time - total); + } else { + // Uniform cooling with non-proportional slowdown + extruder_range_slow_down_non_proportional(cur_begin, by_slowdown_time.end(), time_stretch); + } } else { // Slow down to maximum possible. for (auto it = cur_begin; it != by_slowdown_time.end(); ++it) (*it)->slowdown_to_minimum_feedrate(true); diff --git a/src/libslic3r/GCode/GCodeEditor.cpp b/src/libslic3r/GCode/GCodeEditor.cpp index 5e0b3e6d6f..056ecf15f7 100644 --- a/src/libslic3r/GCode/GCodeEditor.cpp +++ b/src/libslic3r/GCode/GCodeEditor.cpp @@ -113,6 +113,13 @@ std::vector GCodeEditor::parse_layer_gcode( const adj.cooling_slow_down_enabled = m_config.slow_down_for_layer_cooling.get_at(extruder_id); adj.slow_down_layer_time = float(m_config.slow_down_layer_time.get_at(extruder_id)); adj.slow_down_min_speed = float(m_config.slow_down_min_speed.get_at(extruder_id)); + + // Read ConsistentSurface cooling settings + if (m_config.cooling_slowdown_logic.values.size() > extruder_id) + adj.cooling_slowdown_logic = static_cast(m_config.cooling_slowdown_logic.values[extruder_id]); + if (m_config.cooling_perimeter_transition_distance.values.size() > extruder_id) + adj.cooling_perimeter_transition_distance = float(m_config.cooling_perimeter_transition_distance.values[extruder_id]); + map_extruder_to_per_extruder_adjustment[extruder_id] = i; } diff --git a/src/libslic3r/GCode/GCodeEditor.hpp b/src/libslic3r/GCode/GCodeEditor.hpp index 85dc69e05e..282a9c84f8 100644 --- a/src/libslic3r/GCode/GCodeEditor.hpp +++ b/src/libslic3r/GCode/GCodeEditor.hpp @@ -2,9 +2,11 @@ #define slic3r_GCodeEditer_hpp_ #include "../libslic3r.h" +#include "../PrintConfig.hpp" #include #include #include +#include #include #include @@ -13,6 +15,26 @@ namespace Slic3r { class GCode; class Layer; +// Feature types that can be adjusted during cooling slowdown +// Used by ConsistentSurface logic to control which features are slowed first +enum class AdjustableFeatureType : uint32_t { + None = 0, + ExternalPerimeters = 1 << 0, + FirstInternalPerimeters = 1 << 1, +}; + +inline AdjustableFeatureType operator|(AdjustableFeatureType a, AdjustableFeatureType b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +inline AdjustableFeatureType operator&(AdjustableFeatureType a, AdjustableFeatureType b) { + return static_cast(static_cast(a) & static_cast(b)); +} + +inline bool operator!(AdjustableFeatureType a) { + return static_cast(a) == 0; +} + struct CoolingLine { enum Type { @@ -38,13 +60,16 @@ struct CoolingLine TYPE_OBJECT_END = 1 << 17, TYPE_SET_FAN_CHANGING_FILAMENT = 1 << 18, TYPE_NOT_SET_FAN_CHANGING_FILAMENT = 1 << 19, - + // Internal perimeter types for ConsistentSurface cooling logic + TYPE_INTERNAL_PERIMETER = 1 << 20, + TYPE_FIRST_INTERNAL_PERIMETER = 1 << 21, }; CoolingLine(unsigned int type, size_t line_start, size_t line_end) : type(type), line_start(line_start), line_end(line_end), length(0.f), feedrate(0.f), origin_feedrate(0.f), time(0.f), time_max(0.f), slowdown(false) {} + // Legacy method - used by existing code bool adjustable(bool slowdown_external_perimeters) const { return (this->type & TYPE_ADJUSTABLE) && (!(this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) && this->time < this->time_max; @@ -52,6 +77,28 @@ struct CoolingLine bool adjustable() const { return (this->type & TYPE_ADJUSTABLE) && this->time < this->time_max; } + // New method for ConsistentSurface logic - allows fine-grained control over which features are adjustable + bool adjustable(AdjustableFeatureType additional_slowdown_features) const { + if (!(this->type & TYPE_ADJUSTABLE) || this->adjustable_time >= this->adjustable_time_max) { + return false; + } + + if (this->type & TYPE_EXTERNAL_PERIMETER) { + return (additional_slowdown_features & AdjustableFeatureType::ExternalPerimeters) != AdjustableFeatureType::None; + } + + if (this->type & TYPE_FIRST_INTERNAL_PERIMETER) { + return (additional_slowdown_features & AdjustableFeatureType::FirstInternalPerimeters) != AdjustableFeatureType::None; + } + + return true; + } + + // Time calculations for ConsistentSurface logic + inline float total_time() const { return this->adjustable_time + this->non_adjustable_time; } + inline float total_length() const { return this->adjustable_length + this->non_adjustable_length; } + inline float total_time_max() const { return this->adjustable_time_max + this->non_adjustable_time; } + size_t type; // Start of this line at the G-code snippet. size_t line_start; @@ -75,6 +122,16 @@ struct CoolingLine bool outwall_smooth_mark = false; int object_id = -1; int cooling_node_id = -1; + + // For ConsistentSurface logic - split adjustable vs non-adjustable portions + float adjustable_length = 0.f; + float non_adjustable_length = 0.f; + float adjustable_time = 0.f; + float non_adjustable_time = 0.f; + float adjustable_time_max = 0.f; + + // Perimeter index: 0 = external, 1 = first internal, 2+ = deeper internal + std::optional perimeter_index; }; struct PerExtruderAdjustments @@ -204,6 +261,127 @@ struct PerExtruderAdjustments return times; } + // --- ConsistentSurface cooling methods --- + + // Calculate the maximum time stretch when slowing down to min_feedrate, + // considering only features allowed by additional_slowdown_features. + float time_stretch_when_slowing_down_to_feedrate(float min_feedrate, AdjustableFeatureType additional_slowdown_features) const + { + float time_stretch = 0.f; + for (size_t i = 0; i < n_lines_adjustable; ++i) { + const CoolingLine &line = lines[i]; + if (line.adjustable(additional_slowdown_features) && line.feedrate > min_feedrate) + time_stretch += line.adjustable_time * (line.feedrate / min_feedrate - 1.f); + } + return time_stretch; + } + + // Slow down all lines matching the feature type to min_feedrate. + void slow_down_to_feedrate(float min_feedrate, AdjustableFeatureType additional_slowdown_features) + { + for (size_t i = 0; i < n_lines_adjustable; ++i) { + CoolingLine &line = lines[i]; + if (line.adjustable(additional_slowdown_features) && line.feedrate > min_feedrate) { + line.adjustable_time = line.adjustable_length / min_feedrate; + line.time = line.adjustable_time + line.non_adjustable_time; + line.feedrate = min_feedrate; + line.slowdown = true; + } + } + } + + // Calculate maximum time after slowdown for features matching the type. + float maximum_time_after_slowdown(AdjustableFeatureType additional_slowdown_features) const + { + float time_total = 0.f; + for (const CoolingLine &line : lines) { + if (line.adjustable(additional_slowdown_features)) { + if (line.adjustable_time_max == FLT_MAX) + return FLT_MAX; + time_total += line.adjustable_time_max + line.non_adjustable_time; + } else { + time_total += line.time; + } + } + return time_total; + } + + // Calculate adjustable time for features matching the type. + float adjustable_time_for_features(AdjustableFeatureType additional_slowdown_features) const + { + float time_total = 0.f; + for (const CoolingLine &line : lines) { + if (line.adjustable(additional_slowdown_features)) + time_total += line.adjustable_time; + } + return time_total; + } + + // Slow down to minimum feedrate for features matching the type. + float slowdown_to_minimum_feedrate(AdjustableFeatureType additional_slowdown_features) + { + float time_total = 0.f; + for (CoolingLine &line : lines) { + if (line.adjustable(additional_slowdown_features)) { + line.slowdown = true; + line.adjustable_time = line.adjustable_time_max; + line.time = line.adjustable_time + line.non_adjustable_time; + if (line.adjustable_length > 0) + line.feedrate = line.adjustable_length / line.adjustable_time; + } + time_total += line.time; + } + return time_total; + } + + // Create non-adjustable segments at the end of perimeter loops for transition smoothing. + // This preserves speed in the last 'non_adjustable_length' mm of each perimeter. + void create_non_adjustable_segments(float non_adjustable_length) + { + if (non_adjustable_length <= 0) + return; + + // Process lines in reverse to accumulate length from the end of each perimeter loop + float accumulated_length = 0.f; + for (auto it = lines.rbegin(); it != lines.rend(); ++it) { + CoolingLine &line = *it; + + // Reset accumulator at perimeter boundaries (non-adjustable lines or different feature types) + if (!(line.type & CoolingLine::TYPE_ADJUSTABLE) || + (line.type & CoolingLine::TYPE_EXTRUDE_END)) { + accumulated_length = 0.f; + continue; + } + + // Initialize adjustable fields if not set + if (line.adjustable_length == 0.f && line.length > 0.f) { + line.adjustable_length = line.length; + line.adjustable_time = line.time; + line.adjustable_time_max = line.time_max; + } + + float remaining_non_adjustable = non_adjustable_length - accumulated_length; + if (remaining_non_adjustable > 0.f && line.adjustable_length > 0.f) { + float convert_length = std::min(line.adjustable_length, remaining_non_adjustable); + float convert_ratio = convert_length / line.adjustable_length; + + line.non_adjustable_length += convert_length; + line.non_adjustable_time += line.adjustable_time * convert_ratio; + line.adjustable_length -= convert_length; + line.adjustable_time -= line.adjustable_time * convert_ratio; + line.adjustable_time_max = (line.adjustable_length > 0.f && slow_down_min_speed > 0.f) + ? line.adjustable_length / slow_down_min_speed + : 0.f; + + accumulated_length += convert_length; + } else { + accumulated_length += line.length; + } + } + } + + // --- End ConsistentSurface cooling methods --- + // Extruder, for which the G-code will be adjusted. unsigned int extruder_id = 0; // Is the cooling slow down logic enabled for this extruder's material? @@ -213,6 +391,11 @@ struct PerExtruderAdjustments // Minimum print speed allowed for this extruder. float slow_down_min_speed = 0.f; + // Cooling slowdown logic type for this extruder (Uniform or ConsistentSurface) + CoolingSlowdownLogicType cooling_slowdown_logic = cslUniformCooling; + // Distance before perimeters where speed transitions back to normal + float cooling_perimeter_transition_distance = 5.0f; + // Parsed lines. std::vector lines; // The following two values are set by sort_lines_by_decreasing_feedrate(): diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 6bb3ea1c3a..f438d588ca 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -175,6 +175,11 @@ void GCodeWriter::set_travel_acceleration(const std::vector& accel m_travel_accelerations = accelerations; } +void GCodeWriter::set_short_travel_acceleration(const std::vector& accelerations) +{ + m_short_travel_accelerations = accelerations; +} + void GCodeWriter::reset_last_acceleration() { m_last_acceleration = 0; @@ -196,6 +201,11 @@ std::string GCodeWriter::set_extrude_acceleration() } std::string GCodeWriter::set_travel_acceleration() +{ + return set_travel_acceleration(false); +} + +std::string GCodeWriter::set_travel_acceleration(bool use_short_travel_acceleration) { std::vector travel_accelerations = m_is_first_layer ? m_first_layer_travel_accelerations : m_travel_accelerations; if (travel_accelerations.empty()) @@ -205,7 +215,16 @@ std::string GCodeWriter::set_travel_acceleration() if (!cur_filament) return std::string(); - return set_acceleration_impl(travel_accelerations[cur_filament->extruder_id()]); + unsigned int extruder_id = cur_filament->extruder_id(); + + // Use short travel acceleration if requested and available + if (use_short_travel_acceleration && + extruder_id < m_short_travel_accelerations.size() && + m_short_travel_accelerations[extruder_id] > 0) { + return set_acceleration_impl(m_short_travel_accelerations[extruder_id]); + } + + return set_acceleration_impl(travel_accelerations[extruder_id]); } std::string GCodeWriter::set_acceleration_impl(unsigned int acceleration) @@ -377,6 +396,11 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s } std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment) +{ + return travel_to_xy(point, comment, false); +} + +std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment, bool use_short_travel_acceleration) { m_pos(0) = point(0); m_pos(1) = point(1); @@ -390,7 +414,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com w.emit_f(this->config.travel_speed.get_at(get_config_idx_for_filament(this->config, filament()->id())) * 60.0); //BBS w.emit_comment(GCodeWriter::full_gcode_comment, comment); - return set_travel_acceleration() + w.string(); + return set_travel_acceleration(use_short_travel_acceleration) + w.string(); } /* If this method is called more than once before calling unlift(), @@ -468,6 +492,11 @@ std::string GCodeWriter::eager_lift(const LiftType type, bool tool_change) } std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment) +{ + return travel_to_xyz(point, comment, false); +} + +std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment, bool use_short_travel_acceleration) { // FIXME: This function was not being used when travel_speed_z was separated (bd6badf). // Calculation of feedrate was not updated accordingly. If you want to use @@ -549,7 +578,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co } m_pos = dest_point; this->set_current_position_clear(true); - return set_travel_acceleration() + slop_move + xy_z_move; + return set_travel_acceleration(use_short_travel_acceleration) + slop_move + xy_z_move; } else if (!this->will_move_z(point(2))) { double nominal_z = m_pos(2) - m_lifted; @@ -560,7 +589,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co m_lifted = 0.; //BBS this->set_current_position_clear(true); - return this->travel_to_xy(to_2d(point)); + return this->travel_to_xy(to_2d(point), std::string(), use_short_travel_acceleration); } else { /* In all the other cases, we perform an actual XYZ move and cancel @@ -589,7 +618,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co m_pos = dest_point; this->set_current_position_clear(true); - return set_travel_acceleration() + out_string; + return set_travel_acceleration(use_short_travel_acceleration) + out_string; } std::string GCodeWriter::travel_to_z(double z, const std::string &comment) diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 36786fa027..38b743d1e7 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -56,8 +56,10 @@ class GCodeWriter { std::string set_chamber_temperature(int temperature, bool wait = false); void set_acceleration(unsigned int acceleration); void set_travel_acceleration(const std::vector& travel_accelerations); + void set_short_travel_acceleration(const std::vector& short_travel_accelerations); void reset_last_acceleration(); std::vector &get_travel_acceleration() { return m_travel_accelerations; } + std::vector &get_short_travel_acceleration() { return m_short_travel_accelerations; } void set_first_layer_travel_acceleration(const std::vector& travel_accelerations); void set_first_layer(bool is_first_layer); std::string set_pressure_advance(double pa) const; @@ -75,7 +77,9 @@ class GCodeWriter { std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()); double get_current_speed() { return m_current_speed; }; std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string()); + std::string travel_to_xy(const Vec2d &point, const std::string &comment, bool use_short_travel_acceleration); std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string()); + std::string travel_to_xyz(const Vec3d &point, const std::string &comment, bool use_short_travel_acceleration); std::string travel_to_z(double z, const std::string &comment = std::string()); bool will_move_z(double z) const; std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string(), bool force_no_extrusion = false); @@ -126,6 +130,7 @@ class GCodeWriter { private: std::string set_extrude_acceleration(); std::string set_travel_acceleration(); + std::string set_travel_acceleration(bool use_short_travel_acceleration); std::string set_acceleration_impl(unsigned int acceleration); private: @@ -166,6 +171,7 @@ class GCodeWriter { bool m_is_first_layer{false}; unsigned int m_acceleration{0}; std::vector m_travel_accelerations; // multi extruder, extruder size + std::vector m_short_travel_accelerations; // For short travels near external perimeters (VFA reduction) std::vector m_first_layer_travel_accelerations; // multi extruder, extruder size std::string _travel_to_z(double z, const std::string &comment,bool tool_change=false); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3fb1278084..c1eb237e2b 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -934,7 +934,7 @@ static std::vector s_Preset_print_options { "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap","support_interface_speed", "bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration", - "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "travel_acceleration", "initial_layer_travel_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration", + "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "travel_acceleration", "short_travel_acceleration", "initial_layer_travel_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration", "accel_to_decel_enable", "accel_to_decel_factor", "skirt_loops", "skirt_distance", "skirt_height", "draft_shield", "brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers", @@ -996,7 +996,7 @@ static std::vector s_Preset_filament_options{/*"filament_colour", * "counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit", // "bed_type", //BBS:temperature_vitrification - "temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "no_slow_down_for_cooling_on_outwalls", "fan_min_speed","filament_ramming_travel_time","filament_pre_cooling_temperature","filament_ramming_travel_time_nc","filament_pre_cooling_temperature_nc", + "temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "no_slow_down_for_cooling_on_outwalls", "cooling_slowdown_logic", "cooling_perimeter_transition_distance", "fan_min_speed","filament_ramming_travel_time","filament_pre_cooling_temperature","filament_ramming_travel_time_nc","filament_pre_cooling_temperature_nc", "fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "pre_start_fan_time", "overhang_fan_threshold", "overhang_threshold_participating_cooling","close_fan_the_first_x_layers","first_x_layer_fan_speed", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed", "filament_start_gcode", "filament_end_gcode", //exhaust fan control diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 157fa0d471..e2874e862a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -376,6 +376,13 @@ static const t_config_enum_values s_keys_map_OverhangThresholdParticipatingCooli }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(OverhangThresholdParticipatingCooling) +// Cooling slowdown logic for VFA reduction (ported from PrusaSlicer 2.9.3) +static const t_config_enum_values s_keys_map_CoolingSlowdownLogicType = { + { "uniform_cooling", cslUniformCooling }, + { "consistent_surface", cslConsistentSurface }, +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(CoolingSlowdownLogicType) + // BBS static const t_config_enum_values s_keys_map_BedType = { { "Default Plate", btDefault }, @@ -1408,6 +1415,35 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBools{false}); + // Cooling slowdown logic - ported from PrusaSlicer 2.9.3 for VFA reduction + def = this->add("cooling_slowdown_logic", coEnums); + def->label = L("Cooling slowdown logic"); + def->tooltip = L("Determines how the printer slows down when minimum layer time isn't reached.\n\n" + "'Uniform cooling' slows down all print features equally (current default behavior).\n\n" + "'Consistent surface' prioritizes slowing infill and internal perimeters first, " + "preserving external perimeter speed for better surface finish on glossy filaments. " + "This helps reduce VFA (Vertical Fine Artifacts) and maintains consistent surface shine."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("uniform_cooling"); + def->enum_values.push_back("consistent_surface"); + def->enum_labels.push_back(L("Uniform cooling")); + def->enum_labels.push_back(L("Consistent surface")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnumsGeneric{(int)cslUniformCooling}); + + def = this->add("cooling_perimeter_transition_distance", coFloats); + def->label = L("Perimeter transition distance"); + def->tooltip = L("Distance in millimeters before the end of slowed perimeters where the original " + "print speed is gradually restored. This reduces quality issues when transitioning " + "from slowed features to fast external perimeter printing.\n\n" + "Only applies when 'Consistent surface' cooling logic is selected.\n" + "Recommended value: 5-10mm. Set to 0 to disable."); + def->sidetext = L("mm"); + def->min = 0; + def->max = 50; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloats{5.0}); + def = this->add("default_acceleration", coFloats); def->label = L("Normal printing"); def->tooltip = L("The default acceleration of both normal printing and travel except initial layer"); @@ -1426,6 +1462,20 @@ void PrintConfigDef::init_fff_params() def->nullable = true; def->set_default_value(new ConfigOptionFloatsNullable{500.0}); + // Short travel acceleration - ported from PrusaSlicer 2.9.3 for VFA reduction + def = this->add("short_travel_acceleration", coFloats); + def->label = L("Short travel"); + def->tooltip = L("Acceleration used for short travel moves near external perimeters. " + "Short travels are moves shorter than the 'Retraction minimum travel' distance.\n\n" + "Lower values (e.g., 250-500 mm/s²) reduce ringing artifacts on sharp corners " + "without significantly impacting print time.\n\n" + "Set to 0 to disable (uses normal travel acceleration)."); + def->sidetext = "mm/s²"; + def->min = 0; + def->mode = comAdvanced; + def->nullable = true; + def->set_default_value(new ConfigOptionFloatsNullable{0}); + def = this->add("initial_layer_travel_acceleration", coFloats); def->label = L("Initial layer travel"); def->tooltip = L("The acceleration of travel of initial layer"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index e8c7b6cd00..ffe5120fb7 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -237,6 +237,13 @@ enum OverhangThresholdParticipatingCooling { Overhang_threshold_participating_cooling_bridge }; +// Cooling slowdown logic - determines how printer slows down for layer cooling +// Ported from PrusaSlicer 2.9.3 for VFA reduction +enum CoolingSlowdownLogicType { + cslUniformCooling = 0, // Default: slow down all features equally + cslConsistentSurface = 1, // Prioritize slowing infill/internal perimeters first +}; + // BBS enum BedType { btDefault = 0, @@ -1230,8 +1237,11 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionInt, other_layers_print_sequence_nums)) ((ConfigOptionBools, slow_down_for_layer_cooling)) ((ConfigOptionBools, no_slow_down_for_cooling_on_outwalls)) + ((ConfigOptionEnumsGeneric, cooling_slowdown_logic)) + ((ConfigOptionFloats, cooling_perimeter_transition_distance)) ((ConfigOptionFloatsNullable, default_acceleration)) ((ConfigOptionFloatsNullable, travel_acceleration)) + ((ConfigOptionFloatsNullable, short_travel_acceleration)) ((ConfigOptionFloatsNullable, initial_layer_travel_acceleration)) ((ConfigOptionFloatsNullable, inner_wall_acceleration)) ((ConfigOptionFloatsOrPercentsNullable, sparse_infill_acceleration)) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 36e7040f2a..ba8af5a2d3 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -959,6 +959,31 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config wxString text_value = wxString(""); const ConfigOptionDef* opt = config.def()->get(opt_key); + // If the option doesn't exist in the config, return the default value from the definition + if (!config.has(opt_key)) { + if (opt && opt->default_value) { + switch (opt->type) { + case coFloat: + case coPercent: + return double_to_string(opt->default_value->getFloat()); + case coFloats: + case coPercents: + case coInts: + case coEnums: + return opt->default_value->getInt(); + case coBool: + case coBools: + return opt->default_value->getBool(); + case coString: + case coStrings: + return wxString(""); + default: + return opt->default_value->getInt(); + } + } + return 0; + } + if (opt->nullable) { switch (opt->type) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bb9073ded6..79053f67a6 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2695,6 +2695,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Acceleration"), L"param_acceleration", 15); optgroup->append_single_option_line("default_acceleration", "", 0); optgroup->append_single_option_line("travel_acceleration", "", 0); + optgroup->append_single_option_line("short_travel_acceleration", "", 0); optgroup->append_single_option_line("initial_layer_travel_acceleration", "", 0); optgroup->append_single_option_line("initial_layer_acceleration", "", 0); optgroup->append_single_option_line("outer_wall_acceleration", "", 0); @@ -3942,6 +3943,8 @@ void TabFilament::build() optgroup->append_single_option_line("reduce_fan_stop_start_freq", "auto-cooling"); optgroup->append_single_option_line("slow_down_for_layer_cooling", "auto-cooling"); optgroup->append_single_option_line("no_slow_down_for_cooling_on_outwalls", "auto-cooling"); + optgroup->append_single_option_line("cooling_slowdown_logic", "auto-cooling"); + optgroup->append_single_option_line("cooling_perimeter_transition_distance", "auto-cooling"); optgroup->append_single_option_line("slow_down_min_speed","auto-cooling"); optgroup->append_single_option_line("enable_overhang_bridge_fan", "auto-cooling"); @@ -4088,6 +4091,16 @@ void TabFilament::toggle_options() bool cooling = m_config->opt_bool("slow_down_for_layer_cooling", 0); toggle_option("slow_down_min_speed", cooling); toggle_option("no_slow_down_for_cooling_on_outwalls", cooling); + toggle_option("cooling_slowdown_logic", cooling); + + // Only show perimeter transition distance when ConsistentSurface is selected + bool consistent_surface = false; + if (cooling) { + auto* opt = m_config->option("cooling_slowdown_logic"); + if (opt && !opt->values.empty()) + consistent_surface = opt->values[0] == (int)cslConsistentSurface; + } + toggle_option("cooling_perimeter_transition_distance", consistent_surface); bool has_enable_overhang_bridge_fan = m_config->opt_bool("enable_overhang_bridge_fan", 0); for (auto el : {"overhang_fan_speed", "pre_start_fan_time", "overhang_fan_threshold"}) From 710ea489bce153bd1ded4d46aca1a118ce2d906d Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 16 Dec 2025 15:22:22 -0800 Subject: [PATCH 2/5] Enable features for developer mode only --- src/libslic3r/PrintConfig.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index e2874e862a..819c749b04 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1428,7 +1428,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("consistent_surface"); def->enum_labels.push_back(L("Uniform cooling")); def->enum_labels.push_back(L("Consistent surface")); - def->mode = comAdvanced; + def->mode = comDevelop; def->set_default_value(new ConfigOptionEnumsGeneric{(int)cslUniformCooling}); def = this->add("cooling_perimeter_transition_distance", coFloats); @@ -1441,8 +1441,8 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->max = 50; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats{5.0}); + def->mode = comDevelop; + def->set_default_value(new ConfigOptionFloats{10.0}); def = this->add("default_acceleration", coFloats); def->label = L("Normal printing"); @@ -1472,7 +1472,7 @@ void PrintConfigDef::init_fff_params() "Set to 0 to disable (uses normal travel acceleration)."); def->sidetext = "mm/s²"; def->min = 0; - def->mode = comAdvanced; + def->mode = comDevelop; def->nullable = true; def->set_default_value(new ConfigOptionFloatsNullable{0}); From 34198e9927e07e68fb92ff40aa27ee0037bb1d75 Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 26 Dec 2025 09:48:27 -0800 Subject: [PATCH 3/5] move config vars to JSON files. Better naming to be consistent --- .../BBL/filament/fdm_filament_common.json | 6 +++++ .../BBL/process/fdm_process_common.json | 3 +++ src/libslic3r/GCode.cpp | 6 ++--- src/libslic3r/GCodeWriter.cpp | 10 ++++---- src/libslic3r/GCodeWriter.hpp | 6 ++--- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 3 ++- src/libslic3r/PrintConfig.hpp | 2 +- src/slic3r/GUI/OptionsGroup.cpp | 25 ------------------- src/slic3r/GUI/Tab.cpp | 2 +- 10 files changed, 25 insertions(+), 40 deletions(-) diff --git a/resources/profiles/BBL/filament/fdm_filament_common.json b/resources/profiles/BBL/filament/fdm_filament_common.json index 1f023be1d8..fd20c92eb8 100644 --- a/resources/profiles/BBL/filament/fdm_filament_common.json +++ b/resources/profiles/BBL/filament/fdm_filament_common.json @@ -267,6 +267,12 @@ "no_slow_down_for_cooling_on_outwalls": [ "0" ], + "cooling_slowdown_logic": [ + "uniform_cooling" + ], + "cooling_perimeter_transition_distance": [ + "10" + ], "slow_down_layer_time": [ "8" ], diff --git a/resources/profiles/BBL/process/fdm_process_common.json b/resources/profiles/BBL/process/fdm_process_common.json index cc28ef10b5..12516ddfc5 100644 --- a/resources/profiles/BBL/process/fdm_process_common.json +++ b/resources/profiles/BBL/process/fdm_process_common.json @@ -159,6 +159,9 @@ "travel_acceleration": [ "10000" ], + "travel_short_distance_acceleration": [ + "250" + ], "travel_speed": [ "400" ], diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ebe9dc5d6e..e111681257 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2718,7 +2718,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); } std::vector short_travel_accelerations; - for (auto value : m_config.short_travel_acceleration.values) { + for (auto value : m_config.travel_short_distance_acceleration.values) { short_travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); } std::vector first_layer_travel_accelerations; @@ -2726,7 +2726,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato first_layer_travel_accelerations.emplace_back((unsigned int) floor(value + 0.5)); } m_writer.set_travel_acceleration(travel_accelerations); - m_writer.set_short_travel_acceleration(short_travel_accelerations); + m_writer.set_travel_short_acceleration(short_travel_accelerations); m_writer.set_first_layer_travel_acceleration(first_layer_travel_accelerations); // OrcaSlicer: calib if (print.calib_params().mode == CalibMode::Calib_PA_Line) { @@ -6364,7 +6364,7 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string if (!this->on_first_layer()) { // Check if short travel acceleration is enabled (value > 0) unsigned int extruder_id = m_writer.filament()->id(); - auto& short_accel = m_writer.get_short_travel_acceleration(); + auto& short_accel = m_writer.get_travel_short_acceleration(); if (extruder_id < short_accel.size() && short_accel[extruder_id] > 0) { // Use short travel acceleration for external perimeters with short travel distance double travel_length = unscaled(travel.length()); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index f438d588ca..93d8e44f96 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -175,9 +175,9 @@ void GCodeWriter::set_travel_acceleration(const std::vector& accel m_travel_accelerations = accelerations; } -void GCodeWriter::set_short_travel_acceleration(const std::vector& accelerations) +void GCodeWriter::set_travel_short_acceleration(const std::vector& accelerations) { - m_short_travel_accelerations = accelerations; + m_travel_short_accelerations = accelerations; } void GCodeWriter::reset_last_acceleration() @@ -219,9 +219,9 @@ std::string GCodeWriter::set_travel_acceleration(bool use_short_travel_accelerat // Use short travel acceleration if requested and available if (use_short_travel_acceleration && - extruder_id < m_short_travel_accelerations.size() && - m_short_travel_accelerations[extruder_id] > 0) { - return set_acceleration_impl(m_short_travel_accelerations[extruder_id]); + extruder_id < m_travel_short_accelerations.size() && + m_travel_short_accelerations[extruder_id] > 0) { + return set_acceleration_impl(m_travel_short_accelerations[extruder_id]); } return set_acceleration_impl(travel_accelerations[extruder_id]); diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 38b743d1e7..70330e6764 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -56,10 +56,10 @@ class GCodeWriter { std::string set_chamber_temperature(int temperature, bool wait = false); void set_acceleration(unsigned int acceleration); void set_travel_acceleration(const std::vector& travel_accelerations); - void set_short_travel_acceleration(const std::vector& short_travel_accelerations); + void set_travel_short_acceleration(const std::vector& travel_short_accelerations); void reset_last_acceleration(); std::vector &get_travel_acceleration() { return m_travel_accelerations; } - std::vector &get_short_travel_acceleration() { return m_short_travel_accelerations; } + std::vector &get_travel_short_acceleration() { return m_travel_short_accelerations; } void set_first_layer_travel_acceleration(const std::vector& travel_accelerations); void set_first_layer(bool is_first_layer); std::string set_pressure_advance(double pa) const; @@ -171,7 +171,7 @@ class GCodeWriter { bool m_is_first_layer{false}; unsigned int m_acceleration{0}; std::vector m_travel_accelerations; // multi extruder, extruder size - std::vector m_short_travel_accelerations; // For short travels near external perimeters (VFA reduction) + std::vector m_travel_short_accelerations; // For short travels near external perimeters (VFA reduction) std::vector m_first_layer_travel_accelerations; // multi extruder, extruder size std::string _travel_to_z(double z, const std::string &comment,bool tool_change=false); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index c1eb237e2b..7b9b9c6032 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -934,7 +934,7 @@ static std::vector s_Preset_print_options { "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap","support_interface_speed", "bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration", - "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "travel_acceleration", "short_travel_acceleration", "initial_layer_travel_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration", + "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "travel_acceleration", "travel_short_distance_acceleration", "initial_layer_travel_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration", "accel_to_decel_enable", "accel_to_decel_factor", "skirt_loops", "skirt_distance", "skirt_height", "draft_shield", "brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 819c749b04..42fafdc330 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1463,7 +1463,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatsNullable{500.0}); // Short travel acceleration - ported from PrusaSlicer 2.9.3 for VFA reduction - def = this->add("short_travel_acceleration", coFloats); + def = this->add("travel_short_distance_acceleration", coFloats); def->label = L("Short travel"); def->tooltip = L("Acceleration used for short travel moves near external perimeters. " "Short travels are moves shorter than the 'Retraction minimum travel' distance.\n\n" @@ -6427,6 +6427,7 @@ std::set print_options_with_variant = { "travel_speed_z", "default_acceleration", "travel_acceleration", + "travel_short_distance_acceleration", "initial_layer_travel_acceleration", "initial_layer_acceleration", "outer_wall_acceleration", diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index ffe5120fb7..086c894c51 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1241,7 +1241,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloats, cooling_perimeter_transition_distance)) ((ConfigOptionFloatsNullable, default_acceleration)) ((ConfigOptionFloatsNullable, travel_acceleration)) - ((ConfigOptionFloatsNullable, short_travel_acceleration)) + ((ConfigOptionFloatsNullable, travel_short_distance_acceleration)) ((ConfigOptionFloatsNullable, initial_layer_travel_acceleration)) ((ConfigOptionFloatsNullable, inner_wall_acceleration)) ((ConfigOptionFloatsOrPercentsNullable, sparse_infill_acceleration)) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index ba8af5a2d3..36e7040f2a 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -959,31 +959,6 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config wxString text_value = wxString(""); const ConfigOptionDef* opt = config.def()->get(opt_key); - // If the option doesn't exist in the config, return the default value from the definition - if (!config.has(opt_key)) { - if (opt && opt->default_value) { - switch (opt->type) { - case coFloat: - case coPercent: - return double_to_string(opt->default_value->getFloat()); - case coFloats: - case coPercents: - case coInts: - case coEnums: - return opt->default_value->getInt(); - case coBool: - case coBools: - return opt->default_value->getBool(); - case coString: - case coStrings: - return wxString(""); - default: - return opt->default_value->getInt(); - } - } - return 0; - } - if (opt->nullable) { switch (opt->type) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 79053f67a6..c405dbc460 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2695,7 +2695,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Acceleration"), L"param_acceleration", 15); optgroup->append_single_option_line("default_acceleration", "", 0); optgroup->append_single_option_line("travel_acceleration", "", 0); - optgroup->append_single_option_line("short_travel_acceleration", "", 0); + optgroup->append_single_option_line("travel_short_distance_acceleration", "", 0); optgroup->append_single_option_line("initial_layer_travel_acceleration", "", 0); optgroup->append_single_option_line("initial_layer_acceleration", "", 0); optgroup->append_single_option_line("outer_wall_acceleration", "", 0); From 4616bd782f8c1fdb70593b3014d1e430a082db0a Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 26 Dec 2025 10:07:47 -0800 Subject: [PATCH 4/5] default value for travel_short_acceleration set to 250 --- src/libslic3r/PrintConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 42fafdc330..19f539722a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1474,7 +1474,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->mode = comDevelop; def->nullable = true; - def->set_default_value(new ConfigOptionFloatsNullable{0}); + def->set_default_value(new ConfigOptionFloatsNullable{250}); def = this->add("initial_layer_travel_acceleration", coFloats); def->label = L("Initial layer travel"); From c6b6a395ddc441bc0d0e930d6ea9f51ebace3139 Mon Sep 17 00:00:00 2001 From: Raul Date: Sun, 28 Dec 2025 09:45:56 -0800 Subject: [PATCH 5/5] travel_short_distance_acceleration config for dual nozzle printers --- .../profiles/BBL/process/fdm_process_dual_common.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/profiles/BBL/process/fdm_process_dual_common.json b/resources/profiles/BBL/process/fdm_process_dual_common.json index 85ef5a9783..f8df38d6ff 100644 --- a/resources/profiles/BBL/process/fdm_process_dual_common.json +++ b/resources/profiles/BBL/process/fdm_process_dual_common.json @@ -211,6 +211,12 @@ "10000", "10000" ], + "travel_short_distance_acceleration": [ + "250", + "250", + "250", + "250" + ], "top_surface_acceleration": [ "2000", "2000", @@ -242,4 +248,4 @@ "80%" ], "z_direction_outwall_speed_continuous": "1" -} \ No newline at end of file +}