* ci: run unit tests on Windows and macOS
The Unit Tests CI job only ran on Linux, so platform-specific bugs
invisible to a Linux build could land undetected (e.g. the MSVC-only
NfpPlacer crash fixed in #14267). The full non-[NotWorking] suite already
builds and passes on every shipped arch, so this wires them into CI.
A reusable unit_tests.yml, called once per built arch, downloads that
arch's test artifact and runs ctest. Each build leg builds the test
executables and uploads them; a single publish_test_results job on Linux
aggregates the JUnit results into one check.
Coverage: Linux x86_64 + aarch64, Windows x64 + arm64, macOS arm64.
macOS x86_64 is deferred (cross-built on arm64, needs Rosetta).
- build_release_vs.bat: "tests" token enables BUILD_TESTS
- build_release_macos.sh: -T builds and runs tests; ORCA_TESTS_BUILD_ONLY
builds them without running (used by CI)
- scripts/run_unit_tests.sh: parameterized test dir and build config
Addresses #11273.
* ci: bump actions/checkout to v7 in reusable unit_tests workflow
Match the actions/checkout v6->v7 bump (#14517) that upstream applied to
the inline test job this reusable workflow replaces.
* fix: isolate calibration temp paths per user
The calibration temp files under <temp>/calib were file-scope statics
initialized before set_temporary_dir() runs at startup, so they kept
using the shared system temp root and missed the per-user isolation
added in #14607. On Linux every account shares /tmp, so the first user
to calibrate owns /tmp/calib and later users fail to write there, the
same cross-user collision #14607 fixed for model backups, STEP import,
and part skip.
Build the paths lazily from temporary_dir() instead, through a
calib_temp_dir() accessor and a calib_temp_file() join helper. The base
becomes <temp>/orcaslicer_<uid>/calib on Linux and is unchanged on
Windows, where the temp dir is already per user.
Also make StoreParams::path a std::string rather than a non-owning
const char*. The calibration code had to keep a std::string alive
solely to feed that pointer, and the field was uninitialized by
default; owning the string removes the lifetime hazard for all three
callers and makes the entry guard a reliable empty() check. Confined to
the 3mf project exporter (three callers, two internal reads); no
on-disk, format, or ABI impact.
Follows up on #14607 per @Noisyfox's review suggestion.
* dedupe-issues.yml remove unsupported claude_args option
claude_args: is causing an error. Only calling for "--model" anyway, so replaced with model: option.
* Merge branch 'main' into MisterAnderson91-dedupe-issues-yml-update
* fix: prevent out-of-bounds crash in Arachne beading interpolation
SkeletalTrapezoidation::interpolate() derives an inset index from `left` but
uses it to index the merged beading, which follows the thicker of left/right.
When the thicker side has fewer insets, the index runs past the end and the
slicer crashes during "Generating walls".
Skip the adjustment when the index is out of range, as the adjacent guards
already do. interpolate() uses no instance state, so make it static and add a
regression test that exercises it directly.
Fixes#14584
* Support Painting: add Vertical/Horizontal axis-lock checkboxes
Adds the Vertical and Horizontal axis-lock checkboxes to the Support
Painting gizmo, matching the UI in the MMU Segmentation and Seam
Painter gizmos. The underlying constraint logic has lived in
GLGizmoPainterBase since #2424 and already applies to any
ToolType::BRUSH action — the Support gizmo was the only painter
without the UI to enable it.
The Circle and Sphere brush arms are consolidated into a single
"if (Circle || Sphere)" block matching the structure of
GLGizmoMmuSegmentation::on_render_input_window, eliminating
duplicate cursor-radius and axis-lock UI code.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Support Painting: keep Circle/Sphere as separate tool arms per review
Reviewer requested keeping a separate condition per tool for future
extensibility rather than merging Circle and Sphere into one branch.
This restores the upstream Circle/Sphere arm structure and adds the
Vertical/Horizontal axis-lock options to each arm, making the change
purely additive over upstream.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: yw4z <ywsyildiz@gmail.com>
feat: add regex_replace() string transform to filename templates
The filename template language could test strings (=~, !~, one_of) but
never rewrite one, so there was no supported way to reshape a placeholder
value, such as dropping a file extension from {first_object_name}.
Add regex_replace(subject, /pattern/, replacement), reusing the existing
regex-literal syntax and boost::regex engine. Every placeholder keeps
returning its exact value and the template does the transform explicitly:
{regex_replace(first_object_name, /\.[^.]*$/, "")} strip any extension
The replacement may reference capture groups ($1, $2, ...). It is one
grammar function mirroring digits(), with the name registered as a keyword
so it is not parsed as a variable.
Port from BambuStudio commit c8f70c6ca. Shows a warning when AMS
is actively drying during print job preparation, alerting users that
the drying temperature will be lowered during printing.
Three-page wizard: main status/control page, guide page with
filament tray status, and progress page. Supports N3F and N3S AMS types.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: initialize Print::m_isBBLPrinter
Built outside the GUI/CLI (headless tests, embedded use) the member was read
uninitialized: is_BBL_printer()/wipe_tower_type() feed it into ToolOrdering,
which then non-deterministically dropped per-feature filament assignments.
Default it to false, the value the GUI and CLI already assign for non-Bambu
printers.
* docs(test): add the fff_print testing contract
tests/fff_print/README.md codifies how the suite is organized: one file per
subsystem (each owning both in-memory and emitted-G-code assertions), flat
behavioral test names with a single [Subsystem] tag, a robust-tests guide,
the shared helpers, and an add-a-test checklist. Linked from tests/CLAUDE.md.
* test(fff_print): reorganize the suite to the contract and add coverage
Bring every subsystem into one file per the README: rename the test_data
harness to test_helpers; consolidate skirt/brim; split multi-filament and
cooling into their own files; disperse the test_printgcode grab-bag and the
end-to-end smoke scenario into focused tests; fold test_gcode into
test_gcodewriter. Standardize names and tags, align cube tests on the cube()
helper, and de-qualify the flagship files.
New coverage: multi-filament per-feature and per-object routing; a skirt/brim
behavior matrix (the #14333 rework, including brim ears, with regression
coverage for #14319 and #14366); resolved extrusion-width and config
comments; custom-G-code placeholders; fan control and speed-marker
consumption.
Re-enable three slice tests previously tagged [NotWorking]: the clipper
"Coordinate outside allowed range" error that disabled them was specific to a
past CI runner environment and no longer reproduces.
* test(fff_print): tag arm64-flaky skirt/brim tests NotWorking
Four skirt/brim slice tests intermittently throw ClipperLib's "Coordinate
outside allowed range" on the macOS and Windows arm64 CI toolchains (an FP
divergence, not a slicing bug; see PR #14207). Linux x86_64 and aarch64 are
unaffected. Tag them [NotWorking] so ctest -LE NotWorking skips them.
* test(fff_print): re-enable the arm64 skirt/brim tests
These were tagged [NotWorking] as a stopgap when myfork's daily-driver build
combined them with the cross-platform CI on a base that predated upstream's
m_origin fix (99dea01cc3). With upstream merged in, Print::m_origin is
initialized and the "Coordinate outside allowed range" throw is gone, so the
tests pass on macOS/Windows arm64. Drop the tags.
fix(gui): avoid null-pointer UB in create_scaled_bitmap with win == nullptr
create_scaled_bitmap() documents that win may be nullptr, but called
win->FromDIP() on it. Calling a member function through a null pointer
is undefined behavior: clang assumes `this` is non-null and deletes the
subsequent `win ?` null check added in #13117, turning the fallback
branch into an unconditional virtual call through a null vtable.
This crashed LLVM/clang-cl builds at startup (access violation reading
0x0 in BBLTopbar creation); MSVC builds were unaffected by luck.
Use the static, null-safe wxWindow::FromDIP(x, win) overload instead,
which falls back to the primary display DPI. Behavior is unchanged for
non-null windows.