From 6e176434d0c7427054de8ce4c818470eaba36801 Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Sat, 25 Apr 2026 02:50:04 -0400 Subject: [PATCH] docs(imex): document physical-vs-logical index distinction Three IMEX bugs of the same shape have surfaced over the lifetime of this feature: - Inline pem lookup duplicated at two PA emission sites - Pre-slice warnings indexing filament_presets by physical index - Ghost color resolution with stale default pem handling Each was a place where a per-filament array got indexed by what the call site had on hand (a physical T-number) without translating through physical_extruder_map. On non-MMU/non-AFC printers the indices coincide and nothing breaks; on AFC layouts the slicer reads the wrong filament preset for a carriage with no error or log line. Add a header comment block to IMEXHelpers.hpp describing the two index spaces, when each is used, how to translate, and a list of the bugs we hit so future contributors can recognize the pattern. The constant kImexPrimaryMode and the helper declarations follow this block; readers searching for pem helpers will land on the guidance first. Co-Authored-By: Claude Opus 4.7 --- src/libslic3r/IMEXHelpers.hpp | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libslic3r/IMEXHelpers.hpp b/src/libslic3r/IMEXHelpers.hpp index 6ae53c4534..82b5b890bd 100644 --- a/src/libslic3r/IMEXHelpers.hpp +++ b/src/libslic3r/IMEXHelpers.hpp @@ -20,6 +20,48 @@ class PresetBundle; // plate mode equals this. Treat any value NOT equal to this as a parallel mode. inline constexpr const char* kImexPrimaryMode = "primary"; +// ============================================================================= +// PHYSICAL vs LOGICAL extruder indices — read this before adding a new IMEX call site +// ============================================================================= +// IMEX has two distinct index spaces and they are NOT interchangeable on MMU/AFC +// printers (where multiple logical filament slots share one physical extruder): +// +// * PHYSICAL extruder index — identifies a hardware carriage / hotend. +// Source: `imex_mode_active_tools` ("0:P,1:C,2:M") and `printer_extruder_id`. +// Use for: user-facing labels (shown as "T0", "T1"...), per-firmware tool +// qualifiers (Klipper EXTRUDER=extruderN, RRF M572 D, Marlin T), and +// anything that addresses hardware. +// +// * LOGICAL filament slot index — identifies one filament in the project. +// Source: indexing into per-filament arrays — `filament_presets`, +// `nozzle_temperature_initial_layer`, bed_temp arrays per plate type, etc. +// Use for: looking up filament data by slot. +// +// On a single-extruder or pure-IDEX printer the two indices coincide. On any +// printer with `physical_extruder_map` size > 1 they diverge. Confusing them +// produces silent wrong-filament behavior — the slicer reads the wrong filament +// preset / temperature for a given carriage with no error or log line. +// +// Translate physical → logical via: +// resolve_filament_for_head(plate_head_filament_map, pem, physical_idx) +// (or the simpler `first_filament_for_physical_head` if no per-plate override). +// +// The reverse translation (logical → physical) is just `pem.get_at(filament_id)`, +// already encapsulated in `imex_pem_tool_for` for the per-tool-qualifier case. +// +// Past bugs in this class: +// - GCode PA emission used the inline `pem.get_at(filament_id)` form at two +// sites (consolidated into `imex_pem_tool_for` in c2492ccc47). +// - Pre-slice warnings indexed `filament_presets` directly by physical idx, +// causing wrong-filament names on AFC/MMU layouts (fixed in fbc58d2a1d). +// - Ghost color resolution had its own inline pem lookup with a stale default +// (centralized in `effective_physical_extruder_map` in 6a3de6a28f). +// +// New call sites: if you index a per-filament array, you need a logical index. +// If you label a hardware carriage, use the physical index. When in doubt, +// route through one of the helpers below. +// ============================================================================= + // Returns the effective physical_extruder_map given an optionally-explicit map and // the printer's `printer_extruder_id`. If `explicit_pem` has size >= 2 the caller // authored one, and it is returned verbatim. Otherwise the map is auto-derived