# Description
This PR introduces a publish workflow for sharing selected slicer
settings in .3mf projects without exposing or overriding the recipient's
complete printer, filament, or process profiles. A published file
specifies "requirements" for a model — printer, process, and per-slot
filament requirements — while importing it preserves the rest of the
recipient's workflow.
Publish dialog (File → Publish, Ctrl+Shift+E)
- Tabbed dialog (Printer / Filament / Process) with search, Select All /
Select Visible, and DPI rescaling.
- Per-material pages expose three kinds of content: individually
selected filament keys, a Full Publish toggle that embeds the slot's
entire filament preset, and required type and color rows for the slot.
- Publishing is allowed with no settings selected (the file then carries
only identity/requirement data).
- Reuses configuration value formatting extracted into a shared
ConfigValueFormatter.
Export
- Published 3MFs carry published, published_keys, and
published_material_keys metadata.
- A minimal export mode serializes only the selected values, material
identity, and plate geometry, omits embedded preset files, and masks
full-publish vector options to the author's slot so unrelated slot data
never leaks into the file.
Loading
- Only author-selected settings are applied; the recipient's presets are
otherwise preserved and structural/non-publishable keys are protected
(skipped keys are reported).
- Material settings match by filament ID, type, vendor, and slot.
Per-slot type requirements keep a matching receiver material, replace a
mismatched slot with the first same-type library filament (with a
notification), and fall back to a temporary embedded preset or skipped
keys when no match exists. Required colors are applied regardless of the
type match.
- A published 3MF loads as a new project: its path is not adopted as the
project filename (Save prompts instead of overwriting the shared file),
the title reverts to "Untitled", and the published metadata is stripped
so a later save produces a normal 3MF.
- Customized-preset and modified-G-code warnings are suppressed, since
the author's presets and G-code are not applied.
- Previously published 3MF files continue to load through the existing
matching path.
# Screenshots/Recordings/Graphs
<img width="1405" height="734" alt="publish_dialog"
src="https://github.com/user-attachments/assets/96b833c1-2b86-4c09-92b4-a4471a567e62"
/>
[publish_dialog_settings.webm](https://github.com/user-attachments/assets/acf22dd9-ae9b-4a58-b77d-8c2d9ffbc7a5)
## Tests
Added tests covering:
- Coverage for export slot masking, metadata round-trip,
type-match/replace/fallback semantics, slot growth, and skipped-key
reporting.
# Description
This PR redesigns `filament_id` across OrcaSlicer's profile library, so
that one filament
product now carries one consistent id everywhere it ships, instead of a
hand-written value that
unrelated materials routinely shared. Minting scripts and CI checks come
with it so future
profiles comply by construction: a new filament takes its id from the
tool, and the checks
reject a hand-written, duplicated or drifted one before it can merge.
Unique, non-duplicated ids are a precondition for AMS-style spool
syncing to be dependable —
the id is what a printer matches a physical spool against, and while two
products share one, the
match is a coin toss. This PR lays that groundwork. A follow-up PR will
publish an OrcaSlicer
materials reference on the wiki, giving every system profile one place
to point at.
`filament_id` names one filament product, and it is what a device
matches a physical spool
against: Bambu AMS, Creality CFS, the Qidi box, Klipper and Snapmaker
all resolve a tray to a
preset by id alone, first hit wins. Those ids were written by hand, and
on `main` 99 of them
stand for 674 different products — `GFL99` alone covers 132, from
Anycubic PLA to Bambu PLA
Matte. Every consequence is silent: a spool resolves to whichever preset
happens to load first,
tray names and support-material flags are read off the wrong material,
and the second preset
holding a duplicated id disappears from the tray-edit dialog entirely.
The id is now a hash of `(filament_vendor, filament_type, filament
name)`, so one spool product
carries one id in every bundle that ships it, two vendors shipping the
same product converge on it
without coordinating, and a collision cannot be authored by hand. Every
ambiguity across 48
vendors is fixed rather than excused — no grandfather list and no
per-vendor carve-out, Bambu's
bundle included — and the resulting landscape is frozen in
`scripts/filament_id_snapshot.json`,
so a change to any filament's identity lands as a reviewable diff to one
file. CI now runs the
duplicate-subtype validation tree-wide instead of over Bambu only.
Letting the id follow the product meant correcting the identities
themselves. Generics that
shipped under a vendor prefix now have one name and one id everywhere
(`Blocks Generic PETG` is
`Generic PETG @Blocks`), presets whose `filament_vendor` or
`filament_type` contradicted the
spool are fixed, and duplicate pairs are collapsed onto the
better-configured survivor. Renames
carry `renamed_from`, so existing projects and user presets keep
resolving.
Bambu's printers, its AMS and its cloud know only Bambu's own catalog
ids, so those ids leave
the profiles entirely. The Bambu bundle mints like every other vendor,
and the printer agent
swaps in the catalog value only where an id crosses to or from a Bambu
printer — outbound MQTT
and FTP, the AMS mapping sent with a job, the ids written into a 3mf the
printer will read —
mapping back on the way in, so status messages, SD-card prints and
projects saved by an older
Orca or by BambuStudio all still resolve. The correspondence is
generated from BambuStudio's
own shipped bundle by `scripts/update_bambu_filament_ids.py`; an id with
no row is forwarded
untouched, a missing or malformed map degrades to no translation rather
than taking the app
down, and an agent whose printers already speak Orca's ids translates
nothing.
Two device-side bugs this work surfaced are fixed here as well. The Orca
Filament Library was
missing from the AMS material and calibration dialogs, which treated a
filament with no
`compatible_printers` as compatible with nothing while the rest of the
app treats it as
compatible with everything; and Creality CFS sync on a K2-family stock
0.4 nozzle picked the
wrong preset, an imprecise matcher that duplicate ids had been masking.
`docs/HLSD/filament_id.md` is the authoring rule for all of this.
`scripts/orca_id_tool.py`
mints both `filament_id` and `setting_id`, replacing
`assign_vendor_setting_ids.py`, and the
local `check_profile` scripts gained per-vendor scoping so one vendor
can be checked without a
tree-wide run. `scripts/tests/` covers the tooling; `tests/slic3rutils/`
covers the boundary
translation and the CFS matcher.
Ids change for most products and nothing forwards the old value, so a
tray or a calibration
record still holding one falls back to matching by filament type until
the filament is selected
once. Beyond the profile fixes above no print settings change, except
that a few presets stop
claiming printers a dedicated variant already covers.
# 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.
-->
`scripts/check_profile.sh`, the local twin of the "Check profiles" CI
job, with
`scripts/check_profile.bat` as its Windows entry point, passes on this
branch: the extra JSON
check reports no errors and no warnings, system validation and the now
tree-wide
filament-subtype check load all 66 vendors cleanly, all 1013 printer
presets slice, and
custom-preset validation passes against every fixture archive from
v1.9.0 to v2.4.2.
The id tooling has 176 unit tests (`python -m unittest discover -s
scripts/tests`). The C++
suites pass too — 332 in `tests/libslic3r` and 126 in
`tests/slic3rutils`, the latter including
the boundary-translation and Creality CFS matching cases added here.
<!--
> 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)
* Add ffmepg dep
* NEW: reimpl wxMediaCtrl from ffmpeg
Jira: none
Change-Id: I46a47118a7649b2a50fcce8911e2888342ef25de
(cherry picked from commit d6c7f08769c8cfdbbf0e80ad280c9b3408a3c27d)
(cherry picked from commit 94d91be60bfe9bbbcdd21f85b46abc3faf126f17)
* FIX: reset bambu lib after restart network plugin
Change-Id: I4a3a4b7420745835ca3fa00c6edebe9d8d98cbf6
Jira: STUDIO-7571
(cherry picked from commit 28d9c6743fae80bfd40e4ee391e30d62cb16d4ab)
* FIX: ffmpeg decoder memory leak
Change-Id: I997572b5730618a969959f9b24c405d80fa9f83c
Jira: STUDIO-7597
(cherry picked from commit 342cea29bd9593fa89cbb33caff58055b46ebeec)
* FIX: install ffmpeg symbolic sos
Change-Id: Ia4a45182cefcf62a7a4b4a5c89c92251609c5a68
Jira: none
(cherry picked from commit b7f8fa1efdbe0ac2cc896ca24f063f5894fe9f90)
* FIX: ffmpeg swscale & frame_size
Change-Id: I9f4cb8c739b726f7e5cdbe0df7ed06b2eb2154d5
Jira: STUDIO-7624
(cherry picked from commit 5a2c75d835fb437667b590a803eef148baa30875)
* FIX: wxMediaCtrl3 idle image & center pos
Change-Id: Ib9652573e31bfd6229f174c0a1388942d9d98822
Jira: STUDIO-7633
(cherry picked from commit d51247c46e26460b151de79c598d81151280e79c)
* FIX: AVVideoDecoder sws_ctx_ == nullptr on zero size
Change-Id: I9698354bb1f341e276ec9780d4ef4fcd9f8a1028
Jira: STUDIO-7706
(cherry picked from commit ff622e25026a8471c39eb308cf5b115c4a9d84aa)
* fix:cannot open shared object file on linux
Change-Id: Ica66500506cfe8932eac3ae0a58fb7ff30d1da9b
jira:none
(cherry picked from commit febd1aeb4d453bc96571fa5e5727e9e10046cb80)
(cherry picked from commit 5ad579f929154779abd84b01438fd235c647dbf5)
* NEW:add ffmepg build Cmake
buildLinuxImage add ffmpeg so file
jira:nojira
Change-Id: I3e1be53aa58a179b8d9ae048ed7538de3ae8d111
(cherry picked from commit 2d70a1bcb6a5ba601525b08a38e7610f018fe106)
* FIX: ffmpeg cmake install error
jira:nojira
Change-Id: I74cc0f7c86b5364e55cad2af2bd9a82306ee6864
(cherry picked from commit 805df79e3bb044dac29ec1c06736751ccf3675f9)
* FIX: decode video to wxImage on Linux
Change-Id: I5e332a1b0622b3dfc70ac5c4c3bfa62b3411ebdc
Jira: none
(cherry picked from commit c787ba921a31f259e8eb23fd59f178e96279caf9)
* FIX: wxMediaCtrl3 enter Stopped state soon
Change-Id: I120e9d4b9f85599a184650d1d95fe2bec42af171
Jira: STUDIO-8280
(cherry picked from commit 7648d96305d510b9e97f22124961de5115cde830)
* FIX: reset decode buffer zero when scale width changed
Change-Id: Iaa2f99111dd5f7228b7b25e1be0a8cbdbfe982a6
Jira: STUDIO-8422
(cherry picked from commit 659ebc7d07a8f6045ba5443141b44277d7257cec)
* slic3r: Fix missing declarations in wxMediaCtrl3.h
src/slic3r/GUI/wxMediaCtrl3.h:80:10: error: ‘condition_variable’ in namespace ‘std’ does not name a type
80 | std::condition_variable m_cond;
| ^~~~~~~~~~~~~~~~~~
src/slic3r/GUI/wxMediaCtrl3.h:27:1: note: ‘std::condition_variable’ is defined in header ‘<condition_variable>’; did you forget to ‘#include <condition_variable>’?
26 | #include "Printer/BambuTunnel.h"
+++ |+#include <condition_variable>
27 |
src/slic3r/GUI/wxMediaCtrl3.h:81:10: error: ‘thread’ in namespace ‘std’ does not name a type
81 | std::thread m_thread;
| ^~~~~~
src/slic3r/GUI/wxMediaCtrl3.h:27:1: note: ‘std::thread’ is defined in header ‘<thread>’; did you forget to ‘#include <thread>’?
26 | #include "Printer/BambuTunnel.h"
+++ |+#include <thread>
27 |
In file included from src/slic3r/GUI/MediaPlayCtrl.h:17,
from src/slic3r/GUI/MediaPlayCtrl.cpp:1:
src/slic3r/GUI/wxMediaCtrl3.h:77:13: error: field ‘m_frame’ has incomplete type ‘wxImage’
77 | wxImage m_frame;
| ^~~~~~~
(cherry picked from commit 727a73333bd67acf5ff2b1c51ff284c2bacdb413)
* slic3r: Fix missing includes in AVVideoDecoder
In file included from src/slic3r/GUI/AVVideoDecoder.cpp:1:
src/slic3r/GUI/AVVideoDecoder.hpp:28:20: error: ‘wxImage’ has not been declared
28 | bool toWxImage(wxImage &image, wxSize const &size);
| ^~~~~~~
src/slic3r/GUI/AVVideoDecoder.hpp:28:36: error: ‘wxSize’ has not been declared
28 | bool toWxImage(wxImage &image, wxSize const &size);
| ^~~~~~
src/slic3r/GUI/AVVideoDecoder.hpp:38:10: error: ‘vector’ in namespace ‘std’ does not name a template type
38 | std::vector<uint8_t> bits_;
| ^~~~~~
src/slic3r/GUI/AVVideoDecoder.hpp:9:1: note: ‘std::vector’ is defined in header ‘<vector>’; did you forget to ‘#include <vector>’?
8 | #include <libswscale/swscale.h>
+++ |+#include <vector>
9 | }
src/slic3r/GUI/AVVideoDecoder.cpp:145:89: error: invalid use of incomplete type ‘class wxBitmap’
145 | bitmap = wxBitmap((char const *) bits_.data(), size.GetWidth(), size.GetHeight(), 32);
| ^
(cherry picked from commit 781ce14e061366da64fdc2d0d592fa35ee57e67e)
* slic3r: Fix missing includes in wxMediaCtrl2
src/slic3r/GUI/wxMediaCtrl2.cpp: In lambda function:
src/slic3r/GUI/wxMediaCtrl2.cpp:170:13: error: ‘wxMessageBox’ was not declared in this scope; did you mean ‘wxInfoMessageBox’?
170 | wxMessageBox(_L("Your system is missing H.264 codecs for GStreamer, which are required to play video. (Try installing the gstreamer1.0-plugins-bad or gstreamer1.0-libav packages, then restart Bambu Studio?)"), _L("Error"), wxOK);
| ^~~~~~~~~~~~
| wxInfoMessageBox
src/slic3r/GUI/wxMediaCtrl2.cpp: In member function ‘void wxMediaCtrl2::Load(wxURI)’:
src/slic3r/GUI/wxMediaCtrl2.cpp:179:5: error: ‘wxLog’ has not been declared
179 | wxLog::EnableLogging(false);
| ^~~~~
(cherry picked from commit 73908d38d8b1f7c8dcae92d55711bc08cbfff23c)
* slic3r: Fix missing wxPaintDC declaration
src/slic3r/GUI/wxMediaCtrl3.cpp: In member function ‘void wxMediaCtrl3::paintEvent(wxPaintEvent&)’:
src/slic3r/GUI/wxMediaCtrl3.cpp:121:5: error: ‘wxPaintDC’ was not declared in this scope; did you mean ‘wxPoint’?
121 | wxPaintDC dc(this);
| ^~~~~~~~~
| wxPoint
(cherry picked from commit 9ab5009235d212699f91e01d7f930f92849ed1e3)
* slic3r: Fix missing BOOST_LOG_TRIVIAL declaration
src/slic3r/GUI/wxMediaCtrl3.cpp:181:23: error: ‘info’ was not declared in this scope
181 | BOOST_LOG_TRIVIAL(info) << msg.ToUTF8().data();
| ^~~~
src/slic3r/GUI/wxMediaCtrl3.cpp:181:5: error: ‘BOOST_LOG_TRIVIAL’ was not declared in this scope
181 | BOOST_LOG_TRIVIAL(info) << msg.ToUTF8().data();
| ^~~~~~~~~~~~~~~~~
(cherry picked from commit c5c41e20ca2fc7f3b53a4c769961f73df6992008)
* FIX: wxMediaCtrl3 zero size crash
Change-Id: I16a3f7b3afe142bb957a1740b8e8c9820c92b349
Jira: STUDIO-8522
(cherry picked from commit 8cdaea1162ccbcc0bd03ecd99346f3b9cf52cf64)
* FIX: TabCtrl button margin
Change-Id: If8b05a4ef9efb8b57989ee1de6543631e5a3cf90
Jira: STUDIO-8265
(cherry picked from commit 1c5e65707109ad0582b6442cf8e515344f799c27)
* ENH: wxMediaCtrl3 display video frame at pts
Change-Id: I8847236d2307101e5f2befc6477cd20b3691841c
Jira: none
(cherry picked from commit 05328da4612c11d50f6fd90e872b97f5f8f46b1d)
* Fix: fix memory leak caused by ffmpeg decoding
Change-Id: I162ad4ea8d4601c1ffe17a65f292566c9dea6f0b
jira: no-jira
(cherry picked from commit eb20d03186c86b7398b97e3bae0a3c7a7b81c58c)
* ENH: update some missing codes
jira: no-jira
Change-Id: Icb2da53911430ac144b0fb601637a7ad31e7e8db
(cherry picked from commit 13b4213f8a24c76c16e49daf905fa29c0f646a5a)
* Fix build
* Update idle image
* Attempt to fix Windows CI build
* FIX: GTK video window resize ran in a free function without member access
wxMediaCtrl_OnSize referenced wxMediaCtrl2's private m_gtk_video_window,
which does not compile on Linux/GTK. Move the resizing into
wxMediaCtrl2::DoSetSize where the member is in scope.
* Install required tools for Linux
* Install required tools for macOS
* Add ffmpeg to flatpak
* Fix Linux build
* Try fix appimage build
* Fix Linux AppImage bundling of deps-built shared libraries
The AppImage dependency closure resolves each bundled ELF's DT_NEEDED
entries with plain ldd, which cannot resolve the deps-built FFmpeg stack
(libavcodec/libavutil/libswscale) once it is copied into the bundle:
those libs are not installed in any standard loader path and carry no
RUNPATH of their own, so ldd reports the siblings as missing and the
build aborts. Extend the loader path with the bundle directory plus the
source directories of already-bundled files (mirroring
scripts/check_appimage_libs.sh), and key the dedup set on the bundled
file path instead of the source path so dependencies resolved from the
bundle directory are not copied onto themselves.
Co-Authored-By: Claude <noreply@anthropic.com>
* Attempt to fix Linux unit test
* Fix Linux unit tests loading deps-built FFmpeg libraries
The test executables that link libslic3r_gui (which links PkgConfig::LIBAV)
have a load-time dependency on the deps-built FFmpeg shared libraries. The CI
unit-test runner only receives the tests artifact, so those libraries were
unresolvable there (Ubuntu 24.04 ships libavcodec.so.60, not .61). Copy the
libraries next to each affected test executable and give it an $ORIGIN rpath,
mirroring the Windows branch that copies DLLs next to every test executable.
orcaslicer_copy_sos now places the copies in the per-config output directory
for multi-config generators, like orcaslicer_copy_dlls does.
Co-Authored-By: Claude <noreply@anthropic.com>
* Add design doc for macOS FFmpeg player
Co-Authored-By: Claude <noreply@anthropic.com>
* Add implementation plan for macOS FFmpeg player
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: use FFmpeg media player on macOS with static FFmpeg
* build: build static-only FFmpeg for macOS deps
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: remove old BambuPlayer-based media player from macOS
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: add static FFmpeg NOTFOUND guard; drop dead wxMediaCtrl2.h include
* build: drop redundant --enable-shared in FFmpeg deps configure
The literal --enable-shared was always overridden by ${_link_cmd}
(--enable-static --disable-shared on Apple, --enable-shared elsewhere)
and FFmpeg configure processes these flags in order, last one wins.
Remove it and the stale comment documenting the workaround.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: remove dead wxMediaCtrl2 player
wxMediaCtrl2 was never instantiated on any platform (USE_WX_MEDIA_CTRL_2
is 0 everywhere); wxMediaCtrl3 replaced it. Delete wxMediaCtrl2.cpp/h,
drop them from the Win/Linux source list and the gettext list.txt, and
collapse the preprocessor-dead #if USE_WX_MEDIA_CTRL_2 gate in
MediaPlayCtrl.h.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: remove dead GStreamer bambusrc plugin and its build dep
gstbambusrc was the GStreamer source element for the old wxMediaCtrl2
Wayland player, its only consumer (deleted in the previous commit).
The new FFmpeg player handles bambu:/// URIs through the Bambu C API
instead. Drop the plugin and the gstreamer-1.0 / gstreamer-base-1.0
REQUIRED pkg-config dependencies that existed solely for it.
Co-Authored-By: Claude <noreply@anthropic.com>
* build: move FFmpeg media player sources to the common GUI list
wxMediaCtrl3 and AVVideoDecoder are platform-neutral C++ compiled on
all three platforms, so list them once in the common SLIC3R_GUI_SOURCES
instead of duplicating them in the APPLE and non-APPLE branches. The
else() branch is now empty and drops out entirely.
Co-Authored-By: Claude <noreply@anthropic.com>
* deps: disable FFmpeg VideoToolbox/AudioToolbox HW-accel on macOS
The static libavcodec.a/avutil.a compiled the auto-detected
videotoolbox/audiotoolbox objects, which reference VideoToolbox
framework symbols (_VTDecompressionSession*). The app link line
happened to satisfy them transitively, but the orca_stubgen module
link (CI-only) failed with undefined symbols. The player decodes in
software (swscale), so disable both HW-accel paths to keep the
static libs self-contained.
Co-Authored-By: Claude <noreply@anthropic.com>
* Copy the decoded frame instead of aliasing the decoder's buffer
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.
---------
Co-authored-by: chunmao.guo <chunmao.guo@bambulab.com>
Co-authored-by: BBL\chuan.he <chuan.he@bambulab.com>
Co-authored-by: MackBambu <yongfang.bian@bambulab.com>
Co-authored-by: Bastien Nocera <hadess@hadess.net>
Co-authored-by: chao.zhang <chao.zhang@bambulab.com>
Co-authored-by: lane.wei <lane.wei@bambulab.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
A new extrusion role - erInternalBridgeInfill is introduced.
SuperSlicer's implementation is referenced.
Signed-off-by: SoftFever <103989404+SoftFever@users.noreply.github.com>