Fix total_toolchanges placeholder being 0 without a wipe tower (#13895)
* fix: populate total_toolchanges without a wipe tower total_toolchanges is documented as available while change_filament_gcode (and the wipe-tower toolchange flow) is evaluated, but it was sourced only from WipeTowerData::number_of_toolchanges, which stays -1 (clamped to 0) when no wipe tower is generated. Manual filament swaps and toolchanger/IDEX setups without a wipe tower therefore always saw total_toolchanges = 0 in custom G-code and output filenames, despite real tool changes occurring -- breaking the placeholder's documented contract. Add a tool-ordering fallback: when number_of_toolchanges < 0, count tool changes from the print's tool ordering (the transitions in the per-layer extruder sequence). Wipe-tower prints are untouched -- number_of_toolchanges >= 0 still wins -- so their reported count does not change. Limitation: sequential (by-object) prints without a wipe tower leave Print::tool_ordering() empty, so total_toolchanges stays 0 there (unchanged from before). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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<Extruder> &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<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||
std::pair<std::string, unsigned int> 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",
|
||||
|
||||
Reference in New Issue
Block a user