iXex: Parallel Printing Support for IDEX and IQEX Printers #28

Open
opened 2026-04-05 16:18:11 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @cgarwood82 on 4/2/2026

Summary

This PR adds first-class parallel printing support to OrcaSlicer for printers with multiple independent X-axis carriages — IDEX (2 carriages) and IQEX (4 carriages, 2×2 grid). The feature is branded iXex (independent X extruder) and is designed to be printer-agnostic and firmware-flexible, with Klipper as the primary target.

The implementation spans printer configuration, process settings UI, bed visualization, placement validation, G-code generation, and layer preview animation.


What This PR Adds

Printer Configuration

New printer preset options that declare iXex capability and geometry:

Option Type Description
is_ixex bool Marks this printer as iXex-capable
ixex_gantry_count int Number of independent Y-axis gantries (rows)
ixex_tools_per_gantry int Toolheads per gantry along X (columns)
ixex_primary_col / ixex_primary_row int Grid position (0-based) of the primary tool
ixex_carriage_width_x / ixex_carriage_width_y float Toolhead footprint in mm
ixex_tool_layout string Physical orientation: front-left / front-right / rear-left / rear-right
ixex_mode_names string[] Names of user-defined parallel modes
ixex_mode_active_tools string[] Tool role assignments per mode (e.g. 0:P,1:C,2:M,3:M)
ixex_mode_gcodes string[] Firmware macro to activate per mode

Tool roles per mode: Primary (P), Copy (C), Mirror (M), Inactive.

Parallel Mode Editor

Kooha-2026-04-02-02-18-45
Kooha-2026-04-02-02-20-42

A new iXex Parallel Modes section in the Printer preset tab (visible only when is_ixex = true) provides a visual grid editor:

  • Each row in the editor defines one named parallel mode.
  • Tool buttons in the grid cycle through Inactive → Primary → Copy → Mirror states, color-coded (green / blue / amber / grey).
  • A G-code field per mode holds the firmware macro to activate that mode (e.g. IXEX_COPY for Klipper).
  • Modes can be added and deleted. Deleting the active mode resets the process preset to Primary.
  • The Process preset (Others tab) gains an iXex parallel mode dropdown that lists all defined modes plus "primary".
    Kooha-2026-04-02-02-21-45

Bed Visualization

When an iXex mode is active, the build plate renders the carriage grid:
Kooha-2026-04-02-02-22-44

  • The active (primary) zone is full brightness.
  • Inactive zones are dimmed with a blue-grey overlay.
  • Zone dividers are rendered as blue lines across the bed.
  • The grid is a full 2D layout: tools_per_gantry columns × gantry_count rows.
  • Zones recompute lazily on mode change and from scratch on bed shape change.

Placement Validation

Objects placed outside the primary zone block slicing:
Kooha-2026-04-02-02-23-46

  • has_ixex_placement_violations() in PartPlate checks each object's footprint against the primary zone boundaries.
  • Violations inject into the existing update_background_process validation pathway — the Slice button is disabled and an error notification is shown.
  • Mirror tools additionally generate X-axis collision strips (copy tools move in the same direction and cannot collide). Y-direction strips are scoped to same-column tools to avoid false positives from diagonal mirror pairs.

G-code Injection

The selected parallel mode's G-code is written into the output file immediately before machine_start_gcode:

  • Looks up ixex_parallel_mode from the process config, finds the matching entry in ixex_mode_names, and writes the corresponding ixex_mode_gcodes entry.
  • Processed through placeholder_parser_process() so Klipper-style variable substitution works.
  • No-op for Primary mode and non-iXex printers — zero overhead for unaffected users.

Layer Preview Multi-Carriage Animation (Phase 6a)

The sequential preview (scrubber) animates all active carriages simultaneously:
Kooha-2026-04-02-02-30-08

  • One toolhead marker (colored cube) per active carriage, in addition to the primary.
  • Secondary marker colors: cyan (T1), yellow (T2), magenta (T3).
  • Copy tools: marker placed at the same relative position within their bed zone as the primary is in the primary zone.
  • Mirror tools: marker reflects the Copy tool on the same gantry row across the bed X center. Y position is always zone-relative copy (all tools on a row share a physical Y rail).
  • The filament usage legend notes the active carriage count and mode name (e.g. iXex: ×2 (copy_mode)).

Limitations and Known Gaps

Not Implemented in This PR

