Merge upstream main: wipe tower port, per-filament bounds checks, CLI mixed rules

Four files overlapped, and each resolution favours upstream where the two sides
had done the same work:

WipeTower's M104/M109 tool qualifier. Both sides bounds-checked the physical
extruder map lookup; upstream omits the T qualifier when the map cannot answer,
where this branch fell back to the logical index and so named a carriage that may
not be the one printing. Upstream's behaviour is what this branch documents
elsewhere, so its version is taken and the local helper is dropped.

get_extruders' mixed-slot switch. Upstream added the same concept to the CLI
overload as expand_mixed_slots, so the GUI overloads' parameter is renamed to
match rather than carrying two names for one idea.

GLCanvas3D's sequential-clearance branch gains upstream's
update_compacted_wipe_tower_clearance for the by-layer case.

The printer_agent re-sync in TabPrinter::reload_config was upstream's and their
preset-undo fix removed it, so it goes; the IMEX modes grid re-sync beside it
stays, since it spans three options and is not a Field.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-09-18 01:50:53 -04:00
co-authored by Claude Opus 5
2353 changed files with 115549 additions and 116642 deletions
+6 -3
View File
@@ -20,6 +20,7 @@
#include "Plater.hpp"
#include "Camera.hpp"
#include "I18N.hpp"
#include "format.hpp"
#include "GUI_Utils.hpp"
#include "GUI.hpp"
#include "GLCanvas3D.hpp"
@@ -3842,16 +3843,18 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return ret;
};
// Whole sentences: the bare "up to"/"above"/"from"/"to" these used to be glued from gave a
// translator no context, and left the unit and the numbers stuck in English word order.
auto upto_label = [](double z) {
char buf[64];
::sprintf(buf, "%.2f", z);
return _u8L("up to") + " " + std::string(buf) + " " + _u8L("mm");
return format(_u8L("up to %1% mm"), buf);
};
auto above_label = [](double z) {
char buf[64];
::sprintf(buf, "%.2f", z);
return _u8L("above") + " " + std::string(buf) + " " + _u8L("mm");
return format(_u8L("above %1% mm"), buf);
};
auto fromto_label = [](double z1, double z2) {
@@ -3859,7 +3862,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
::sprintf(buf1, "%.2f", z1);
char buf2[64];
::sprintf(buf2, "%.2f", z2);
return _u8L("from") + " " + std::string(buf1) + " " + _u8L("to") + " " + std::string(buf2) + " " + _u8L("mm");
return format(_u8L("from %1% to %2% mm"), buf1, buf2);
};
auto role_time_and_percent = [this, total_estimated_time](libvgcode::EGCodeExtrusionRole role) {