feat(imex): topology-aware Tool 0 Position dropdown

For single-gantry IMEX setups, front/rear is meaningless — only left/right
matters. Collapse the imex_tool_layout dropdown to two items ("Left" / "Right",
mapped to front-left/front-right internally) when imex_gantry_count == 1, and
show all four corner items otherwise. Normalize stored rear-* selections to
their front-* equivalents on the transition so the displayed selection always
matches the persisted value.

Also rename the field label "Tool 0 Corner" → "Tool 0 Position" so it reads
correctly in both single- and dual-gantry contexts, with a tooltip that
explains the IDEX/IQEX distinction.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-05-14 13:25:37 -04:00
co-authored by Claude Opus 4.7
parent f11011efac
commit cb66867768
2 changed files with 48 additions and 3 deletions
+5 -3
View File
@@ -5821,10 +5821,12 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionInt(2));
def = this->add("imex_tool_layout", coEnum);
def->label = L("Tool 0 Corner");
def->tooltip = L("Physical corner of the bed where tool T0 (index 0) is located. "
def->label = L("Tool 0 Position");
def->tooltip = L("Physical position on the bed where tool T0 (index 0) is located. "
"Determines how tool indices map to bed zones. "
"front = lower Y (near the operator), rear = higher Y (back of machine).");
"For single-gantry setups (IDEX) only left/right matters; "
"for dual-gantry setups (IQEX) all four corners are selectable "
"(front = lower Y / near the operator, rear = higher Y / back of machine).");
def->mode = comAdvanced;
def->enum_keys_map = &ConfigOptionEnum<ImexToolLayout>::get_enum_values();
def->enum_values.push_back("front-left");
+43
View File
@@ -6141,6 +6141,49 @@ void TabPrinter::toggle_options()
toggle_option("imex_viz_theme", is_imex);
toggle_option("imex_firmware_managed_zones", is_imex);
if (m_imex_modes_ctrl) m_imex_modes_ctrl->Show(is_imex);
// IDEX/IQEX: the tool_layout dropdown carries 4 corner values
// (front-left / front-right / rear-left / rear-right) in storage, but front/rear
// is meaningless on single-gantry setups. Collapse the dropdown to just two
// items ("Left" / "Right") when imex_gantry_count == 1 — mapped to front-left
// and front-right internally — and normalize any stored rear-* selection to its
// front-* equivalent so the displayed selection always matches the stored value.
if (is_imex) {
if (Field* layout_field = get_field("imex_tool_layout"); layout_field) {
if (auto* choice = dynamic_cast<Choice*>(layout_field); choice) {
const int gantry_count = m_config->opt_int("imex_gantry_count");
int current_val = 0;
if (auto* o = m_config->option<ConfigOptionEnum<ImexToolLayout>>("imex_tool_layout"))
current_val = static_cast<int>(o->value);
// Normalize rear-* → front-* when collapsing to 1 gantry.
if (gantry_count == 1 && (current_val == static_cast<int>(ImexToolLayout::RearLeft)
|| current_val == static_cast<int>(ImexToolLayout::RearRight))) {
ImexToolLayout normalized = (current_val == static_cast<int>(ImexToolLayout::RearLeft))
? ImexToolLayout::FrontLeft
: ImexToolLayout::FrontRight;
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("imex_tool_layout",
new ConfigOptionEnum<ImexToolLayout>(normalized));
load_config(new_conf);
current_val = static_cast<int>(normalized);
}
wxArrayString items;
if (gantry_count >= 2) {
items.Add(_L("Front-left"));
items.Add(_L("Front-right"));
items.Add(_L("Rear-left"));
items.Add(_L("Rear-right"));
} else {
items.Add(_L("Left"));
items.Add(_L("Right"));
}
choice->set_values(items);
choice->set_value(boost::any(current_val), false);
}
}
}
}
wxString extruder_number;
long val = 1;