feat: 4-tool support, primary row, zone sizing, and stability fixes

IMEXModesCtrl:
- Primary mode is now a non-deletable first row stored as sentinel
  "primary" in imex_mode_names; older configs load cleanly
- New rows default T0 → Primary when no tool assignment is stored
- Filter "primary" from plater popup/cycle list to prevent double entry
- imex_tools_per_gantry cap raised 2 → 4

Zone sizing:
- Zone width/height now based on active tool count only; inactive tools
  donate their bed share to active neighbors (fixes 4-tool layout)
- Active col/row maps (col_to_zone/row_to_zone) applied consistently
  across zone fills, collision strips, and primary zone box

GCodeViewer animation:
- Mirror position formula fixed: left-of-copy reflects across copy
  zone's left edge; right-of-copy reflects across right edge
  (T3 was rendering on top of T1)
- strip_width/row_strip_height use active counts, matching PartPlate

Stability:
- Early return in calc_imex_zones() when tool_states is empty; prevents
  OOB crash on new printer with stale process-preset mode name
- is_imex toggle in on_config_change calls refresh_imex_icons() so the
  plate mode icon appears without requiring a new project

GCode:
- Remove "primary" guard so Primary mode gcode field is emitted at
  start of print

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-04-09 19:08:57 -04:00
co-authored by Claude Sonnet 4.6
parent 0d73cd13ba
commit 9a87363044
11 changed files with 220 additions and 134 deletions
+1 -1
View File
@@ -5506,7 +5506,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Tools per Gantry");
def->tooltip = L("Number of independent toolheads per gantry along X. 2 for IDEX-style.");
def->min = 1;
def->max = 2;
def->max = 4;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(2));