From bc0fc8a789c01b1a32fa6b2a96b5192f2298b33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Fri, 16 Feb 2024 09:59:45 +0100 Subject: [PATCH] Fix missing deretraction coused by caching gcode writer. Use find and replace to remove the retraction if not required --- src/libslic3r/GCode.cpp | 70 +++++++++++++++++++++----- src/libslic3r/GCode.hpp | 3 +- src/libslic3r/GCode/GCodeProcessor.cpp | 2 + src/libslic3r/GCode/GCodeProcessor.hpp | 2 + 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 426520ac4e..cf3d2022dc 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2145,9 +2145,6 @@ std::string GCodeGenerator::get_layer_change_gcode(const Vec3d& from, const Vec3 )}; std::string travel_gcode; - if (!this->m_config.retract_layer_change.get_at(extruder_id) && this->m_config.retract_before_travel.get_at(extruder_id) < (to - from).norm()) { - travel_gcode += m_layer_change_wipe; - } Vec3d previous_point{this->point_to_gcode(travel.front())}; for (const Vec3crd& point : travel) { const Vec3d gcode_point{this->point_to_gcode(point)}; @@ -2246,6 +2243,7 @@ LayerResult GCodeGenerator::process_layer( m_max_layer_z = std::max(m_max_layer_z, m_last_layer_z); m_last_height = height; m_current_layer_first_position = std::nullopt; + m_already_unretracted = false; // Set new layer - this will change Z and force a retraction if retract_layer_change is enabled. if (!first_layer && ! print.config().before_layer_gcode.value.empty()) { @@ -2416,8 +2414,9 @@ LayerResult GCodeGenerator::process_layer( && m_layer_change_extruder_id && !result.spiral_vase_enable && print_z > previous_layer_z - && EXTRUDER_CONFIG(travel_ramping_lift) - && EXTRUDER_CONFIG(travel_slope) > 0 && EXTRUDER_CONFIG(travel_slope) < 90 + && this->m_config.travel_ramping_lift.get_at(*m_layer_change_extruder_id) + && this->m_config.travel_slope.get_at(*m_layer_change_extruder_id) > 0 + && this->m_config.travel_slope.get_at(*m_layer_change_extruder_id) < 90 ); if (first_layer) { layer_change_gcode = ""; // Explicit for readability. @@ -2427,6 +2426,45 @@ LayerResult GCodeGenerator::process_layer( layer_change_gcode = this->writer().get_travel_to_z_gcode(print_z, "simple layer change"); } + const auto keep_retraciton{[&](){ + if (!do_ramping_layer_change) { + return true; + } + const double travel_length{(*m_current_layer_first_position - *m_previous_layer_last_position_before_wipe).norm()}; + if (this->m_config.retract_before_travel.get_at(*m_layer_change_extruder_id) < travel_length) { + // Travel is long, keep retraction. + return true; + } + return false; + }}; + + bool removed_retraction{false}; + if (this->m_config.travel_ramping_lift.get_at(*m_layer_change_extruder_id)) { + const std::string retraction_start_tag = GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Retraction_Start); + const std::string retraction_end_tag = GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Retraction_End); + + if (keep_retraciton()) { + boost::algorithm::replace_first(gcode, retraction_start_tag, ""); + boost::algorithm::replace_first(gcode, retraction_end_tag, ""); + } else { + const std::size_t start{gcode.find(retraction_start_tag)}; + const std::size_t end_tag_start{gcode.find(retraction_end_tag)}; + const std::size_t end{end_tag_start + retraction_end_tag.size()}; + gcode.replace(start, end - start, ""); + + layer_change_gcode = this->get_layer_change_gcode(*m_previous_layer_last_position_before_wipe, *m_current_layer_first_position, *m_layer_change_extruder_id); + removed_retraction = true; + } + } + + if (removed_retraction) { + const std::size_t start{gcode.find("FIRST_UNRETRACT")}; + const std::size_t end{gcode.find("\n", start)}; + gcode.replace(start, end - start, ""); + } else { + boost::algorithm::replace_first(gcode,"FIRST_UNRETRACT", ""); + } + boost::algorithm::replace_first(gcode, tag, layer_change_gcode); BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << @@ -2743,14 +2781,15 @@ std::string GCodeGenerator::change_layer( // Increment a progress bar indicator. gcode += m_writer.update_progress(++ m_layer_index, m_layer_count); - if (EXTRUDER_CONFIG(retract_layer_change)) { + if (!EXTRUDER_CONFIG(travel_ramping_lift) && EXTRUDER_CONFIG(retract_layer_change)) { gcode += this->retract_and_wipe(); - } else { - const GCodeWriter saved_writer{this->writer()}; - const std::optional saved_last_position{this->last_position}; - this->m_layer_change_wipe = this->retract_and_wipe(); - this->m_writer = saved_writer; - this->last_position = saved_last_position; + } else if (EXTRUDER_CONFIG(travel_ramping_lift)){ + m_previous_layer_last_position_before_wipe = this->last_position ? + std::optional{to_3d(this->point_to_gcode(*this->last_position), previous_layer_z)} : + std::nullopt; + gcode += GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Retraction_Start); + gcode += this->retract_and_wipe(); + gcode += GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Retraction_End); } Vec3d new_position = this->writer().get_position(); @@ -3100,7 +3139,12 @@ std::string GCodeGenerator::_extrude( } // compensate retraction - gcode += this->unretract(); + if (this->m_already_unretracted) { + gcode += this->unretract(); + } else { + this->m_already_unretracted = true; + gcode += "FIRST_UNRETRACT" + this->unretract(); + } if (!m_pending_pre_extrusion_gcode.empty()) { // There is G-Code that is due to be inserted before an extrusion starts. Insert it. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index d9cc38d3ed..97b3695859 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -386,7 +386,6 @@ private: OozePrevention m_ooze_prevention; GCode::Wipe m_wipe; - std::string m_layer_change_wipe; GCode::LabelObjects m_label_objects; AvoidCrossingPerimeters m_avoid_crossing_perimeters; JPSPathFinder m_avoid_crossing_curled_overhangs; @@ -425,9 +424,11 @@ private: #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING std::optional m_previous_layer_last_position; + std::optional m_previous_layer_last_position_before_wipe; // This needs to be populated during the layer processing! std::optional m_current_layer_first_position; std::optional m_layer_change_extruder_id; + bool m_already_unretracted{false}; std::unique_ptr m_cooling_buffer; std::unique_ptr m_spiral_vase; std::unique_ptr m_find_replace; diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index e3a576e520..a602a77de4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -58,6 +58,8 @@ const std::vector GCodeProcessor::Reserved_Tags = { "WIDTH:", "LAYER_CHANGE", "LAYER_CHANGE_TRAVEL", + "LAYER_CHANGE_RETRACTION_START", + "LAYER_CHANGE_RETRACTION_END", "COLOR_CHANGE", "PAUSE_PRINT", "CUSTOM_GCODE", diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index f5658fcec8..759ce4f57d 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -193,6 +193,8 @@ namespace Slic3r { Width, Layer_Change, Layer_Change_Travel, + Layer_Change_Retraction_Start, + Layer_Change_Retraction_End, Color_Change, Pause_Print, Custom_Code,