Commit Graph
30808 Commits
Author SHA1 Message Date
Ian Chua dcddb9283c fix: updated stale docs 2026-09-16 22:54:54 +08:00
Ian Chua ba9cf6e897 Revert "fix: latent ams in use bug"
This reverts commit 910dbcd2e6.
2026-09-16 22:54:54 +08:00
Ian Chua d1f2ecb903 feat: restore printer agent implementations 2026-09-16 22:54:46 +08:00
Ian Chua 753c793ea0 revert: filament sync work 2026-09-16 22:20:35 +08:00
Ian Chua 9c5494b19f fix: disable unused DataChannel media support 2026-09-16 22:08:53 +08:00
Ian Chua 93a119427a Merge branch main into feat/printer-agent-infra 2026-09-16 22:06:09 +08:00
Ian Chua d264fcaef4 fix: always build bundled DataChannel dep 2026-09-16 22:04:27 +08:00
Ian Chua b4ab6dedfd fix: move printer agent plugin tests into test_plugin_lifecycle.cpp 2026-09-16 21:33:04 +08:00
Ian Chua ed59f93456 fix: scope get_my_machine_list to printers listed under the current printer agent 2026-09-16 19:48:59 +08:00
Ian Chua cf52c81dcd fix: stop the correct media controller 2026-09-16 18:44:06 +08:00
Ian Chua 803a2a3239 fix: dedupe compatible printer type check 2026-09-16 17:18:59 +08:00
Ian Chua 985092bb46 fix: move non-mandatory printer agent function stubs to IPrinterAgent 2026-09-16 16:56:43 +08:00
Ian Chua cb16a2e547 feat: enable https camera stream mode 2026-09-16 16:24:29 +08:00
Ian Chua 2c2e91b629 fix: remove hardcoded ICE servers 2026-09-16 14:36:49 +08:00
Ian Chua c3faf903ca fix: use ORCA_CLOUD_PROVIDER instead of hardcoded string 2026-09-16 14:24:40 +08:00
Ian Chua 5f3c957597 fix: remove stale comment 2026-09-16 14:23:00 +08:00
Ian Chua 8557285389 fix: revert moonraker specific behavior 2026-09-16 14:21:09 +08:00
Ian Chua a9edab78a8 fix: inject provider, agent id and generation to get_user_print_info to ensure correct metadata 2026-09-16 14:15:24 +08:00
Ian Chua 79dede7d59 fix: change rtc log level 2026-09-16 14:14:21 +08:00
Ian Chua 2ac45b2f78 fix: invoke js clearInterval on WebMediaController::stop 2026-09-16 14:13:37 +08:00
Ian Chua b4f33e71e9 fix: add internal_developer_mode chekc back to MediaPlayCtrl::load() 2026-09-16 14:12:48 +08:00
SoftFever a0ada1aa88 fix wiki links 2026-09-16 00:43:50 +08:00
Kris Austin 9409598c2a ci: run the unit-test suite under the flatpak build's bounds-checked STL (#14709)
* ci(flatpak): run the unit suite in a separate job, mirroring the other arches

Alternative to the in-job step: split build and test like the Linux/Windows/
macOS legs. The flatpak build now builds the test binaries in-sandbox (the
action's run-tests fires the module's build-only test-commands), prunes the
kept build tree to the test binaries + CTest metadata + data, and uploads it
with /app as a test asset (size reported to the run summary).

A new unit_tests_flatpak matrix job downloads that asset on a native runner,
restores the module-build symlink, and runs the suite via flatpak-builder
--run (which bind-mounts /run/build so TEST_DATA_DIR resolves) against the
GNOME SDK's bounds-checked STL. Results feed publish_test_results.

Costs a per-arch asset upload/download + a runtime install on the test
runner; the trade-off vs the in-job step is a genuine separate graph box.

* ci(flatpak): run tests via `flatpak build` to avoid rofiles-fuse

