diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ff7b341807..9061d8bc27 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1249,7 +1249,12 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail // Prusa Multi-Material wipe tower. if (has_wipe_tower && ! layers_to_print.empty()) { m_wipe_tower = std::make_unique(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()); - file.write(m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); + + // Set position for wipe tower generation. + Vec3d new_position = this->writer().get_position(); + new_position.z() = first_layer_height + m_config.z_offset.value; + this->writer().update_position(new_position); + if (print.config().single_extruder_multi_material_priming) { file.write(m_wipe_tower->prime(*this)); // Verify, whether the print overaps the priming extrusions. @@ -2195,7 +2200,7 @@ LayerResult GCodeGenerator::process_layer( m_current_layer_first_position = std::nullopt; // Set new layer - this will change Z and force a retraction if retract_layer_change is enabled. - if (! print.config().before_layer_gcode.value.empty()) { + if (!first_layer && ! print.config().before_layer_gcode.value.empty()) { DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); @@ -2210,7 +2215,7 @@ LayerResult GCodeGenerator::process_layer( m_travel_obstacle_tracker.init_layer(layer, layers); m_object_layer_over_raft = false; - if (! print.config().layer_gcode.value.empty()) { + if (!first_layer && ! print.config().layer_gcode.value.empty()) { DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); config.set_key_value("layer_z", new ConfigOptionFloat(print_z)); @@ -2346,13 +2351,12 @@ LayerResult GCodeGenerator::process_layer( && EXTRUDER_CONFIG(travel_ramping_lift) && EXTRUDER_CONFIG(travel_slope) > 0 && EXTRUDER_CONFIG(travel_slope) < 90 ); - if (do_ramping_layer_change) { + if (first_layer) { + layer_change_gcode = ""; // Explicit for readability. + } else if (do_ramping_layer_change) { layer_change_gcode = this->get_layer_change_gcode(*m_previous_layer_last_position, *m_current_layer_first_position, *m_layer_change_extruder_id); } else { - if (!m_current_layer_first_position) { - throw std::runtime_error("Destination is required for layer change!"); - } - layer_change_gcode = this->writer().get_travel_to_z_gcode(m_current_layer_first_position->z(), "simple layer change"); + layer_change_gcode = this->writer().get_travel_to_z_gcode(m_config.z_offset.value + print_z, "simple layer change"); } boost::algorithm::replace_first(gcode, tag, layer_change_gcode); @@ -2675,7 +2679,7 @@ std::string GCodeGenerator::change_layer( gcode += this->retract_and_wipe(); Vec3d new_position = this->writer().get_position(); - new_position.z() = print_z; + new_position.z() = print_z + m_config.z_offset.value; this->writer().update_position(new_position); m_previous_layer_last_position = this->last_position ? diff --git a/src/libslic3r/GCode/WipeTowerIntegration.cpp b/src/libslic3r/GCode/WipeTowerIntegration.cpp index 3cccbde78d..56c2f4af93 100644 --- a/src/libslic3r/GCode/WipeTowerIntegration.cpp +++ b/src/libslic3r/GCode/WipeTowerIntegration.cpp @@ -60,8 +60,8 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip const Point xy_point = wipe_tower_point_to_object_point(gcodegen, start_pos); gcode += gcodegen.retract_and_wipe(); gcodegen.m_avoid_crossing_perimeters.use_external_mp_once(); + const std::string comment{"Travel to a Wipe Tower"}; if (gcodegen.m_current_layer_first_position) { - const std::string comment{"Travel to a Wipe Tower"}; if (gcodegen.last_position) { gcode += gcodegen.travel_to( *gcodegen.last_position, xy_point, ExtrusionRole::Mixed, comment @@ -72,13 +72,13 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip } } else { const Vec3crd point = to_3d(xy_point, scaled(z)); - const Vec3d gcode_point = to_3d(gcodegen.point_to_gcode(point.head<2>()), z); + const Vec3d gcode_point = gcodegen.point_to_gcode(point); gcodegen.last_position = point.head<2>(); gcodegen.writer().update_position(gcode_point); gcode += gcodegen.writer() - .get_travel_to_xy_gcode(gcode_point.head<2>(), "move to first layer point"); + .get_travel_to_xy_gcode(gcode_point.head<2>(), comment); gcode += gcodegen.writer() - .get_travel_to_z_gcode(gcode_point.z(), "move to first layer point"); + .get_travel_to_z_gcode(gcode_point.z(), comment); gcodegen.m_current_layer_first_position = gcode_point; } gcode += gcodegen.unretract(); diff --git a/src/libslic3r/GCode/WipeTowerIntegration.hpp b/src/libslic3r/GCode/WipeTowerIntegration.hpp index 52b27625bb..231e6659c6 100644 --- a/src/libslic3r/GCode/WipeTowerIntegration.hpp +++ b/src/libslic3r/GCode/WipeTowerIntegration.hpp @@ -26,7 +26,8 @@ public: m_tool_changes(tool_changes), m_final_purge(final_purge), m_layer_idx(-1), - m_tool_change_idx(0) + m_tool_change_idx(0), + m_last_wipe_tower_print_z(print_config.z_offset.value) {} std::string prime(GCodeGenerator &gcodegen); @@ -56,7 +57,7 @@ private: // Current layer index. int m_layer_idx; int m_tool_change_idx; - double m_last_wipe_tower_print_z = 0.f; + double m_last_wipe_tower_print_z; }; } // namespace GCode diff --git a/tests/fff_print/test_cooling.cpp b/tests/fff_print/test_cooling.cpp index 1f560d53f0..187d7f4394 100644 --- a/tests/fff_print/test_cooling.cpp +++ b/tests/fff_print/test_cooling.cpp @@ -250,9 +250,9 @@ SCENARIO("Cooling integration tests", "[Cooling]") { if (l == 0) l = line.dist_Z(self); if (l > 0.) { - if (layer_times.empty()) - layer_times.emplace_back(0.); - layer_times.back() += 60. * std::abs(l) / line.new_F(self); + if (!layer_times.empty()) { // Ignore anything before first z move. + layer_times.back() += 60. * std::abs(l) / line.new_F(self); + } } if (line.has('F') && line.f() == external_perimeter_speed) ++ layer_external[scaled(self.z())]; diff --git a/tests/fff_print/test_custom_gcode.cpp b/tests/fff_print/test_custom_gcode.cpp index 0d109070bf..2dd97e9c35 100644 --- a/tests/fff_print/test_custom_gcode.cpp +++ b/tests/fff_print/test_custom_gcode.cpp @@ -45,13 +45,21 @@ SCENARIO("Custom G-code", "[CustomGCode]") }); GCodeReader parser; bool last_move_was_z_change = false; + bool first_z_move = true; // First z move is not a layer change. int num_layer_changes_not_applied = 0; parser.parse_buffer(Slic3r::Test::slice({ Test::TestMesh::cube_2x20x10 }, config), - [&last_move_was_z_change, &num_layer_changes_not_applied](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) + [&](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) { - if (last_move_was_z_change != line.cmd_is("_MY_CUSTOM_LAYER_GCODE_")) + if (last_move_was_z_change != line.cmd_is("_MY_CUSTOM_LAYER_GCODE_")) { ++ num_layer_changes_not_applied; - last_move_was_z_change = line.dist_Z(self) > 0; + } + if (line.dist_Z(self) > 0 && first_z_move) { + first_z_move = false; + } else if (line.dist_Z(self) > 0){ + last_move_was_z_change = true; + } else { + last_move_was_z_change = false; + } }); THEN("custom layer G-code is applied after Z move and before other moves") { REQUIRE(num_layer_changes_not_applied == 0);