mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 09:02:06 +00:00
Integrations up to commit b3c41fda4180a2946812726218d0a849be0aedb6.
- libslic3r: vendor FilamentMixer; MixedFilamentManager (auto-gen, resolve,
serialize; manual-pattern / gradient / pointillism); 19 new PrintConfig
keys; PresetBundle owns the canonical manager with 3MF + AppConfig
roundtrip and AMS-safe strip+restore; Print owns the slicing-time copy
with PrintApply auto-regen on color change; TriangleSelector::
shift_states_above + filament-id remap; inset_idx propagation through
ExtrusionPath/Loop/MultiPath copy/assign.
- Slicing: virtual filament IDs in painted regions (same-physical channels
collapse when mixed_filament_region_collapse is on); ByObject
collect_filament_data expands mixed slots; pair-cadence + whole-object +
3+component Local-Z plan generators; LocalZOrderOptimizer utility.
- GCode + ToolOrdering: LayerTools resolves virtual IDs through wall /
infill / sparse / solid queries; SameLayerPointillisme in process_layer
(uniform-segment + grouped per-perimeter-index splitters); WipeTower2
Local-Z reservation + sub-layer G-code emission; per-layer infill
filament override.
- PartPlate: get_extruders* expand virtual slots into physical components;
CLI path rebuilds a local manager from full_config.
- GUI: five widget files extracted from FS Plater.cpp (~5000 LOC) —
MixedMixPreview, MixedGradientSelector + WeightsDialog,
MixedFilamentColorMapPanel, MixedFilamentColorMatchDialog (ΔE₀₀ recipe
search), MixedFilamentConfigPanel; Sidebar Mixed Filaments panel
(drag-reorder, enable/delete, Add Gradient/Pattern/Color); Tab exposure
of mixed-filament / dithering / per-layer infill-override settings +
ConfigManipulation visibility and slot-validation rules;
BBLMixedFilamentBroken / BBLSingleExtruderMixedFilamentRisk
notifications + slice gate; WipeTowerDialog edits physical P×P
sub-matrix; bounds-safe extruder_id guards in 3DScene / GLCanvas3D /
GLGizmoMmuSegmentation; change_filament merge guard and
on_filaments_delete is_mixed_before_delete propagation.
- Tests: 4 Catch2 tests for 3MF roundtrip (auto/custom persistence,
PresetBundle string path, total_filaments stability); full-pipeline
slice E2E deferred — TODO in file.
Co-authored-by: Rad <radugheorghiu96@gmail.com>
Co-authored-by: Justin Hayes <justinh@rahb.ca>
Co-authored-by: Calogero Guagenti <calogeroguagenti@gmail.com>
Co-authored-by: xSil3nt <ahmedshazin21@gmail.com>
Co-authored-by: ratdoux <62392831+ratdoux@users.noreply.github.com>
Co-authored-by: Rad <radugheorghiu96@gmail.com>
Co-authored-by: Justin Hayes <justinh@rahb.ca>
Co-authored-by: Calogero Guagenti <calogeroguagenti@gmail.com>
Co-authored-by: xSil3nt <ahmedshazin21@gmail.com>
Co-authored-by: ratdoux <62392831+ratdoux@users.noreply.github.com>
172 lines
7.7 KiB
Markdown
172 lines
7.7 KiB
Markdown
# Mixed Filament
|
|
|
|
Ported from [OrcaSlicer-FullSpectrum](https://github.com/SoftFever/OrcaSlicer-FullSpectrum)
|
|
with contributions from Rad, Justin Hayes, Calogero Guagenti, xSil3nt, and ratdoux.
|
|
|
|
---
|
|
|
|
## User Guide
|
|
|
|
### What It Does
|
|
|
|
Mixed Filament lets a single virtual filament slot alternate between two
|
|
physical filaments across layers (or within a layer in Pointillisme mode),
|
|
producing blended or gradient-like colours on single-extruder printers.
|
|
|
|
### Enabling
|
|
|
|
1. Load a multi-colour (multi-extruder) profile with at least 2 filaments.
|
|
2. The **Mixed Filaments** panel appears automatically in the right-hand sidebar
|
|
when 2 or more filaments are configured.
|
|
3. Each auto-generated row represents one pair of physical filaments.
|
|
Toggle a row to enable it; the total filament count grows to include the
|
|
virtual slot.
|
|
|
|
### Sidebar Workflow
|
|
|
|
- **Add** — creates a custom row for the same pair or a different ratio.
|
|
- **Edit** — opens `MixedFilamentConfigPanel` to adjust ratio, pattern,
|
|
surface offset (bias), and distribution mode.
|
|
- **Delete** — marks the row deleted; existing painted geometry retains its
|
|
virtual filament ID until you re-slice or repaint.
|
|
|
|
Painting with a virtual filament ID behaves the same as painting with a
|
|
physical one — use the Multi-Material Painting gizmo and select the virtual
|
|
slot from the colour palette.
|
|
|
|
### Color Match Dialog
|
|
|
|
Open via the colour swatch on a mixed row. The dialog (`MixedFilamentColorMatchDialog`)
|
|
shows a live preview strip of the blended result and lets you adjust ratio
|
|
until the preview matches your target colour. The preview accounts for
|
|
surface-offset bias when enabled.
|
|
|
|
### Anti-Banding Options
|
|
|
|
| Setting | What it does |
|
|
|---|---|
|
|
| `mixed_filament_advanced_dithering` | Uses an ordered dither pattern instead of simple A-then-B runs. Reduces stripe visibility on some hue pairs. More experimental than the default. |
|
|
| `dithering_local_z_mode` | Splits each blended layer into two sub-layers whose heights are proportional to the mix ratio (e.g. 66/33 at 0.12 mm → 0.08 mm + 0.04 mm). Produces the smoothest colour gradients. |
|
|
| `dithering_local_z_whole_objects` | Extends Local-Z splitting beyond painted masks to cover the entire object cross-section. Useful when mixed walls surround a painted zone. |
|
|
| `dithering_local_z_direct_multicolor` | For rows with 3 or more physical components, allocates Local-Z sub-layers directly across all components with carry-over error correction instead of collapsing to pair cadence. More toolchanges; less banding. |
|
|
|
|
### Gotchas
|
|
|
|
- **Single-extruder warning** — Mixed Filament requires a physical toolchange
|
|
between the two components. On a true single-nozzle printer this means a
|
|
manual filament swap. Verify your printer profile supports `T0`/`T1` before
|
|
using mixed slots in a production print.
|
|
- **Variable-layer interaction** — If Variable Layer Height is enabled, Local-Z
|
|
sub-layer heights are recomputed per interval. The mix ratio is preserved but
|
|
the absolute sub-layer heights change with the variable height. Review the
|
|
layer preview after applying variable layers.
|
|
- **Custom sequence disabled** — OrcaSlicer's "custom toolchange sequence" is
|
|
suppressed when mixed filaments are active (`PlateSettingsDialog`). The
|
|
virtual-to-physical resolution must control toolchange order; a user-defined
|
|
sequence would break it.
|
|
- **Stable IDs** — each mixed row carries a `stable_id` (64-bit). If you
|
|
reorder or delete rows and then load an older project, the ID remap in
|
|
`PresetBundle::update_mixed_filament_id_remap` translates painted geometry
|
|
to the correct new virtual slot. Do not rely on the 1-based filament index
|
|
as a stable identifier.
|
|
|
|
---
|
|
|
|
## Developer Guide
|
|
|
|
### Core Data Structures
|
|
|
|
```
|
|
src/libslic3r/MixedFilament.hpp — MixedFilament struct, MixedFilamentManager
|
|
src/libslic3r/MixedFilament.cpp — serialization, resolve(), auto_generate()
|
|
src/libslic3r/LocalZOrderOptimizer.hpp — bucket-ordering helpers for Local-Z
|
|
```
|
|
|
|
The key scalar fields on `MixedFilament`:
|
|
|
|
- `component_a`, `component_b` — 1-based physical filament indices.
|
|
- `ratio_a`, `ratio_b` — layer-alternation cadence numerators.
|
|
- `mix_b_percent` — nominal colour mix (used for Local-Z height computation
|
|
and the Color Match preview; does not change the cadence).
|
|
- `stable_id` — monotonically increasing 64-bit ID assigned at construction.
|
|
Never reused. Survives serialization round-trips.
|
|
- `distribution_mode` — selects between `Simple`, `SameLayerPointillisme`,
|
|
and `GroupedManual`.
|
|
|
|
### Seam: Adding New Distribution Modes
|
|
|
|
`MixedFilamentManager::resolve()` in `MixedFilament.cpp` is the single
|
|
dispatch point that maps `(virtual_filament_id, num_physical, layer_index)`
|
|
to a physical extruder. The current switch covers `Simple` and
|
|
`SameLayerPointillisme`. A new mode is added by:
|
|
|
|
1. Adding a value to the `MixedFilament::DistributionMode` enum in
|
|
`MixedFilament.hpp`.
|
|
2. Adding a `case` to `MixedFilamentManager::resolve()` in `MixedFilament.cpp`.
|
|
3. Serializing the new mode token in `serialize_custom_entries` /
|
|
`load_custom_entries` (format is a semicolon-delimited row string; see
|
|
existing tokens for the convention).
|
|
|
|
G-code emission (`src/libslic3r/GCode/`) reads only the physical ID returned
|
|
by `resolve()`, so new modes are automatically emitted without further changes.
|
|
|
|
### Seam: New Toolchange-Cost Heuristics
|
|
|
|
`LocalZOrderOptimizer` (`src/libslic3r/LocalZOrderOptimizer.hpp`) exposes:
|
|
|
|
- `order_bucket_extruders(bucket, current, preferred_last)` — reorders a
|
|
single-layer bucket to minimise toolchanges given the current active extruder.
|
|
- `order_pass_group(group, current_extruder)` — greedy walk across a set of
|
|
buckets (one per Local-Z sub-layer) to minimise total transitions.
|
|
|
|
To add a new heuristic (e.g. cost-based look-ahead), replace or wrap
|
|
`order_pass_group`. The caller in `PrintObjectSlice.cpp` passes the result
|
|
directly into the sub-layer plan, so the heuristic is fully decoupled from
|
|
the plan builder.
|
|
|
|
### Seam: New Picker Shapes in the Color Map Panel
|
|
|
|
`MixedFilamentColorMapPanel` (`src/slic3r/GUI/MixedFilamentColorMapPanel.hpp`)
|
|
renders a 2-D colour map using a set of geometry "types" (currently strip and
|
|
gradient). Each type is a small self-contained rendering path keyed by an enum
|
|
value. New shapes are added by:
|
|
|
|
1. Adding an enum value to `MixedFilamentColorMapPanel::GeometryType`.
|
|
2. Implementing the corresponding `Paint*` helper (follow `PaintStrip` as a
|
|
template).
|
|
3. Wiring the new type into the `switch` in `OnPaint`.
|
|
|
|
### Persistence (3MF)
|
|
|
|
The entire mixed-filament state is stored as a single string key
|
|
`mixed_filament_definitions` in the project config block (section `[presets]`
|
|
in the 3MF metadata).
|
|
|
|
Round-trip path:
|
|
|
|
```
|
|
MixedFilamentManager::serialize_custom_entries()
|
|
called by PresetBundle::sync_mixed_filaments_to_config()
|
|
written by bbs_3mf: store_bbs_3mf → config.set("presets", "mixed_filament_definitions", ...)
|
|
|
|
load_bbs_3mf → config.get("presets", "mixed_filament_definitions")
|
|
stored in project_config["mixed_filament_definitions"]
|
|
read by PresetBundle::sync_mixed_filaments_from_config()
|
|
→ mixed_filaments.auto_generate(colours)
|
|
→ mixed_filaments.load_custom_entries(defs, colours)
|
|
```
|
|
|
|
Auto-generated rows are *not* written to the definitions string; they are
|
|
rebuilt from the filament colour list. Only `custom == true` rows are stored.
|
|
|
|
See `tests/fff_print/test_mixed_filament_e2e.cpp` for regression tests
|
|
covering this path.
|
|
|
|
### ID Remap
|
|
|
|
When filaments are added, removed, or reordered, virtual IDs shift.
|
|
`PresetBundle::update_mixed_filament_id_remap(old_mixed, old_count, new_count)`
|
|
produces a `remap` vector where `remap[old_virtual_id] = new_virtual_id`.
|
|
Painted triangle mesh face data uses these IDs; the remap is applied in
|
|
`TriangleSelectorMixed` after any filament list change.
|