`flatpak-builder --run` sets up a rofiles-fuse overlay that this CI container
rejects (Failure spawning rofiles-fuse, exit_status: 256), even in a fresh job
with a machine-id and the runtime installed, and --disable-rofiles-fuse is not
accepted in --run mode. `flatpak build` enters the sandbox via bwrap directly,
so it sidesteps rofiles-fuse; bind-mounting the build tree at /run/build gives
the same path the compiled-in TEST_DATA_DIR expects.

* ci(flatpak): slim the test asset (strip binaries, drop source tree)

The first cut shipped ~1 GB: the test exes carried debug info (the SDK builds
with -g and only the app gets stripped) and the packaged module dir included
the whole copied source tree the tests never read at runtime. Strip the test
binaries and keep only build_flatpak/tests, tests/ (TEST_DATA_DIR) and scripts/.
The irreducible remainder is /app, which the exes link against.

* ci(flatpak): extract the test run into a reusable unit_tests_flatpak workflow

Move the flatpak test job out of build_all.yml into a reusable
unit_tests_flatpak.yml, called once per arch (Flatpak x86_64 / aarch64) the
same way the other arches call unit_tests.yml. build_all.yml keeps only the
build + asset packaging; the reusable workflow downloads the asset, runs the
suite via `flatpak build`, and uploads results as test-results-<artifact> for
publish_test_results. Drops the now-unused manifest checkout (flatpak build
does not need it).

* ci(flatpak): trim comments to the non-obvious

No behavior change.

* ci(flatpak): drop redundant caller comment

* ci(flatpak): drop redundant trim comment

* ci(flatpak): drop size-report scaffolding and redundant if-guards

* ci(flatpak): force the app module to rebuild so the test asset always exists

flatpak-builder caches modules by content hash and skips a hit, producing no
build tree and no test asset, so a re-run of the same commit would leave the
separate test job with nothing to download. Inject a per-run cache-buster into
the OrcaSlicer module's build-options (part of its cache key) so it always
rebuilds, mirroring how the other arches cache only deps and always rebuild the
app and tests. The deps modules stay cached.

* ci(flatpak): trim cache-buster comment, fix stale step name

* fix: guard H2C per-filament array reads against short config arrays

The H2C tool-ordering, wipe-tower, and g-code export paths index per-filament
config arrays by filament/tool id. A config with fewer entries than the filament
count (partial or legacy projects, minimal test configs) makes these reads run
past the end of the vector: silent under a normal STL, but UB that aborts under
the flatpak build's bounds-checked STL (_GLIBCXX_ASSERTIONS).

Route the reads through the existing clamping accessors (get_at,
get_filament_category, is_in_same_extruder) and add a small clamp helper for
filament_change_length. The guards are no-ops when the arrays are sized to the
filament count, so correctly specified configs are unaffected.

* ci(flatpak): build filament_group_tests too

The suite landed on main after this branch was cut and arrived via a later merge,
so it was missing from the target list and ctest failed the leg with
filament_group_tests_NOT_BUILT.

Not tests/all, which build_linux.sh uses: that is a Ninja subdirectory target and
this build configures with the default Makefile generator, where it does not exist.

* ci(flatpak): give the embedded-interpreter tests a valid Python home

python_test_support.hpp sets PyConfig.home to <testdir>/python when that
path resolves. WIN32/APPLE populate it with a copied bundled runtime; the
flatpak leg had no such branch, so home resolved to a directory with no
stdlib and all 21 embedded plugin tests failed at "failed to get the
Python codec of the filesystem encoding".

Symlink <testdir>/python to the bundled /app/libpython that already ships
in the flatpak (the test exe links libpython3.12.so from there via rpath),
so the interpreter initializes without duplicating the runtime.

* ci(flatpak): sync the ToolOrdering guard mirror with #14789

Match #14709's build_filament_group_context guard to the version on
#14789 (size filament_info to filament_nums, truncate filament_ids)
so the folded guard is a byte-identical mirror that drops cleanly when
#14789 merges, instead of leaving a stale hunk that conflicts on rebase.

* fix: guard WipeTower per-filament array reads against short config arrays

The BambuStudio WipeTower sync reintroduced raw per-filament array
indexing that reads out of bounds when a config leaves an array shorter
than the filament count: m_physical_extruder_map in format_line_M104/M109
(indexed even when empty), and m_filament_categories in get_wall_skip_points
and get_wall_filament_for_all_layer. Silent on a normal STL, a hard abort
under the bounds-checked STL the Flatpak build uses.

