* build: remove std::move that blocks copy elision
std::move wrapped around a temporary, or around a local being returned,
stops the compiler constructing it in place. Each edit is the fix clang
suggests, which is to delete the std::move call and keep its argument.
Three of the 39 sites save a move, the two return std::move(local) in
Print.cpp and TreeSupport.cpp:2749. The rest are equivalent either way
and match how the codebase already writes this elsewhere.
Clears 39 -Wpessimizing-move warnings.
* build: drop null checks on references and this
A reference cannot be bound to null and this cannot be null, so the
compiler folds these conditions to true and drops the guard. Seven are
if (&bitmap && bitmap.IsOk()), where IsOk() already does the work; two
test this directly. The guarded code runs either way, so removing the
dead operand changes nothing.
Clears 11 -Wundefined-bool-conversion warnings.
* 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.
Update perimeter traversal to pass each extrusion's closed/open state into `apply_fuzzy_skin`. This lets fuzzy skin logic distinguish contours from closed loops when processing perimeters.
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
* Fix contour cleanup across coplanar triangles
Avoid generic collinear simplification after slicing. Skip only junctions created by shared edges between coplanar faces so contours stay stable without altering shallow geometry.
Fixes#15364
* Fix contour cleanup across coplanar triangles (code review fixes)
---------
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
* Skip straight-run splits in corner smoothing
Teach `CornerSmoother` to treat vertices that only continue a straight segment as part of the same leg instead of rounding them as corners. The smoother now keeps a three-point window so it can emit a corner only once both adjoining legs are known, which avoids unnecessary corner processing while preserving real turns such as hairpins.
* Add regression test for split-leg smoothing
Adds a FillCornerSmoothing regression test covering polylines with an extra collinear vertex in a straight run. The test ensures corner smoothing treats split and unsplit geometry identically, preventing inconsistent rounding radii in triangular/grid infill paths.
# 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)
* chore: mark every declaration that overrides a base virtual
clang-cl reports 42 member functions across 28 files that override a
base virtual without being marked `override`, inside classes that
already mark their other overrides. That is every occurrence of
-Winconsistent-missing-override in the tree, so the category drops to
zero and -Werror=inconsistent-missing-override becomes available as a
guard against it coming back.
Behaviour is unchanged. Each keyword goes only where clang had already
resolved the declaration to a base virtual, so it records what the
compiler already worked out and cannot affect overload resolution or
dispatch. If any of these signatures had not really overridden a base
method, the build would have failed rather than warned.
Where a declaration already carried `virtual` it is left alone and the
keyword appended, matching the surrounding declarations. Plain
`override` is used rather than the wxWidgets `wxOVERRIDE` macro, which
wx/defs.h defines as `override` beneath a comment marking it obsolete,
and which the rest of src/slic3r already avoids by 1742 occurrences to
113.
A full clang-cl build takes -Winconsistent-missing-override from 1,146
warning lines to 0. Those 42 declarations produce that many lines
because a header is re-diagnosed in every translation unit that
includes it. CalibrationWizardStartPage.hpp alone accounts for 336 of
them from 4 declarations.
* chore: drop unused lambda captures in GUI/Widgets
clang-cl reports 10 lambda captures in src/slic3r/GUI/Widgets that are
never read. Removing them changes nothing at runtime.
Every capture removed is `this` or a raw pointer. clang does not report
a capture whose type has a non-trivial destructor, since such a capture
can be held purely for its effect on an object's lifetime, so nothing
that owns or extends a lifetime is touched. The std::weak_ptr captured
beside the removed `this` in MultiNozzleSync.cpp stays.
This clears the category in GUI/Widgets only. A full clang-cl build
takes -Wunused-lambda-capture from 312 warning lines to 302, leaving
235 sites in other directories for a follow-up.
Introduced a shared `colinear_vertex_tolerance()` helper in `ExtrusionLine.hpp` and updated both simplify paths (`ExtrusionLine.cpp` and `WallToolPaths.cpp`) to use it instead of duplicated hardcoded `0.005` scaled thresholds. This keeps the near-colinear early-out tied to `SCALED_EPSILON` (rounding-noise scale) and avoids unintended curve decimation from larger tolerances, while documenting the geometric impact in code.
* Add caching system for presets
* Removing user\bundle serialization and keeping it only for system presets
* Integrate caching into WebGuideDialog which speeds up time of SetupWizzard and PrinterSelection dialog
* Add CI\CD step to prepare cache file in ahead of time so user does not need to wait
* Add partial cache generation when only one of the vendros is changed to speed up recalculation time
* Handle corrupted files
* Add cache to GuideDialog as previos version didn't work as expected
* Add inspecting tool and fix CI cache generation
* Generate cache per vendor
* Simplify code by mergin it in PresetBundle
* Simplify code a bit more
* Add cereal serialize() to VendorProfile, PrinterModel, Preset, and Semver
* Remove CachedPrinterModel/VendorProfile/Preset mirror structs from VendorCache
* Fix use-after-free in CallAfter lambda; replace raw thread pointer with unique_ptr
* Use get_vendor_cache_key() to match cache keys written by the app
* Remove BOM added by VSC
* Skip invalid vendors
* Remove leftover cache file
* Fix build for windows arm64
* Revert json cache back
* Update check for stale cache
* Serealize all value fields for Preset class to minimize regression later
* Minimize field duplication by moving Cache thing into PresetBundle
* Add tests for Cache system
* Add a bit more tests
* Merge branch 'main' into feature/cache_profiles_and_optimize_loading_speed
* Rvert from per-verndor to single cache file
Replace N per-vendor .cache files with a single system_presets.cache
that holds all vendors and presets in one serialized blob.
Cache load is now all-or-nothing: on hit all vendors are applied from
the bundle (sub-second); on miss all vendors are parsed from JSON and
a fresh bundle is written to the user cache dir.
Invalidation is driven by bundle_key - a sorted concatenation of all
vendor JSON version strings. Any vendor update invalidates the whole
cache and triggers re-parse on next launch.
Guide wizard (WebGuideDialog) loads the bundled cache into a plain
PresetBundle instead of a separate VendorGuideData struct, removing
the duplicate data model.
generate_system_cache simplified from a per-vendor loop to a single
save_system_presets_cache() call producing one output file.
* Transfer all Preset fields from cache via move assignmet
apply_vendor_preset_group was copying fields manually and missed
bundle_id, user_id, base_id, sync_info, updated_time, key_values,
ini_str. Replace field-by-field copy with move assignment of the
fully-deserialized Preset, then restore the vendor pointer which
is excluded from serialization.
* Ignore cache for future
* Remove not used files
* Ship one preset cache per vendor in place of the profile JSONs
Each vendor's system presets serialize into a single <vendor>.opc built at
package time, and a shipped build carries that file alone — the profile JSON
and its sub-file tree are pruned. The vendor loader, the setup wizard's profile
list and the resource installer all read a vendor through its cache, falling
back to parsing whenever one is absent, stale or unreadable, so the cache stays
an optimization and never a source of truth. Caches hold presets in source form
and resolve inheritance at load, through the same code the JSON path uses.
* Make the preset cache self-describing and load each vendor from the system folder alone
The cached DynamicPrintConfig is keyed by name, through a per-file dictionary of the
distinct opt_keys, the type each was written as, and the distinct enum value names,
instead of by serialization_key_ordinal — a position assigned by declaration order at
static init, where inserting one option shifts every later ordinal and the lookup then
succeeds on the wrong option. Because a name-keyed payload drops the options this build
cannot place rather than being rejected wholesale, the schema fingerprint goes, and with
it the two fallbacks that existed only because an installed cache died on every app
upgrade: the second lookup tier into resources/profiles and the parse fallback to the
same place. A vendor is loaded from <data_dir>/system/ and nowhere else, as on main —
which is what makes the app write its .opc files there again.
* Simplify the preset cache internals after review
* Use the shared temp-dir helper in the preset bundle loading test
* Bound stamp string reads in the preset cache
* Speed up the setup wizard with a profile-data cache
The wizard's per-vendor fast path threw on vendors present only in
resources, falling back to a ~29 s raw JSON scan on every open. Each
vendor now loads from the directory it was found in, and the derived
model/machine/filament/process catalog is cached whole in
<data_dir>/cache/wizard_profile_data.json, stamped by each vendor's
name and version - a fresh cache makes an open one file read, with no
bundle built and no presets installed (~0.2 s vs ~2 s).
* Remove debug SVG dump from a geometry test
* Move the per-vendor cache file format into PresetCacheFormat
* Move the vendor install helpers from PresetBundle into Utils
* rename
* fix flatpak
* change cache version to 1
---------
Co-authored-by: SoftFever <softfeverever@gmail.com>
* Normalize the junction direction vector over XYZE
calc_vmax_junction_deviation() treats the dot product of two jd_unit_vec as a
cosine, but the vectors were scaled by 1 / block.distance, which is the XYZ
length. On an extruding move the E component then pushes the 4D norm above 1 and
the dot product below -1, so the corner reads as straighter than it is and is
planned too fast -- the more so the higher the flow. Measured on a 6 degree
corner at scv 5: 86.9mm/s with no extrusion, 94.4mm/s at 0.029mm/mm, 150.0mm/s
at 0.1mm/mm.
Neither firmware does that. Marlin normalizes over XYZE for any extruding move
(planner.cpp: `if (... || esteps > 0) normalize_junction_vector(unit_vec)`) and
Klipper leaves E out of the cosine entirely, dotting only axes_r[0..2]
(toolhead.py::Move.calc_junction). Normalizing satisfies both: with E normalized
in, the cosine differs from the XYZ-only one by ~1e-5 at printing flow rates.
This is a deliberate divergence from PrusaSlicer, which still scales by
1 / distance -- it carries an older Marlin's behaviour.
Travel moves are unaffected, their vector was already unit length.
Reported by Copilot in review of #15304.
* Test that extrusion rate does not change corner planning
The junction deviation tests were all travel-only, which is exactly why the E
component of the junction vector went unchecked. Cover it: the same corner has
to be planned the same whether nothing, an ordinary 0.42 x 0.2 line, or a fat
large-nozzle line is extruded through it, on both Klipper and Marlin 2.
Reported by Copilot in review of #15304.
* Plan corners with junction deviation where the firmware uses it
The time estimator only ever had the classic per-axis jerk model, which limits a
corner by the largest single-axis component of the velocity change. That is
anisotropic: the same corner is allowed sqrt(2) more speed on a diagonal than on
an axis, which paints a four-lobed ripple around every circular wall in the
actual speed and actual flow views, worst on small parts whose walls are made of
short segments.
Klipper has no classic jerk at all and Marlin 2 has none while M205 J is in use;
both plan corners with junction deviation, which sees only the corner angle. Add
that model and use it for those machines:
- Klipper: derived from the square corner velocity, as the firmware does
(jd = scv^2 * (sqrt(2) - 1) / max_accel), reading the scv from
machine_max_jerk_x, where process_SET_VELOCITY_LIMIT() already stores
SQUARE_CORNER_VELOCITY.
- Marlin 2: machine_max_junction_deviation, which was already loaded into the
machine limits but never reached the planner.
- Every other flavor keeps the classic jerk path unchanged.
The model has no per-axis jerk floor, so this also drops the hard slow spot the
estimator drew at the start of every loop from machine_max_jerk_e.
Toolpaths are unaffected: on a full export the only lines that change are M73.
The junction deviation maths, including Marlin's JD_HANDLE_SMALL_SEGMENTS arc
approximation, is ported from PrusaSlicer's src/libslic3r/GCode/GCodeProcessor.cpp.
The Klipper mapping is not in PrusaSlicer, which ignores SET_VELOCITY_LIMIT.
* Add tests for junction deviation corner planning
Cover the three properties the change rests on:
- a right angle on Klipper is planned at exactly the square corner velocity,
the identity that makes the scv to junction deviation mapping correct, and a
shallow corner is planned far faster than per-axis jerk allows;
- junction deviation gives the same speed whatever the corner's orientation,
while classic jerk keeps its sqrt(2) spread, which is the four-lobed ripple;
- machines that do not plan with junction deviation are provably untouched,
including a Marlin 2 printer that has it disabled.
# Description
Printers discovered/bound under one printer agent (e.g. built-in BBL)
were leaking into another, independent agent's "My Device"/"Other
Device" lists and inheriting its saved access code, since neither the
device list nor bind state was ever scoped by which agent found them.
- Add printer_agent_id to MachineObject/BBLocalMachine, stamped at
discovery/bind time; filter get_my_machine_list(),
get_my_cloud_machine_list(), and update_other_devices() by it.
- clear_other_devices() now drops entries stamped by the outgoing
agent on swap, so the incoming agent's own discovery re-inserts and
re-stamps them fresh instead of leaving them stale-tagged forever.
- Scope access_code by (dev_id, printer_agent_id) on BBLocalMachine
(LAN only since cloud's userMachineList is always refreshed live from
the account API, so it isn't at risk the same way), with a
BBL-only legacy fallback to the old flat access_code/user_access_code
keys so existing bindings keep working.
# 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)