Per-layer G-code collision detection
The placement-time zone check catches gross violations (object placed in wrong zone) but does not verify that toolpaths on any given layer maintain adequate X separation between adjacent carriages. A per-layer check via ConflictChecker was designed but deferred. Without it, a print that passes placement validation could still crash carriages if the primary object's toolpaths reach too close to a zone boundary.

Ghost path overlays
Secondary carriage toolpaths are not rendered in the layer preview. The secondary markers animate correctly, but the paths they would trace are not drawn. Adding ghost path rendering would require duplicating and offsetting the toolpath geometry per secondary carriage, which is a significant addition to the libvgcode rendering pipeline.

Object placement in secondary zones
There is currently no mechanism to place objects into Copy or Mirror zones. The secondary zones are virtual — the firmware mirrors or copies the primary object's paths. Users who want to visualize the ghost objects in their secondary zones as reference cannot do so. This is a deliberate design choice for this MVP (the firmware handles the duplication), but a future "ghost object" feature would allow users to see and verify placement.

No per-mode slicing
All carriages in a mode execute the same sliced toolpaths (offset by zone). There is no support for slicing different objects for each carriage independently within one mode. That would require a more substantial rework of the multi-plate / multi-process pipeline.

Firmware Assumptions

  • The implementation assumes the firmware handles all carriage synchronization and offset math. OrcaSlicer only injects the mode-activation macro at print start.
  • Tested against Klipper. Marlin-based IDEX printers use a different activation mechanism (M605 / T0 / T1) and would need their own macro content in the G-code fields — the fields are free-form strings so this works, but no Marlin validation has been done.
  • Mid-print mode switching is explicitly not supported. The mode is locked at print start.

UI / UX Gaps

  • The iXex Parallel Modes editor does not warn when a gantry row has Mirror tools but no Copy tool (the mirror would fall back to reflecting the primary). Validation and a visible warning would be a useful addition.
  • There is no gantry-row validation preventing two Mirror tools on the same row without a Copy (which produces undefined behavior in the mirror math).
  • The mode dropdown in the process tab does not show a visual indicator when the selected mode is no longer defined in the printer preset (it silently resets to Primary).

Files Changed

File Change
src/libslic3r/PrintConfig.cpp iXex config option definitions
src/libslic3r/PrintConfig.hpp iXex config option declarations, IXexMode enum
src/libslic3r/Preset.cpp iXex keys registered in printer and process preset option lists
src/libslic3r/GCode.cpp Mode G-code injection before machine start G-code
src/slic3r/GUI/Tab.cpp IXexModesCtrl editor widget, printer tab section, process tab mode dropdown; clear_pages() now nulls iXex control pointers to prevent dangling-pointer crash on preset save
src/slic3r/GUI/Tab.hpp TabPrinter member declarations for iXex controls
src/slic3r/GUI/PartPlate.cpp Zone visualization, placement violation detection
src/slic3r/GUI/PartPlate.hpp iXex zone members, has_ixex_placement_violations()
src/slic3r/GUI/Plater.cpp Validation pathway injection
src/slic3r/GUI/GCodeViewer.cpp Multi-carriage marker animation, legend annotation
src/slic3r/GUI/GCodeViewer.hpp m_ixex_secondary_markers, toolhead box members

Testing Notes

Validated on an IQEX printer (4 carriages, 2×2 grid, Klipper firmware) with the following configurations:

  • Primary only — baseline, no regression vs. standard single-extruder workflow
  • Copy mode (T0 Primary, T1 Copy, same row) — carriage markers animate in sync offset by strip width
  • Mirror mode (T0 Primary, T1 Mirror, same row) — T1 marker reflects T0 across bed center X
  • Cross-row copy + mirror (T0 Primary row 0, T2 Copy row 1, T3 Mirror row 1) — T2 follows T0's zone-relative position; T3 mirrors T2's X; Y shared per row
  • Delete active mode — no crash; process preset resets to Primary
  • Placement outside primary zone — slicing blocked with error notification