Bounds-check the physical extruder map before indexing (omitting the T
token, as the existing -1 path already does), and route the two raw
m_filament_categories reads through the clamping get_filament_category()
accessor the surrounding code already uses. No change for correctly-sized
configs.

* fix: default-initialize WallToolPathsParams fields

min_length_factor and is_top_or_bottom_layer had no default initializers, and the FillConcentric/FillConcentricInternal callers never set them, so WallToolPaths::removeSmallLines() thresholded on stack garbage. Which short extrusion lines it dropped then depended on memory layout, so concentric solid-infill output was nondeterministic between runs and across machines. Give every member a default, matching the adjacent FillParams. The perimeter path was already fine because it builds the struct via make_paths_params().

* fix: bounds-check the toolchange flush-volume and HRC per-filament lookups

GCode::set_extruder's toolchange flush-volume lookup and
GCodeProcessor::update_slice_warnings's HRC check index per-filament and
per-extruder arrays (flush_volumes_matrix, the filament map, the nozzle list)
by filament/extruder id. When a config leaves one of those arrays shorter than
the filament count (partial or legacy multi-extruder projects, minimal
configs), the reads run off the end: silent on a normal STL, a hard abort under
_GLIBCXX_ASSERTIONS.

Route both reads through bounds checks: the flush lookup falls back to no flush,
matching the existing unknown-old-filament branch beside it, and the HRC check
skips an unmapped filament, mirroring the required_nozzle_HRC guard on the line
above. When the arrays are sized to the filament count the values are unchanged,
so correctly-specified configs are unaffected.

* ci: retrigger checks

* ci: name the flatpak rebuild token after the cache it defeats

Since #15650 the Flatpak job also has a compiler cache, so a bare
"cache-buster" no longer says which cache is meant. Call it
flatpak_builder_cache_buster, and name the build-dir trim step after
the flatpak-builder cache save it keeps lean.

* ci: ship resources/profiles and resources/printers in the flatpak test asset

Two slic3rutils tests added in 4aa0e1d60b read
resources/printers/bambu_filament_ids.json through PROFILES_DIR/.., and
the asset dropped resources/ entirely, so both failed parsing an empty
stream on each Flatpak leg. Keep the two subtrees the tests reach;
test_gcodewriter's shipped-profile case stops skipping on this leg too.

* ci: restore the CRLF line endings of build_all.yml

The last merge from upstream/main rewrote the file with LF endings, which
turns the 60-line change into a whole-file diff on GitHub. Upstream has had
this file as CRLF since it was created, so put it back.

* ci: trigger Build all on changes to the unit-test workflows

The path filters only matched build_*.yml, so an edit to unit_tests.yml or
unit_tests_flatpak.yml could merge without ever running.

* ci: put a timeout on the flatpak unit-test step

