diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b6a2ddb665..359052bc96 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2278,17 +2278,45 @@ namespace DoExport { ooze_prevention.enable = print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material; } + // Count tool/filament changes across the print from the tool ordering. Used as a fallback when no + // wipe tower populated WipeTowerData::number_of_toolchanges (left at -1). Covers non-sequential + // prints without a wipe tower (manual swaps, toolchanger/IDEX). Note: sequential (by-object) prints + // leave print.tool_ordering() empty, so total_toolchanges stays 0 there (unchanged from before). + static int total_toolchanges_from_ordering(const ToolOrdering &tool_ordering) + { + int changes = 0; + int last = -1; + for (const LayerTools < : tool_ordering) + for (unsigned int extruder : lt.extruders) { + if (last >= 0 && int(extruder) != last) + ++ changes; + last = int(extruder); + } + return changes; + } + + // Total tool changes for the print, preferring the wipe-tower count and falling back to the tool + // ordering when no wipe tower populated it (number_of_toolchanges < 0). + static int resolve_total_toolchanges(const WipeTowerData &wipe_tower_data, const ToolOrdering &tool_ordering) + { + int changes = wipe_tower_data.number_of_toolchanges; + if (changes < 0) + changes = total_toolchanges_from_ordering(tool_ordering); + return std::max(0, changes); + } + // Fill in print_statistics and return formatted string containing filament statistics to be inserted into G-code comment section. static std::string update_print_stats_and_format_filament_stats( const bool has_wipe_tower, const WipeTowerData &wipe_tower_data, const std::vector &extruders, - PrintStatistics &print_statistics) + PrintStatistics &print_statistics, + const ToolOrdering &tool_ordering) { std::string filament_stats_string_out; print_statistics.clear(); - print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges); + print_statistics.total_toolchanges = resolve_total_toolchanges(wipe_tower_data, tool_ordering); if (! extruders.empty()) { std::pair out_filament_used_mm ("; filament used [mm] = ", 0); std::pair out_filament_used_cm3("; filament used [cm3] = ", 0); @@ -2858,7 +2886,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided. this->placeholder_parser().set("has_wipe_tower", has_wipe_tower); this->placeholder_parser().set("has_single_extruder_multi_material_priming", wipe_tower_type == WipeTowerType::Type2 && has_wipe_tower && print.config().single_extruder_multi_material_priming); - this->placeholder_parser().set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change). + this->placeholder_parser().set("total_toolchanges", DoExport::resolve_total_toolchanges(print.wipe_tower_data(), print.tool_ordering())); this->placeholder_parser().set("num_extruders", int(print.config().nozzle_diameter.values.size())); this->placeholder_parser().set("retract_length", new ConfigOptionFloats(print.config().retraction_length)); @@ -3473,7 +3501,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato has_wipe_tower, print.wipe_tower_data(), m_writer.extruders(), // Modifies - print.m_print_statistics)); + print.m_print_statistics, + // Const input (tool-change fallback for non-wipe-tower prints) + print.tool_ordering())); print.m_print_statistics.initial_tool = initial_extruder_id; if (!is_bbl_printers) { file.write_format("; total filament used [g] = %.2lf\n",