The validator, fixture archives and unpacked fixture trees no longer live under <repo>/.test/check_profiles, so every worktree on a machine shares one copy instead of re-downloading. macOS, Linux and Windows each use their own user cache dir, named apart from OrcaSlicer's per-user dirs. The now-unused /.test/ ignore rule is dropped.
The no-tower case was gated on there being no purge volume, but the SEMM flush matrix reads every configured slot and is nonzero even when only one filament is used, so the plater preview drew a tower the print would never contain.
filament_id is the plain mint of the product triple (filament_vendor,
filament_type, filament name), and nothing else feeds it. The tooling used to
accept any salt iteration of a preset's own triple, and its minting policy
stepped past ids that other products held in the tree or in the snapshot, so
which id a product got could depend on history. Every "salt split" in the tree
masked a redundant preset rather than a real need, and no shipped id is
salted, so salting goes entirely: no salt parameter, no id policy object, and
--generate no longer reads the snapshot.
--check now holds every declared and every inherited id to that one value and
lists each preset that misses it, variants under a wrong root included, instead
of folding them into the root's error. Two products whose triples mint one id
is reported as a collision naming both, and --generate refuses to write it;
the remedy is a rename so the triples differ. The Bambu catalog map generator
keys its rows by the same mint rather than by what the tree already ships.
No id changes: all 913 ids in the tree are already the mint of their triple,
so --generate is a no-op and the snapshot is untouched.
"Snapmaker PLA-CF @U1" and "Snapmaker PLA-CF @U1 0.4 nozzle" are the same
product on the same printer: both pin "Snapmaker U1 (0.4 nozzle)", and only a
filament_id salt split kept them apart. The first came with the original U1
profiles (#10225); the second with the tool-changer rework (#15039), which
added the 0.4/0.6/0.8 nozzle variants and left the older preset behind.
Drop the older one and re-mint the 0.4 variant onto OFhQf8ou, the id its 0.6
and 0.8 siblings already carry, so the product holds one id across the three
nozzles; renamed_from redirects the retired name. Users of the retired preset
get the #15039 tuning - 39 keys differ, including nozzle 230 -> 240 C, plate
55 -> 65 C and vitrification 150 -> 45 C - which is what the 0.6 and 0.8
variants already ship.
"Snapmaker PLA-CF @U1 base" stays. #15039 orphaned it by having the nozzle
variants inherit fdm_filament_pla directly, so it is unreferenced, but it is a
base in the vendor's own convention - 10 of the 14 @U1 families with nozzle
variants wire them to one - and it holds U1 loading and cooling values the
variants never set. Wiring them to it would change slicing output, which is
Snapmaker's call to make, not this PR's.
Claude-Session: https://claude.ai/code/session_01Q3zm9HuyskkSb4hynviV99
"Update re:3D profiles" (#13750) added the tuned "@0.4/@0.8 nozzle" and
"@0.8/@1.75 nozzle" variants but kept the five original un-suffixed presets,
trimming each to a stub that overrides only filament_vendor while still
claiming every printer of both nozzles. On any re3D printer the stub was
selectable alongside the ~50-key variant that actually tunes the material,
which is what forced five filament_id salt splits to keep the pair apart.
Drop the stubs. The variants already carry the products' ids, so nothing is
re-minted; renamed_from redirects each retired name to the smaller-nozzle
variant, and "re3D rPETG @0.8 nozzle" additionally takes over the
"re3D Greengate rPETG" mapping that lived on the deleted umbrella. Each
printer model's default_materials now lists the variants for its own
nozzles rather than the stub.
Cubicon's nine "@base" presets were the only instantiated ones of the 196
"@base" filament presets in the library; the other 187 are instantiation:false.
Being selectable, and claiming xCeler-I and xCeler-Plus, they put two presets of
one product on those two printers - which is what forced the nine filament_id
salt splits: one product deliberately kept on two ids so AMS matching stayed
unambiguous.
Flip them to instantiation:false and drop the compatible_printers, setting_id
and filament_settings_id that a base has no use for, matching what the other
150 bases carry. The three "@Cubicon xCeler-{I,Mini,Plus} 0.4 nozzle" variants
keep one printer each, so every printer still sees exactly one preset per
product and they converge on its single id; the nine salted ids retire.
A base is not added to the preset collection, so user presets that inherited
the selectable "@base" - the v2.3.2-v2.4.2 fixtures have one per material -
would lose their parent. renamed_from on the xCeler-I variant, the first model
the base ever claimed, redirects them; a preset built on "@base" while printing
on an xCeler-Plus narrows to the xCeler-I.
The six default_materials / default_filament_profile fields named
"Cubicon PLA @Cubicon xCeler-<model>", dropping the " 0.4 nozzle" the presets
actually carry, so none of them ever resolved; each model now names its own
variant.
Claude-Session: https://claude.ai/code/session_01Q3zm9HuyskkSb4hynviV99
A filament_id is now exactly what the preset's own filament_vendor,
filament_type and filament name mint, wherever it inherits from. Inheriting
settings no longer limits what a preset may claim, so the checks that policed
inheritance are gone, and so are the four grandfather lists that held thousands
of presets as permanent exceptions. The snapshot records sanctioned state rather
than excuses: one entry per id, carrying the product it names beside the presets
claiming it.
Profiles that disagreed are corrected instead of excused. The Elegoo TPU and
PAHT roots were named for a different product than all of their variants and
become TPU 95A and PAHT-CF; Elegoo PET-CF gains the filament_type its variants
already set; the Snapmaker breakaway support presets get an id of their own
rather than riding the PVA chain; and a BBL preset name carrying a doubled space
is fixed behind renamed_from. Their ids re-mint from the corrected identities.
The tooling and the design note also drop the word "family", which invited
reading a brand's Lite and Pro spools as one id.
No change to slicing output — only filament_id values, three preset names, the
inherits lines following those renames and the vendor indexes move.
Orca content-addresses every system filament, Bambu's included, but a printer,
its AMS and its vendor's cloud know only that vendor's own catalog ids. The
printer agent now translates between the two: outbound MQTT and FTP traffic, the
AMS mapping sent with a print job, and the ids written into a 3mf bound for the
printer all leave in the printer's own ids, while status messages, loaded
projects and SD-card prints arrive in Orca's. An id with no mapping passes
through unchanged, and an agent whose printers already speak Orca's ids
translates nothing at all.
Bambu's map is generated from BambuStudio's own shipped bundle; a missing or
unreadable file leaves every lookup an identity rather than taking the app down.
The profile check validates the map's shape, and profile CI now runs on the paths
that can change it. docs/HLSD/filament_id.md records the places the map
deliberately does not reach.
The tree-wide length check (freed from its BBL/OFL carve-out last commit)
was flagging 21 pre-existing SeeMeCNC files that no vendor index references
and that therefore never load, turning CI red for files with no bearing on
what ships. The rule now only fires on presets a vendor's filament_list
actually references; every .json under the vendor's filament directory is
still parsed through the duplicate-key hook, so that coverage is unchanged.
Also removed a duplicated BAMBU_MAP_PATH definition: update_bambu_filament_ids.py
now imports the constant from assign_filament_ids.py, which it already imports
several other constants from, instead of recomputing the same path independently.
Every vendor's filament_id declarations, Bambu's own bundle included, are now
minted and checked the same way: the GF* catalog space is reserved but
ownerless, format is validated unconditionally with no snapshot or BBL
exemption, and both --remint and the default assign pass treat a non-OF
declaration as one needing a fresh mint (so a future BambuStudio sync
self-heals instead of needing a manual pass). A new check validates
resources/printers/bambu_filament_ids.json against the tree it describes:
that it parses, carries its header, keys only OF ids, maps each Bambu id once,
and agrees with the tree on every product it shares. The redundant BBL/OFL
carve-out in the profile checker's length check is dropped too, so it runs
the same way for every vendor.
The BBL bundle itself hasn't been touched yet and still declares its old GF
ids, so TestRealTree.test_shipped_snapshot_matches_tree is expected to fail
here (209 declarations flagged) until the next commit re-mints the bundle
onto OF ids.
scripts/update_bambu_filament_ids.py derives resources/printers/bambu_filament_ids.json
from BambuStudio's own shipped BBL bundle (cloned from upstream, or read from a local
checkout via --bambustudio-dir), pairing each Bambu catalog id with the Orca filament_id
we already ship for that product where we ship one, else a freshly generated one. Nothing
reads the map yet; later work uses it to translate ids at the Bambu printer boundary.
The sweep now validates each printer with the filament that printer ships, so a run
over every vendor reports what a single-vendor run does. Validator only - no change
to slicing output or shipped profiles.
Format/3mf.cpp also saved and loaded it, but nothing calls its store_3mf and
its load_3mf only sees files fingerprinted as PrusaSlicer's, which never carry
a recipe. Its round-trip test only exercised that dead loop. The BBS backend,
which every save and load goes through, is untouched.
The Design tab's viewport is the fourth GLCanvas3D on the shared GL context and
the only one the plater does not own, so unbind_canvas_event_handlers() and
reset_canvas_volumes() never reached it — the macOS Command+Q and Debian cases
those calls exist for. Its frame-level handlers become members so they can be
unbound.
The bind sat above GLCanvas3D::bind_event_handlers(), and on_size never Skips,
so wx's reverse-order dispatch stopped before it and the handler never ran.
These dialogs treated a filament with no compatible_printers as compatible with
nothing, while the rest of the app treats it as compatible with everything, so
the entire Orca Filament Library was missing from the AMS material and
calibration filament lists. They now resolve compatibility the same way the
plater does, and a vendor profile still supersedes the library generic of the
same name.
wxImage with static_data set stores the pointer and never copies it, so the
frame handed to wxMediaCtrl3 aliased AVVideoDecoder::bits_. That buffer is
rewritten by the next sws_scale with the mutex released, reallocated by
bits_.resize() when the window grows, and freed outright when the decoder
leaves PlayThread's loop body at end of stream, all while the GUI thread may
be painting from it.
Windows is unaffected either way, since toWxBitmap already copies the bits
into GDI.
It was already public and used elsewhere, so the new get_background_process()
and its duplicate forward declaration were redundant; Plater.hpp is now untouched.
The recipe's 3MF entry moved from Metadata/SnapOrca_cad.bin to
Metadata/orca_cad.bin, so projects saved by earlier builds opened with an
empty Design tab. Both 3MF backends now read either name and write only the
new one; the recipe version advances to 6 to mark the move.
The tab is now gated on a new enable_cad_feature app-config key, off by
default, exposed in Preferences under General > Features. When off, the
page is never created, so the Design-only camera option is hidden too.
Takes effect on restart, like the other feature toggles.
SLIC3R_CAD=OFF now builds without SolveSpace or OCCT's ModelingAlgorithms
module, leaving the dependency set identical to upstream's, and the Design
tab's mate connector preference no longer appears in builds without the tab.
When the deps prefix and the project disagree about the option, the configure
fails naming the cause, rather than failing at link time or at first launch
on Windows. The Windows packaging step stages exactly the toolkits libslic3r
links.
The Camera is Plater-owned and shared by every canvas, and Design sits
outside the panel switch that saves and restores it for Prepare,
Preview and Assemble — so orbiting in Design moved what the editor
tabs showed, and Design lost its own view on every switch. Trade the
live camera for a parked one on the way in and back on the way out, so
Design keeps its view the way Assemble already does.
New Project and Open Project went through Plater::priv::reset, which
drops ModelObjects but not the Model-level recipe, and never touched
the Design panel's document at all — so the previous design stayed
loaded and its next edit wrote itself into the new project.
A design that has not been committed to the plate has no ModelObjects,
so the project also read as clean: no autosave, and no unsaved-changes
prompt before the reset threw the design away.
DesignPanel's constructor creates several hundred controls and its own GL
canvas, which every launch paid for whether or not the user ever opened the
tab. The notebook page is now an empty placeholder and the panel is built
into it the first time the tab is selected, so m_design_panel stays null
until then.
This also lifts the ordering constraint that had pushed the plater's
background colour and Hide() below the panel construction; they go back
where they were.
* Keep mixed-color filaments intact when the extruder count changes
The extruder-count spinner resized the filament arrays in bulk at the tail,
which is where mixed-color slots live, so a new filament landed behind the
mix and the sidebar skipped a slot number. It now adds and removes one slot
at a time through the same calls the sidebar's +/- buttons use, so a new
slot opens ahead of the mixed tail and a removal renumbers object filament
ids, painted facets, custom g-code and mixed components rather than
clamping them away.
Drops the vector overload of set_num_filaments(), which this leaves without
callers.
# Description
This PR ports the color mixing feature from BambuStudio.
The port is based on the previous work by @ianalexis in #15231.
This PR completes the port and fixes various bugs.
Several improvements were also made during the porting process.
WIP
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
The sidebar Mixed Filament list, the extruder icons, the color painting
gizmo and the canvas filament bar now show the same bottom-to-top fade the
Edit Mixed Filament preview shows, custom gradient curves included, instead
of a horizontal fade between the two component colours. Ordinary and vendor
multi-colour filaments are drawn exactly as before.
Mixed-colour slots are virtual and never flushed. Guard auto_calc_flushing_volumes_internal against them as BambuStudio does, and make the flushing dialog's default matrix and the sidebar 'modified' comparison physical-only so the untouched mixed rows no longer count as a user edit and the Re-calculate result matches the physical-only table.