Matches the 20 minutes of the regular unit-test workflow; without it a hung
test holds the runner for the six-hour job default.
2026-09-15 12:41:46 -03:00
Kris Austin 7e545651bb deps: compile unicodectype.c unoptimised in the Windows arm64 Python (#15719)
VS 2026's ARM64 code generator needs about 27 GB for
_PyUnicode_ToNumeric, a switch with 1951 cases in
Objects/unicodetype_db.h; the same file takes under 1 GB on x64. The
16 GB CI runner has an 18.9 GB commit limit and only gets through when
Windows grows the pagefile on the temp disk in time, so cold arm64
dependency builds fail at random with C1002 "compiler is out of heap
space". build_release_vs.bat returns 0 on failure, so the job still
reports success and the incomplete dependencies are cached.

A property sheet compiles that one file with optimisation off on arm64;
the rest stays whole-program optimised and x64 is unchanged.
MSBuild reads it from PCbuild/msbuild.rsp, which is now written at
configure time and copied in, so a checkout path with spaces works too.
2026-09-15 11:55:11 -03:00
Kris Austin ac3997c0d1 fix: bounds-check the toolchange flush-volume and HRC per-filament lookups (#15289)
* fix: bounds-check the toolchange flush-volume and HRC per-filament lookups

GCode::set_extruder's toolchange flush-volume lookup and
GCodeProcessor::update_slice_warnings's HRC check index per-filament and
per-extruder arrays (flush_volumes_matrix, the filament map, the nozzle list)
by filament/extruder id. When a config leaves one of those arrays shorter than
the filament count (partial or legacy multi-extruder projects, minimal
configs), the reads run off the end: silent on a normal STL, a hard abort under
_GLIBCXX_ASSERTIONS.

Route both reads through bounds checks: the flush lookup falls back to no flush,
matching the existing unknown-old-filament branch beside it, and the HRC check
skips an unmapped filament, mirroring the required_nozzle_HRC guard on the line
above. When the arrays are sized to the filament count the values are unchanged,
so correctly-specified configs are unaffected.

* ci: retrigger checks
2026-09-15 09:46:31 -03:00
Kris Austin bd1304443c fix: guard per-filament array reads against short config arrays (#14789)
* fix: guard H2C per-filament array reads against short config arrays

The H2C tool-ordering, wipe-tower, and g-code export paths index per-filament
config arrays by filament/tool id. A config with fewer entries than the filament
count (partial or legacy projects, minimal test configs) makes these reads run
past the end of the vector: silent under a normal STL, but UB that aborts under
the flatpak build's bounds-checked STL (_GLIBCXX_ASSERTIONS).

Route the reads through the existing clamping accessors (get_at,
get_filament_category, is_in_same_extruder) and add a small clamp helper for
filament_change_length. The guards are no-ops when the arrays are sized to the
filament count, so correctly specified configs are unaffected.

* fix: size the grouping context's filament_info to the filament count

build_filament_group_context built model_info.filament_info by walking
filament_type, so a config whose filament_type is shorter than the filament
count produced a short vector. FilamentGroup indexes filament_info by filament
id, so clamping the individual reads only moved the out-of-bounds access
downstream. Loop to filament_nums and read all three fields through get_at,
and drop filament_ids entries past the filament count, since the grouping code
pairs filament_ids and filament_info by position.

Adds a regression test with four filaments and one-entry filament_type /
filament_is_support. Without the fix it throws bad_alloc from copying a garbage
std::string read past the end.

* fix: guard the carousel nozzle-change length reads too

The carousel branch added in b90ac13d86/b0dddb4648 reads
m_filaments_change_length by tool id without a bounds check, the same
pattern this branch already routed through filament_change_length_at
a few lines above in both plan_toolchange and plan_tower_new.

* fix: guard WipeTower per-filament array reads against short config arrays

The BambuStudio WipeTower sync reintroduced raw per-filament array
indexing that reads out of bounds when a config leaves an array shorter
than the filament count: m_physical_extruder_map in format_line_M104/M109
(indexed even when empty), and m_filament_categories in get_wall_skip_points
and get_wall_filament_for_all_layer. Silent on a normal STL, a hard abort
under the bounds-checked STL the Flatpak build uses.

Bounds-check the physical extruder map before indexing (omitting the T
token, as the existing -1 path already does), and route the two raw
m_filament_categories reads through the clamping get_filament_category()
accessor the surrounding code already uses. No change for correctly-sized
configs.
2026-09-15 09:03:20 -03:00
Ian Chua 8c91cab971 fix(ci): add libdatachannel to flatpak manifest 2026-09-15 20:01:48 +08:00
Ian Chua 79077518e9 fix: re-include apply header guarded by ifdef __APPLE__ 2026-09-15 19:45:14 +08:00
Lam Wei Lun bb3a260acb Update YouTube URL for Publish 3MF dialog (#15718) 2026-09-15 18:31:15 +08:00
Ian Chua 56aa348c89 fix(ci): set depends openssl 2026-09-15 18:16:50 +08:00
Lam Wei Lun 2b6eb425e4 Update YouTube URL for publish 3MF guide 2026-09-15 18:04:06 +08:00
Lam Wei Lun ae1752fbf2 Resolve printer agent first before getting cloud printer agent 2026-09-15 18:02:02 +08:00
Ian Chua cf3f36a1c6 Merge branch 'feat/printer-agent-infra' of https://github.com/OrcaSlicer/OrcaSlicer into feat/printer-agent-infra 2026-09-15 17:37:57 +08:00
Ian Chua cca7d8adb1 fix(ci): deps build order for datachannel 2026-09-15 17:35:25 +08:00
Ian Chua 396d9ff51a Merge branch 'main' into feat/printer-agent-infra 2026-09-15 16:47:15 +08:00
Ian Chua 81540c81e0 Merge branch 'feat/printer-agent-infra' of https://github.com/OrcaSlicer/OrcaSlicer into feat/printer-agent-infra 2026-09-15 16:46:38 +08:00
Ian Chua e7ace6cc99 fix: unit tests & unused variables 2026-09-15 16:46:28 +08:00
Lam Wei Lun 79c20a1fad Guard libdatachannel. Remove unused code 2026-09-15 16:33:12 +08:00
Ian Chua e48f9f47d2 Revert "fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests"
This reverts commit 2f566e3779.
2026-09-15 16:12:33 +08:00
Ian Chua 2f566e3779 fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests 2026-09-15 16:08:10 +08:00
Ian Chua 37d1edf69a fix: printer agent virutal optional functions 2026-09-15 15:54:55 +08:00
Lam Wei Lun f1cf9c69b1 Log first before std::move 2026-09-15 15:49:15 +08:00
Lam Wei Lun 1df362888e Fixes nullptr deref 2026-09-15 15:47:48 +08:00
HanifKoh 0956b4d8fe Add a Nightly Parity Workflow (#15712)
# Description

<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
  > * What issue does this PR address or fix?
  > * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->

Adds a nightly workflow that runs the long parity checks from
[orca-test-repo](https://github.com/OrcaSlicer/orca-test-repo), which
are too slow for the per-build "Run external slicer regression tests"
step and are kept out of every PR and merge build.

## What it runs

`.github/workflows/parity_nightly.yml`, three jobs:

| Job | What it does |
|---|---|
| Find the build to test | Picks the latest successful `build_all.yml`
run for the branch (`main` by default) and records its commit. |
| Override sweep effect stage (shard 0 and 1) | Runs orca-test-repo's
override sweep with `--effect-full`: every config option that lands on
the CLI is re-sliced on its own to check that it actually changes the
G-code. Split into 2 shards, each with a 60-minute timeout. |
| GUI-vs-CLI parity harness | Slices a set of fixtures in the GUI
(headless under Xvfb) and on the CLI, compares the exports, and scores
divergences against a known-differences ledger. It reports only and
never fails on a divergence. |

## When it runs

- **Every night at 21:00 UTC,** after `build_all.yml`'s 17:00 UTC run
has finished.
- **By hand** through `workflow_dispatch`, with optional inputs:
  - `build_branch`: the branch whose latest successful build to test;
  - `test_repo_ref`: the orca-test-repo ref;
  - `fixtures`: a subset of harness fixtures;
  - `cli_presets`: `flat` or `raw`.
- **No `push` or `pull_request` trigger,** so nothing here runs on PRs
or merges. The per-build CI step is unchanged.

## How it tests a build

- **Binary:** the Linux x86_64 AppImage from the chosen `build_all` run.
- **Source:** OrcaSlicer checked out at that run's exact commit. The
AppImage only ships packed preset caches, so profiles and the CLI option
list come from this checkout, matched to the binary.
- **Output:** each job writes a summary to the run page and uploads its
report (`override-report-shard*`, `parity-scorecard`) for 30 days.
- **Failures:** a failing effect shard fails the run, and GitHub's usual
failure notification for scheduled workflows applies.

# 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.
-->

- Dispatched on this branch against orca-test-repo `main` and #15693's
build ([run
34933239912](https://github.com/OrcaSlicer/OrcaSlicer/actions/runs/34933239912)).
Every job passed:
- **effect shard 0:** 19m31s; 225 options sliced, 151 effective, none
crashed or hung, every fixture sliced;
  - **effect shard 1:** 19m33s; 349 options sliced, 254 effective, same;
  - **harness:** 4m32s; all 13 fixtures, 0 new divergences, 0 errors.
- An earlier dispatch on this branch, testing #15693's build against
orca-test-repo's parity branch ([run
34836468900](https://github.com/OrcaSlicer/OrcaSlicer/actions/runs/34836468900)),
passed: effect shards in 20m28s and 23m30s, and the harness reported 0
new divergences.
- The workflow only runs from the default branch on its schedule, so the
nightly trigger itself takes effect once this is merged.

<!--
> 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)
2026-09-15 15:01:35 +08:00
HanifKoh 5514559feb Load Each Vendor Tree Once When the CLI Resolves System Presets (#15693)
# Description

<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
  > * What issue does this PR address or fix?
  > * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->

Since #15438, every CLI run that loads a system preset spends about a
second per preset file re-parsing that vendor's entire profile tree. A
slice with a machine, process and filament preset got roughly 2.5 s
slower, and a four-filament slice roughly 4 s slower. This PR loads each
vendor tree once per run instead. Resolved presets and G-code are
unchanged.

The GUI never takes this path, and no release contains #15438, so the
regression only affects CLI runs on current dev and nightly builds. That
includes print farms, slicing services and plugins that call
`orca-slicer --slice`, and CI suites.

## Changes

### Why it was slow

`PresetBundle::resolve_preset_config` resolves a system preset through
its vendor manifest by loading the whole OrcaFilamentLibrary bundle and
the whole vendor tree from JSON, then picking the one preset out. The
CLI did that separately for every `--load-settings` and
`--load-filaments` file, on a fresh `PresetBundle` each time. With BBL
presets, a machine + process + filament run opened `BBL.json` three
times and read BBL's 2,879 profile files and the library's 512 three
times over.

### Load each vendor tree once

- `PresetBundle` keeps every vendor bundle its manifest path loads,
keyed by source root, vendor and substitution rule, and reuses them for
later resolutions on the same bundle.
- OrcaFilamentLibrary is cached the same way, so vendors under one root
share a single library load and the library's own presets resolve from
that same instance. A vendor bundle only reads from its base while
loading, so sharing it is safe.
- A failed or throwing load is not kept, so error reporting is
unchanged.
- The key includes the source root, so presets from two different
profile roots still resolve separately.
- The CLI resolves every system preset through one `PresetBundle` for
the whole run, instead of creating one per file.

The resolved configurations still come from the same canonical vendor
loader, so what a preset resolves to does not change. Only the CLI calls
`resolve_preset_config`, so a long-lived GUI bundle cannot end up
holding profile trees that later change on disk.

# Screenshots/Recordings/Graphs

<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->

CLI slice of a 20 mm cube with X1 Carbon system presets. Both builds get
the same datadir, best of 3, Linux. "Before" is this PR's base from CI.

| System presets loaded | Before | After |
|---|---|---|
| machine | 0.95 s | 0.87 s |
| machine + process | 1.67 s | 0.92 s |
| machine + process + 1 filament | 2.51 s | 0.97 s |
| machine + process + 4 filaments | 5.00 s | 0.99 s |

Files opened during the machine + process + filament run (`strace -e
openat`):

| | Before | After |
|---|---|---|
| `BBL.json` | 3 | 1 |
| `OrcaFilamentLibrary.json` | 3 | 1 |
| `system/BBL/**/*.json` | 8,634 | 2,880 |
| `system/OrcaFilamentLibrary/**/*.json` | 1,536 | 512 |

Peak memory did not rise: max RSS 306 MB → 286 MB for the three-preset
run, and 305 MB → 285 MB for four filaments. The "before" figure is an
AppImage, so part of that gap is probably packaging.

## Tests

<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->

- New test "Manifest-backed resolution reuses the vendor tree it already
loaded" in `tests/libslic3r/test_preset_bundle_loading.cpp`. It resolves
one preset, changes the parent profile on disk, then resolves a sibling.
The same bundle returns the value it already loaded, and a fresh bundle
picks up the change.
- New test "Manifest-backed resolution shares the library between
vendors under one root". It resolves through one vendor, changes a
library profile on disk, then resolves through a second vendor and a
library preset on the same bundle. Both return the value already loaded,
and a fresh bundle picks up the change.
- All `[Preset][Bundle]` tests pass (87 test cases, 1,069 assertions),
including the existing manifest-backed resolution cases for source-root
scoping, malformed vendor loads, missing parents and type mismatches.
- G-code of the three-preset slice is identical before and after, header
lines excluded.
- The external CLI regression suite passes. Two cases report as
unexpectedly passing because #15639 fixed their bug. They pass the same
way on this PR's base without the change.
- A GUI-vs-CLI parity run over 10 fixtures shows no new differences.
- Builds clean on Linux (Release, with tests).

<!--
> 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)
2026-09-15 15:01:24 +08:00
Ian Chua 4b2466b179 fix: uninitialized ams state blocking print 2026-09-15 14:40:04 +08:00
Hanif Koh d5cf1502c4 Share One Library Load Between Vendors in the CLI Preset Resolver
The manifest resolver loaded OrcaFilamentLibrary once per vendor it
resolved through, so a run that mixes vendors parsed the library tree
again for each of them. The library is now cached like any other vendor
tree, keyed on its root and substitution rule, and doubles as the base
every vendor under that root loads against. A vendor bundle only reads
from its base while loading, so sharing the instance is safe.

The cache key carries the substitution rule as its enum, and the lookup
lambdas take a const bundle since they only read.
2026-09-15 13:31:30 +08:00
Ian Chua 3adcb3e953 fix: split infra from impl 2026-09-15 13:27:17 +08:00
HanifKoh 37e2b6c928 CLI: let --export-settings - write the merged config JSON to stdout (#15698)
`--export-settings` already writes the merged config as JSON at the
right point in the CLI flow. Passing `-` now writes that same document
to stdout, so scripts can inspect the effective config without a temp
file. This replaces #14605.

- `ConfigBase::save_to_json` gains a stream overload. The file overload
serializes through it before opening the file, so the output format is
unchanged, and a config that cannot be serialized (invalid UTF-8) now
leaves the existing file untouched instead of truncating it.
- On stdout, invalid UTF-8 in string values is written as U+FFFD instead
of ending the process with an uncaught `type_error`. Files keep the
strict behaviour.
- To keep stdout pure JSON, `-` is rejected up front (stderr message,
`CLI_INVALID_PARAMS`, shell status 254) when combined with an action or
transform that can write to stdout or does real work: `--info`,
`--help`, `--orient`, slicing and exporting. Options that do nothing
without a slice (`--uptodate`, `--min-save`, `--pipe`, ...) are still
accepted.
- The one unconditional stdout write on a success path, "skip locked
instance" during arrange, now goes to the log.
- Every other value, including the default `output.json`, behaves as
before.

Tests in `tests/libslic3r/test_config.cpp`: the stream output equals the
file output and keeps the tab-indented format; invalid UTF-8 throws on
the strict path and is replaced when asked; a failed save leaves the
previous file intact.
2026-09-15 13:16:22 +08:00
Kris Austin efc9f253ee fix: resolve relative input paths given on the command line (#14803)
Opening a model with a relative path, for example `orca-slicer ./some.3mf`,
failed with "Loading of a model file failed." and "The file does not contain
any geometry data.", while the same file opened by an absolute path or by
drag and drop worked.

GUI_App::init_app_config() changes the working directory to <data_dir>/log,
and it runs from the GUI_App constructor because the app config is needed
early for instance checking. The input files are opened much later, in
post_init(), so a path still relative at that point resolved against the log
directory instead of the directory OrcaSlicer was started from, and the 3MF
reader failed to open it.

Resolve the input paths in CLI::setup(), which runs before GUI_App is
constructed and therefore before the working directory moves. Absolute paths
are returned unchanged, so the forms that open today are unaffected, and
custom open protocol URLs are passed through since post_init() hands those to
the downloader rather than the file loader.

The working directory change is left alone. It was added in #3248 so the TUTK
logs land in the data directory instead of the working directory (#3209).
2026-09-15 12:47:01 +08:00