*Originally created by @cgarwood82 on 4/2/2026* ## Summary This PR adds first-class parallel printing support to OrcaSlicer for printers with multiple independent X-axis carriages — IDEX (2 carriages) and IQEX (4 carriages, 2×2 grid). The feature is branded **iXex** (independent X extruder) and is designed to be printer-agnostic and firmware-flexible, with Klipper as the primary target. The implementation spans printer configuration, process settings UI, bed visualization, placement validation, G-code generation, and layer preview animation. --- ## What This PR Adds ### Printer Configuration New printer preset options that declare iXex capability and geometry: | Option | Type | Description | |--------|------|-------------| | `is_ixex` | bool | Marks this printer as iXex-capable | | `ixex_gantry_count` | int | Number of independent Y-axis gantries (rows) | | `ixex_tools_per_gantry` | int | Toolheads per gantry along X (columns) | | `ixex_primary_col` / `ixex_primary_row` | int | Grid position (0-based) of the primary tool | | `ixex_carriage_width_x` / `ixex_carriage_width_y` | float | Toolhead footprint in mm | | `ixex_tool_layout` | string | Physical orientation: front-left / front-right / rear-left / rear-right | | `ixex_mode_names` | string[] | Names of user-defined parallel modes | | `ixex_mode_active_tools` | string[] | Tool role assignments per mode (e.g. `0:P,1:C,2:M,3:M`) | | `ixex_mode_gcodes` | string[] | Firmware macro to activate per mode | Tool roles per mode: **Primary** (P), **Copy** (C), **Mirror** (M), **Inactive**. ### Parallel Mode Editor ![Kooha-2026-04-02-02-18-45](https://github.com/user-attachments/assets/330587bd-f390-4a72-8eac-07506978aed9) ![Kooha-2026-04-02-02-20-42](https://github.com/user-attachments/assets/b7c51ff8-e50d-4bf7-9848-a95a99ab65d5) A new **iXex Parallel Modes** section in the Printer preset tab (visible only when `is_ixex = true`) provides a visual grid editor: - Each row in the editor defines one named parallel mode. - Tool buttons in the grid cycle through Inactive → Primary → Copy → Mirror states, color-coded (green / blue / amber / grey). - A G-code field per mode holds the firmware macro to activate that mode (e.g. `IXEX_COPY` for Klipper). - Modes can be added and deleted. Deleting the active mode resets the process preset to Primary. - The **Process preset** (Others tab) gains an **iXex parallel mode** dropdown that lists all defined modes plus "primary". ![Kooha-2026-04-02-02-21-45](https://github.com/user-attachments/assets/42e77489-3e52-4edf-b5fe-ba4557d7b780) ### Bed Visualization When an iXex mode is active, the build plate renders the carriage grid: ![Kooha-2026-04-02-02-22-44](https://github.com/user-attachments/assets/5d0979af-4e80-4c96-be42-b0b2d5bdc359) - The **active (primary) zone** is full brightness. - **Inactive zones** are dimmed with a blue-grey overlay. - **Zone dividers** are rendered as blue lines across the bed. - The grid is a full 2D layout: `tools_per_gantry` columns × `gantry_count` rows. - Zones recompute lazily on mode change and from scratch on bed shape change. ### Placement Validation Objects placed outside the primary zone block slicing: ![Kooha-2026-04-02-02-23-46](https://github.com/user-attachments/assets/7e92be0b-d12f-4fc7-90ba-f0e5ccbdd3e3) - `has_ixex_placement_violations()` in `PartPlate` checks each object's footprint against the primary zone boundaries. - Violations inject into the existing `update_background_process` validation pathway — the Slice button is disabled and an error notification is shown. - Mirror tools additionally generate X-axis collision strips (copy tools move in the same direction and cannot collide). Y-direction strips are scoped to same-column tools to avoid false positives from diagonal mirror pairs. ### G-code Injection The selected parallel mode's G-code is written into the output file immediately before `machine_start_gcode`: - Looks up `ixex_parallel_mode` from the process config, finds the matching entry in `ixex_mode_names`, and writes the corresponding `ixex_mode_gcodes` entry. - Processed through `placeholder_parser_process()` so Klipper-style variable substitution works. - No-op for Primary mode and non-iXex printers — zero overhead for unaffected users. ### Layer Preview Multi-Carriage Animation (Phase 6a) The sequential preview (scrubber) animates all active carriages simultaneously: ![Kooha-2026-04-02-02-30-08](https://github.com/user-attachments/assets/21cc3abc-82fc-4408-bf19-1f4bda915d7c) - One toolhead marker (colored cube) per active carriage, in addition to the primary. - Secondary marker colors: cyan (T1), yellow (T2), magenta (T3). - **Copy** tools: marker placed at the same relative position within their bed zone as the primary is in the primary zone. - **Mirror** tools: marker reflects the Copy tool on the same gantry row across the bed X center. Y position is always zone-relative copy (all tools on a row share a physical Y rail). - The filament usage legend notes the active carriage count and mode name (e.g. `iXex: ×2 (copy_mode)`). --- ## Limitations and Known Gaps ### Not Implemented in This PR **Per-layer G-code collision detection** The placement-time zone check catches gross violations (object placed in wrong zone) but does not verify that toolpaths on any given layer maintain adequate X separation between adjacent carriages. A per-layer check via `ConflictChecker` was designed but deferred. Without it, a print that passes placement validation could still crash carriages if the primary object's toolpaths reach too close to a zone boundary. **Ghost path overlays** Secondary carriage toolpaths are not rendered in the layer preview. The secondary markers animate correctly, but the paths they would trace are not drawn. Adding ghost path rendering would require duplicating and offsetting the toolpath geometry per secondary carriage, which is a significant addition to the libvgcode rendering pipeline. **Object placement in secondary zones** There is currently no mechanism to place objects into Copy or Mirror zones. The secondary zones are virtual — the firmware mirrors or copies the primary object's paths. Users who want to visualize the ghost objects in their secondary zones as reference cannot do so. This is a deliberate design choice for this MVP (the firmware handles the duplication), but a future "ghost object" feature would allow users to see and verify placement. **No per-mode slicing** All carriages in a mode execute the same sliced toolpaths (offset by zone). There is no support for slicing different objects for each carriage independently within one mode. That would require a more substantial rework of the multi-plate / multi-process pipeline. ### Firmware Assumptions - The implementation assumes the firmware handles all carriage synchronization and offset math. OrcaSlicer only injects the mode-activation macro at print start. - Tested against Klipper. Marlin-based IDEX printers use a different activation mechanism (`M605` / `T0` / `T1`) and would need their own macro content in the G-code fields — the fields are free-form strings so this works, but no Marlin validation has been done. - Mid-print mode switching is explicitly not supported. The mode is locked at print start. ### UI / UX Gaps - The iXex Parallel Modes editor does not warn when a gantry row has Mirror tools but no Copy tool (the mirror would fall back to reflecting the primary). Validation and a visible warning would be a useful addition. - There is no gantry-row validation preventing two Mirror tools on the same row without a Copy (which produces undefined behavior in the mirror math). - The mode dropdown in the process tab does not show a visual indicator when the selected mode is no longer defined in the printer preset (it silently resets to Primary). --- ## Files Changed | File | Change | |------|--------| | `src/libslic3r/PrintConfig.cpp` | iXex config option definitions | | `src/libslic3r/PrintConfig.hpp` | iXex config option declarations, `IXexMode` enum | | `src/libslic3r/Preset.cpp` | iXex keys registered in printer and process preset option lists | | `src/libslic3r/GCode.cpp` | Mode G-code injection before machine start G-code | | `src/slic3r/GUI/Tab.cpp` | `IXexModesCtrl` editor widget, printer tab section, process tab mode dropdown; `clear_pages()` now nulls iXex control pointers to prevent dangling-pointer crash on preset save | | `src/slic3r/GUI/Tab.hpp` | `TabPrinter` member declarations for iXex controls | | `src/slic3r/GUI/PartPlate.cpp` | Zone visualization, placement violation detection | | `src/slic3r/GUI/PartPlate.hpp` | iXex zone members, `has_ixex_placement_violations()` | | `src/slic3r/GUI/Plater.cpp` | Validation pathway injection | | `src/slic3r/GUI/GCodeViewer.cpp` | Multi-carriage marker animation, legend annotation | | `src/slic3r/GUI/GCodeViewer.hpp` | `m_ixex_secondary_markers`, toolhead box members | --- ## Testing Notes Validated on an IQEX printer (4 carriages, 2×2 grid, Klipper firmware) with the following configurations: - **Primary only** — baseline, no regression vs. standard single-extruder workflow - **Copy mode** (T0 Primary, T1 Copy, same row) — carriage markers animate in sync offset by strip width - **Mirror mode** (T0 Primary, T1 Mirror, same row) — T1 marker reflects T0 across bed center X - **Cross-row copy + mirror** (T0 Primary row 0, T2 Copy row 1, T3 Mirror row 1) — T2 follows T0's zone-relative position; T3 mirrors T2's X; Y shared per row - **Delete active mode** — no crash; process preset resets to Primary - **Placement outside primary zone** — slicing blocked with error notification
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/OrcaSlicer#28