refactor(imex): consolidate IMEX active-tools parsing through one helper

GCode.cpp's static get_imex_active_tools() inlined its own "phys[:role]"
tokenizer with subtly different semantics from IMEXHelpers'
parse_imex_active_tools — only the GCode version bounded against
MAXIMUM_EXTRUDER_NUMBER. Three other call sites (PartPlate zones,
GCodeViewer legend, Plater warnings) routed through parse_imex_active_tools
already.

Move the bounds check into parse_imex_active_tools so all consumers get
it consistently, then rewrite get_imex_active_tools to do only the
Print-extraction portion (active mode lookup, tools-string fetch) and
delegate token parsing to the helper. Keeps Print out of IMEXHelpers'
include set.

No behavior change for the non-pathological case (mode strings have always
parsed identically); for indices >= MAXIMUM_EXTRUDER_NUMBER (64) the three
older call sites silently filter them out now where previously they would
have accepted them — this matches what get_imex_active_tools already did.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-04-25 00:32:34 -04:00
co-authored by Claude Opus 4.7
parent 085f5ccec8
commit 4e0a2704b9
2 changed files with 7 additions and 14 deletions
+6 -13
View File
@@ -2395,8 +2395,10 @@ static BambuBedType to_bambu_bed_type(BedType type)
// Orca IMEX: Returns the tool indices active in the current IMEX mode.
// In copy/mirror parallel modes, secondary carriages never receive tool-change
// commands — the firmware mirrors the primary's moves — so they don't appear in
// tool_ordering.all_extruders(). This helper parses imex_mode_active_tools to enumerate them.
// Format: "0:P,1:C,2:M,3:M" — only the leading integer index is used.
// tool_ordering.all_extruders(). This helper extracts the active mode's tool string
// from the Print and delegates parsing to IMEXHelpers::parse_imex_active_tools so the
// "phys[:role]" tokenization matches every other IMEX consumer (PartPlate zones,
// GCodeViewer legend, Plater warnings).
// Indices are PHYSICAL T-indices. Callers that need a filament-slot (for PA / temp
// lookups) must resolve via first_filament_for_physical_head or resolve_filament_for_head.
static std::vector<int> get_imex_active_tools(const Print& print)
@@ -2418,17 +2420,8 @@ static std::vector<int> get_imex_active_tools(const Print& print)
for (size_t i = 0; i < mode_names_opt->values.size(); ++i) {
if (i >= tools_opt->values.size() || mode_names_opt->values[i] != active_mode)
continue;
std::istringstream ss(tools_opt->values[i]);
std::string token;
while (std::getline(ss, token, ',')) {
token.erase(std::remove_if(token.begin(), token.end(), ::isspace), token.end());
if (token.empty()) continue;
try {
int idx = std::stoi(token); // leading integer before optional ':role' suffix
if (idx >= 0 && idx < (int)MAXIMUM_EXTRUDER_NUMBER)
active_tools.push_back(idx);
} catch (...) {}
}
for (const auto& [phys, role] : parse_imex_active_tools(tools_opt->values[i]))
active_tools.push_back(phys);
break;
}
return active_tools;
+1 -1
View File
@@ -84,7 +84,7 @@ std::vector<std::pair<int, ImexRole>> parse_imex_active_tools(const std::string&
const std::string idx_str = (colon == std::string::npos) ? tok : tok.substr(0, colon);
int phys = -1;
try { phys = std::stoi(idx_str); } catch (...) { continue; }
if (phys < 0) continue;
if (phys < 0 || phys >= (int)MAXIMUM_EXTRUDER_NUMBER) continue;
ImexRole role = ImexRole::Copy;
if (colon != std::string::npos) {
const std::string r = tok.substr(colon + 1);