From 789f848694b955d293ca6b277d1c8046aa6f7436 Mon Sep 17 00:00:00 2001 From: Fernando Marino` Date: Wed, 30 Sep 2026 00:18:15 +0200 Subject: [PATCH] Write the estimated printing time comment after the config block, not before (#15897) Co-authored-by: Fernando Marino Co-authored-by: yw4z --- src/libslic3r/GCode.cpp | 42 ++++++++++++++++++---------------- tests/fff_print/test_print.cpp | 19 +++++++++++++++ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 9f06ce9d3d..90cca3f084 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4174,6 +4174,28 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato print.throw_if_canceled(); + // Some firmwares only scan the last N lines for the time estimate, so the stats are written + // after the config block. + if (!is_bbl_printers && !skip_config_block) { + file.write("; CONFIG_BLOCK_START\n"); + std::string full_config; + append_full_config(print, full_config); + if (!full_config.empty()) + file.write(full_config); + + // SoftFever: write compatiple info + int first_layer_bed_temperature = get_bed_temperature(0, true, print.config().curr_bed_type); + file.write_format("; first_layer_bed_temperature = %d\n", first_layer_bed_temperature); + file.write_format("; bed_shape = %s\n", print.full_print_config().opt_serialize("printable_area").c_str()); + file.write_format("; first_layer_temperature = %d\n", print.config().nozzle_temperature_initial_layer.get_at(0)); + file.write_format("; first_layer_height = %.3f\n", print.config().initial_layer_print_height.value); + + //SF TODO +// file.write_format("; variable_layer_height = %d\n", print.ad.adaptive_layer_height ? 1 : 0); + + file.write("; CONFIG_BLOCK_END\n\n"); + } + // Get filament stats. file.write(DoExport::update_print_stats_and_format_filament_stats( // Const inputs @@ -4200,26 +4222,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder) .c_str()); file.write("\n"); - if (!skip_config_block) { - file.write("; CONFIG_BLOCK_START\n"); - std::string full_config; - append_full_config(print, full_config); - if (!full_config.empty()) - file.write(full_config); - - // SoftFever: write compatiple info - int first_layer_bed_temperature = get_bed_temperature(0, true, print.config().curr_bed_type); - file.write_format("; first_layer_bed_temperature = %d\n", first_layer_bed_temperature); - file.write_format("; bed_shape = %s\n", print.full_print_config().opt_serialize("printable_area").c_str()); - file.write_format("; first_layer_temperature = %d\n", print.config().nozzle_temperature_initial_layer.get_at(0)); - file.write_format("; first_layer_height = %.3f\n", print.config().initial_layer_print_height.value); - - //SF TODO -// file.write_format("; variable_layer_height = %d\n", print.ad.adaptive_layer_height ? 1 : 0); - - file.write("; CONFIG_BLOCK_END\n\n"); - } // !skip_config_block - } file.write("\n"); diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index 32cd608b43..a28669b8d4 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -489,6 +489,25 @@ TEST_CASE("gcode_skip_config_block omits the resolved-settings comment block", " CHECK(gcode.find("; EXECUTABLE_BLOCK_START") != std::string::npos); } +// Some firmwares only scan the last N lines of the file for "estimated printing time", so it +// must stay close to EOF regardless of the resolved-settings config block's size. +TEST_CASE("The estimated printing time comment stays near the end of the file", "[Print]") +{ + const std::string gcode = slice({ cube(20) }, {}); + const size_t config_block_end = gcode.find("; CONFIG_BLOCK_END"); + const size_t filament_stats = gcode.find("; filament used [mm]"); + const size_t time_comment = gcode.find("estimated printing time"); + REQUIRE(config_block_end != std::string::npos); + REQUIRE(filament_stats != std::string::npos); + REQUIRE(time_comment != std::string::npos); + CHECK(filament_stats > config_block_end); + CHECK(time_comment > filament_stats); + + const size_t line_start = gcode.rfind('\n', time_comment) + 1; + const size_t trailing_lines = std::count(gcode.begin() + line_start, gcode.end(), '\n'); + CHECK(trailing_lines <= 5); +} + // Custom G-code templates substitute placeholders during export. TEST_CASE("Custom G-code placeholders are substituted", "[Print]") {