# 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?
-->
Part 1 of 3 of the CLI-mode bug sweep, split out of #15452 per review
feedback there. This PR contains the crash fixes.
## Fixes
- **`--outputdir`/`--datadir` with a missing parent directory aborted**
via unguarded `create_directory`. Directories are now created
recursively, with a graceful early exit and a specific error message if
creation fails.
- **`--slice` + `--export-3mf` segfaulted on a from-scratch slice**:
`ConfigOptionVector::get_at()` on an empty vector is `.front()` of an
empty vector (UB). Guards added for `filament_color`/`filament_id` at
the CLI call site, and inside `DynamicPrintConfig::get_filament_type`
for `filament_type`/`filament_is_support`/`filament_id`. Only *empty*
vectors are treated as missing — the existing clamp-to-front behavior
for merely out-of-range indices is preserved, so GUI callers are
unaffected.
- **OOB heap write from stale `filament_self_index` on
`--load-filaments`** (fixes#14181): a 3MF carrying more
`filament_self_index` entries than loaded filaments wrote past the end
of `old_variant_counts`. The guard validates both bounds — entries `>
filament_count` *and* non-positive entries (`< 1`), since a single `0`
in an otherwise-valid array indexes `old_variant_counts[-1]`.
- **Wrong printable-area check** for non-rectangular beds: use the
printable area's bounding box instead of a naive vertex calculation
(fixes#15363).
- **`nozzle_height` and `align_center` were not read into the arrange
config** in CLI mode.
# 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.
-->
- Repro'd each crash on CLI before the fix; all resolved after.
- `tests/libslic3r` suite passes; full binary builds clean on Linux.
- Added `get_filament_type` unit 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)
No IMEX code upstream, so nothing in this merge touches the feature. All 21 overlapping
files auto-resolved; verified every upstream addition is present in the merged tree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Reject invalid CLI argument values instead of silently accepting them
* Add read_cli accept/reject tests
* Update Option Type for LogFile argument
* Add read_cli vector option tests
* Accept common bool spellings on the CLI, cover --logfile in tests
* Add unit tests for truthy bool parsing
Follow-up to #14785. Routes the tests that still hand-rolled temp paths through
the shared helpers and unifies the temp guards.
- Add ScopedTemporaryDir and a shared ScopedTemporaryPath base under it and
ScopedTemporaryFile.
- Move test_3mf's round-trip .3mf output out of the TEST_DATA_DIR source tree
(a fixed-name leak) and test_toolordering's fixed-name temp .gcode (a sharding
collision) onto ScopedTemporaryFile.
- Move test_config, test_slicing_pipeline_bindings, the test_3mf backup dirs, and
test_preset_bundle_loading onto the guards.
- Make slic3rutils ScopedDataDir compose ScopedTemporaryDir; dedupe
test_network_versions' fixture and delete test_plugin_lifecycle's duplicate.
Resolved 4 conflicts:
- PrintConfig.hpp / Preset.cpp: upstream restored calib_flowrate_topinfill_special_order
(removed in the prior merge, now re-added and re-registered); kept it alongside our
IMEX options (imex_parallel_mode, imex_head_filament_map).
- Plater.cpp: kept our <sstream> include plus upstream's <optional> and plugin includes.
- tests/fff_print/test_gcodewriter.cpp: both sides appended disjoint scenarios after a
shared base. Reconstructed as upstream's full file (base + its 3 toolchange/H2C
scenarios + the boost/filesystem include its helper needs) followed by our 10
set_pressure_advance / set_temperature scenarios. 22 scenarios total, no duplicates.
Resolve five conflicts, all of which needed both sides rather than a pick:
- BackgroundSlicingProcess: ours was a pure tabs->spaces reformat of base, so
keep main's per-filament volume/nozzle map read-back (its only change here).
- GUI_App: main's #12506 else-if attached to an `if` this branch deleted;
re-expressed onto the same-agent early-return path (the agent factory caches
per id, so pointer equality is the same predicate).
- MainFrame: both sides relocated Sync Presets independently; keep main's
push_notification plus the branch's Plugins menu items.
- Tab: the "TODO: Orca: Support hybrid" blocks were unchanged base, not a branch
decision; take main's enabled Hybrid to match the already auto-merged siblings.
- test_config: union of both sides' cases (6 plugin + 9 multi-nozzle).
Conflicts were all co-located additions rather than design collisions:
- GCode.cpp: adopt upstream's toolchange(filament_id, nozzle_id) signature and
per-variant set_config_index() while keeping the IMEX bare-T<n> suppression;
rebase the second-layer temperature loop's non-IMEX branch onto upstream's
get_filament_config_index() resolution.
- Preset.cpp / PresetBundle.cpp / PrintConfig.cpp: keep both sides' option-list
and enum-map entries.
- GLCanvas3D.cpp: upstream's printable_heights argument plus the IMEX ghost pass.
- PartPlate.cpp: keep <set> (still used).
- test_gcodewriter.cpp / test_3mf.cpp: keep both sides' test cases.
Resolves two conflicts:
- GLCanvas3D.hpp: keep both the IMEX ghost render declarations and
upstream's _render_wireframe_overlay().
- test_gcodewriter.cpp: both sides appended test cases to the same
region; keep upstream's origin/machine-limit tests alongside the
pressure-advance and temperature scenarios.
* ENH: config: add logic to apply params to object/region config with multi-extruder
JIRA: no-jira
Change-Id: Ieab98cd8d031e5ca82a3aad2d0b89d8ae4a794f1
(cherry picked from commit 3179fd416e68ca8bc2d746f859508d07db18fe5b)
* FIX: X1C switch to H2D lose Highflow parameter
Jira: STUDIO-15272
Change-Id: Id8cf5d93a49d5542ac82f9554974b458e15c1193
(cherry picked from commit 15d9f072ff658a3beb4f916d978dfea12c2d9f16)
* Fix mishandling of `stride` param and add unit test for it
* Fix modified multi-variant per-obj option highlight
* Fix issue that per-obj FloatsOrPercents options are marked as dirty incorrectly when lost focus
---------
Co-authored-by: lane.wei <lane.wei@bambulab.com>
Co-authored-by: weiting.ji <weiting.ji@bambulab.com>
G-code post-processing is now a step of the slicing-pipeline plugin rather than a
separate capability type. One capability class can transform slices at the geometry
seams AND edit the final G-code, behind a single picker/option.
- Add SlicingPipelineStepPlugin::psGCodePostProcess (bound as
orca.slicing.Step.psGCodePostProcess). Unlike the geometry steps it fires from the
GUI export path in PostProcessor.cpp, not from Print::process(): ctx.print/ctx.object
are None and the plugin edits the file at ctx.gcode_path in place. It may run more
than once per slice (file export and/or upload) and its output is not shown in the
preview.
- Extend SlicingPipelineContext with gcode_path/host/output_name and a C++-only
full_config; config_value() falls back to it when there is no live Print.
- PostProcessor.cpp dispatches SlicingPipelinePluginCapability at psGCodePostProcess,
driven by the existing slicing_pipeline_plugin option.
- The exported G-code lives outside data_dir(), so the plugin audit sandbox would
block the write; the trampoline's audit setup grants ctx.gcode_path's folder as a
scoped allowed root, gated on a non-empty gcode_path so the geometry-step hooks gain
no extra filesystem access.
BREAKING CHANGE: the separate G-code post-processing capability type is removed.
- orca.gcode.GCodePluginCapabilityBase and orca.PluginType.PostProcessing are gone;
post-processing plugins migrate to orca.slicing.SlicingPipelineCapabilityBase +
Step.psGCodePostProcess (and gain ctx.params / ctx.config_value()).
- The post_process_plugin config option is removed; use slicing_pipeline_plugin.
Presets carrying the old key degrade to the standard unknown-key warning.
- Manifest type = "post-processing" now maps to Unknown (advisory only; the loader
dispatches on the C++ get_type()).
Also repairs two latent build breaks the branch carried: stale Step enum value usages
in test_slicing_pipeline_hook.cpp and a reference to the removed
ConfigOptionDef::PluginType::None in Tab::on_value_change (now is_plugin_backed()).
Adds the orca_gcode_stamp sample plugin and a psGCodePostProcess binding test.
Adds PluginHostSlicing, which registers the print-graph data model (Print,
PrintObject, Layer, LayerRegion, Surface, ExPolygon, extrusions, ...) into the
orca.host submodule in the same raw-class style as PluginHostApi's Model/Preset
graph, with shared helpers in PluginBindingUtils. SlicingPipelinePluginCapability
is trimmed to the capability surface (the standalone SlicingNumpy helper is folded
away). Adds the Twistify example plugin next to Inset and broadens the binding,
hook, and plugin-install tests.
Catches the iXex/IDEX branch up to upstream main (44 commits). One
content conflict resolved:
- src/libslic3r/Print.hpp: kept upstream's default-initialized
m_origin {0,0,0} alongside our m_imex_slice_offset member.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Catches the iXex/IDEX parallel-printing branch up to upstream main
(102 commits). Two content conflicts resolved:
- src/libslic3r/Preset.cpp: s_Preset_printer_options — kept upstream's
new "use_3mf" key and our iMEX printer-capability/mode keys.
- tests/fff_print/test_gcodewriter.cpp: upstream revived the disabled
suite (#14196), dropping the obsolete [.]-tagged lift() test and its
config_lift_unlift.ini; kept their set_speed + z_hop tests and appended
our 10 per-firmware set_pressure_advance/set_temperature scenarios.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Self-review found two weaknesses in the preceding test commits:
1) The equal-size [Variant] scenario claimed to distinguish the truncation
guard's `cur > target` predicate from a regression to `cur >= target`,
but both paths yield identical child values in practice: when
extruder_variant names match, set_with_restore's variant_index is fully
populated (no -1 slots) and the merge path restores every position from
backup — producing the same {1.5, 2.5} output as the skip path. The
test passes in both guard states.
Rewritten to use mismatched variant names between child and parent.
variant_index then has -1 slots, and set_with_restore overwrites those
positions with parent values. Now the merge path yields {0.8, 0.8} and
the skip path yields {1.5, 2.5} — observably different. Verified:
- `cur > target` (correct): 4 scenarios pass, 15 assertions
- `cur >= target` (regressed): equal-size scenario fails with
"1.5 is within 0.000000001 of 0.80000000000000004"
- Guard removed entirely: child>parent + stride=2 both fail with
truncation ("1 == 2" / "2 == 4")
2) The [3mf][IMEX] round-trip only covered a single plate. A plate-
indexing regression (IMEX metadata landing on the wrong plate, or
bleeding across plates on reload) would not have been caught.
Added a multi-plate scenario: two plates with distinct mode and
head-filament-map values. Asserts both land on their respective
destination plates after reload. Load-bearing verified:
- With IMEX serialization intact: 3 scenarios pass, 45 assertions
- With IMEX serialization disabled: positive + multi-plate fail
(both "nullptr != nullptr"); primary-mode passes (expects nullptr)
- With primary-mode short-circuit removed: primary-mode scenario
fails ("0x... == nullptr") because primary modes now serialize
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds three scenarios alongside the existing child>parent stride=1 regression
test for update_non_diff_values_to_base_config:
- stride=2 child>parent: machine_max_acceleration_x (size 4 vs 2) — confirms
the truncation guard fires for the (normal,silent)-pair stride=2 path, not
just stride=1. Catches a regression class the existing test would miss
because stride=2 routes through normalize_stride2_floats and a different
set_with_restore call site.
- equal-size (2=2): exercises the path the guard does NOT short-circuit;
asserts child per-extruder values survive set_with_restore's nil-restore
merge. Catches any future change that breaks the equal-size merge — the
fix's `cur > target ? skip` predicate could regress to `cur >= target` and
silently override child values otherwise.
- non-variant scalar: layer_height in `keys` and `different_keys` but absent
from printer_options_with_variant_1/_2. Hits the is_scalar() / "nothing to
do" branch and must remain untouched. Scopes the guard's blast radius.
All four scenarios in the [Variant] tag pass: 15 assertions, 4 test cases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a Catch2 scenario that builds a 2-extruder child DynamicPrintConfig
inheriting from a 1-extruder parent, calls update_non_diff_values_to_base_config
through the real printer_options_with_variant_1 / _2 key sets, and asserts
that printer_extruder_id, printer_extruder_variant, and retraction_length
retain their full size after the merge. Covers three distinct
set_with_restore<T> instantiations (Ints, Strings, Floats) and verifies
both size preservation and per-extruder value preservation.
Verified load-bearing: with the guard in update_non_diff_values_to_base_config
temporarily removed, the test fails with "1 == 2" on pe_id.values.size() and
retraction_length.values.size(); with the guard restored, all six assertions
pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Get libslic3r tests closer to passing
I can't get geometry tests to do anything useful. I've added extra
output, but it hasn't helped me figure out why they don't work
yet. That's also probably the last broken 3mf test doesn't work.
The config tests were mostly broken because of config name changes.
The placeholder_parser tests have some things that may-or-may-not
still apply to Orca.
* Vendor a 3.x version of Catch2
Everything is surely broken at this point.
* Allow building tests separately from Orca with build_linux.sh
* Remove unnecessary log message screwing up ctest
Same solution as Prusaslicer
* Make 2 TriangleMesh methods const
Since they can be.
* Move method comment to the header where it belongsc
* Add indirectly-included header directly
Transform3d IIRC
* libslic3r tests converted to Catch2 v3
Still has 3 failing tests, but builds and runs.
* Disable 2D convex hull test and comment what I've learned
Not sure the best way to solve this yet.
* Add diff compare method for DynamicConfig
Help the unit test report errors better.
* Perl no longer used, remove comment line
* Clang-format Config.?pp
So difficult to work with ATM
* Remove cpp17 unit tests
Who gives a shit
* Don't need explicit "example" test
We have lots of tests to serve as examples.
* Leave breadcrumb to enable sla_print tests
* Fix serialization of DynamicConfig
Add comments to test, because these code paths might not be even used
anymore.
* Update run_unit_tests to run all the tests
By the time I'm done with the PR all tests will either excluded by
default or passing, so just do all.
* Update how-to-test now that build_linux.sh builds tests separately
* Update cmake regenerate instructions
Read this online; hopefully works.
* Enable slic3rutils test with Catch2 v3
* Port libnest2d and fff_print to Catch2 v3
They build. Many failing.
* Add slightly more info to Objects not fit on bed exception
* Disable failing fff_print tests from running
They're mostly failing for "objects don't fit on bed" for an
infinite-sized bed. Given infinite bed is probably only used in tests,
it probably was incidentally broken long ago.
* Must checkout tests directory in GH Actions
So we get the test data
* Missed a failing fff_print test
* Disable (most/all) broken libnest2d tests
Trying all, not checking yet though
* Fix Polygon convex/concave detection tests
Document the implementation too. Reorganize the tests to be cleaner.
* Update the test script to run tests in parallel
* Get sla_print tests to build
Probably not passing
* Don't cause full project rebuild when updating test CMakeLists.txts
* Revert "Clang-format Config.?pp"
This reverts commit 771e4c0ad2.
---------
Co-authored-by: SoftFever <softfeverever@gmail.com>