mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
init work to integrate OrcaSlicer-FullSpectrum fork
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>
This commit is contained in:
171
doc/MixedFilament.md
Normal file
171
doc/MixedFilament.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user