Commit Graph
105 Commits
Author SHA1 Message Date
SoftFever 0aeb6df122 Merge branch 'main' into cad-mainline 2026-08-27 17:06:37 +08:00
Clifford GarwoodandClaude Opus 5 ba07716ddb Merge upstream main: color mixing feature and related fixes
Brings in 54 upstream commits, the bulk of them the BambuStudio-ported color
mixing / mixed filament subsystem (#15347) plus its follow-ups, along with the
Assimp-backed colored OBJ import, warning-policy build changes, and assorted
profile and localization updates.

Two conflicts, both "each side added at the same point", resolved by keeping
both:

- Print::validate() -- our IMEX multi-color block and upstream's new gradient
  mixed filament warning were inserted at the same spot after the empty
  extruders check. They test unrelated conditions, so both are kept, each with
  its own closing brace.
- tests/libslic3r/test_3mf.cpp -- our three IMEX per-plate round-trip scenarios
  and upstream's mixed-filament round-trip scenario both append to the end of
  the file, and each side added one include. All four scenarios and both
  includes are kept.

Everything else merged cleanly, including GCode.cpp, ToolOrdering.cpp,
PartPlate.cpp and PrintConfig.cpp. Upstream left the is_extruder_used block
untouched, so the IMEX supplement still applies, and estimate_wipe_tower_polygon
is unchanged, so the prime tower hull work is unaffected.

Not addressed here, and worth its own change: a mixed filament is a virtual slot
that no nozzle carries, while physical_extruder_map routes logical slots to
physical heads. Print::extruders() lists mixed slots under their own id whereas
tool_ordering.all_extruders() lists them post-expansion, so the IMEX pem lookups
have no defined answer for a mixed slot. Upstream's own guards reject a mixed
filament where a physical slot is required; IMEX likely wants the same.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 13:07:26 -04:00
harrierpigeon d289478618 Merge remote-tracking branch 'upstream/main' into haryr/aug25-rebase
# Conflicts:
#	resources/profiles/Custom.json
#	src/libslic3r/Brim.cpp
#	src/libslic3r/GCode.cpp
#	src/libslic3r/GCode.hpp
#	src/libslic3r/Preset.cpp
#	src/slic3r/GUI/3DScene.cpp
#	src/slic3r/GUI/ConfigManipulation.cpp
#	src/slic3r/GUI/GLCanvas3D.cpp
#	src/slic3r/GUI/Plater.cpp
2026-08-25 06:50:46 -05:00
Ian Bassi 42f708bbb6 Fixes from Full spectrum port
https://github.com/OrcaSlicer/OrcaSlicer/pull/14383
2026-08-23 22:11:48 +08:00
Ian Bassi 8fea099d99 BBL Port Color Mix Base 2026-08-23 22:11:48 +08:00
Clifford GarwoodandClaude Opus 5 90d1481463 Merge upstream main into the IMEX work
Upstream replaced MainFrame's fixed-index TabPosition enum with string-based
page ids ("feat: refactor notebook/tabs to be string based instead of fixed
index based"). The IMEX toolhead-visibility menu item was the only consumer of
that enum left on this branch, so its enable check now compares
m_tabpanel->GetSelectedPageName() against TAB_ID_PREVIEW -- the same form the
neighbouring upstream menu items use.

That mismatch is what broke CI: the branch built on its own, but the merge
commit CI builds no longer had TabPosition declared. No other conflicts.

666/666 tests pass in Release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 17:34:10 -04:00
Tommaso BianchiandClaude Opus 5 5d7fc8c545 Port the sketch layer work from snaporca: offset chains, right-click, MCP verbs
Carries snaporca 971320e129, 6b049f0dc6, 4aae782029, 444d59f212, 74cf3d7e54 and the build
guards from 597557a6e4. Parity re-verified after every hunk: 17 files identical, 8 diverging by
their expected counts — DesignPanel.cpp still 32, DesignCanvas.cpp still 16, which is the proof
each hunk landed on the right side rather than being copied over a real divergence.

OFFSET OFFSETS THE CHAIN. Per-entity offsetting returned a closed rectangle as four parallel
segments that no longer touch, so entities_to_wires gave four OPEN wires and nothing could be
extruded. offset_entities now chains by shared endpoints and repairs each seam by mitering the
neighbours to their intersection. Second bug, invisible to any single-entity test: +d meant
"left of travel" for a line but "radius + d" for an arc regardless of sweep, so a slot outline
offset with its straights going one way and its caps the other. The convention is now written on
the declaration and pinned by a test.

tests/libslic3r/test_sketchprofile.cpp is new and asserts the LOOP rather than coordinates —
the property that decides whether a profile can be built, and the one the existing single-entity
[SketchEdit] cases cannot see. Its include is catch2/catch_all.hpp here: this fork ships Catch2
v3 while snaporca is on v2, which is why the test files are a tolerated divergence.

RIGHT-CLICK PICKS WHAT YOU POINTED AT, so a line's own verbs are offered instead of the
empty-selection vocabulary; sk_delete stops sharing btn:delete with the feature tree; and an
element's defining number (length / radius / diameter / angle / distance) can be typed, from the
menu or from V.

TWELVE MCP SKETCH VERBS. The socket had ~40 verbs and none touched a sketch, so the 2D layer
could only be exercised by driving a GUI with synthetic clicks. sketch_describe reports each
closed loop, the loops it encloses as voids, exact areas, and where a chain is still open;
sketch_validate/sketch_heal are FreeCAD's ValidateSketch — find vertices that overlap within a
tolerance but carry no coincidence, then weld them AND record the constraint, so a loop closed
by floating-point luck becomes one closed by construction. scripts/mcp-sketch-smoke.py is the
loop that asserts all of it.

Kernel suite on this fork: all tests passed, 2677 assertions in 230 test cases. The GUI target
links against the rebuilt deps image (the wxInspector blockage is gone) and the binary carries
the new verbs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 09:00:26 +02:00
ExPikaPakaandSoftFever 5ed56eb876 Cache system presets to eliminate startup and wizard load times (#14217)
* 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>
2026-08-21 16:56:52 +08:00
SoftFever 6a0524ea85 Merge branch 'main' into pr/tommasobbianchi/15238 2026-08-19 19:15:38 +08:00
ExPikaPaka faa0d9a44a Merge branch 'main' into feature/texture_displacement 2026-08-19 09:13:53 +02:00
Ian Bassi 322dc9b6a6 Smooth more patterns (#15205) 2026-08-18 12:19:27 -03:00
SoftFever 030e5f469e Merge branch 'main' into cad-mainline 2026-08-13 15:22:08 +08:00
Tommaso BianchiandClaude Opus 5 b305e8b154 tests: compile the five CAD test files that were never wired
tests/libslic3r/CMakeLists.txt added only test_caddocument.cpp under
SLIC3R_CAD. The other five shipped in the tree and were never compiled, so
49 TEST_CASE blocks looked like coverage and were not: sketch constraints,
sketch editing, sketch import, inference, and the libslvs constraint set.

They also still targeted Catch2 v2 — mainline is on v3, where the umbrella
header is catch2/catch_all.hpp and Approx lives in the Catch namespace rather
than at global scope. Both fixed; nothing else in the files changed.

Found by building the tree rather than reading it. Suite goes from 374 to 423
test cases, 54,424 to 54,620 assertions, all passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 18:05:02 +02:00
harrierpigeon 55b4dca9bc Belt printers: brim laid onto the tilted belt, with a leading apron
A belt printer slices in a rotated frame, so the belt surface is a tilted
plane rather than the Z=0 bed plane.  Each slicing layer touches the belt
only along a narrow strip at its leading edge - about 0.2mm at 45 degrees -
so a part's first layer is really a first line, with almost no contact patch
to hold it down while the belt drags it forward.  Brim was hard-disabled on
belt printers, leaving no remedy at all.

Generate the brim on the belt plane instead.  The object's belt footprint is
the union over layers of each slice clipped to that layer's contact band; the
brim is offset from it in a "flattened" frame where the shear axis is
stretched by 1/cos(tilt), so ordinary Clipper offsets measure true on-belt
distance.  It is emitted as cross-belt lines, one per layer band, anchored to
a fixed fraction of the band so every line shares a nozzle-to-belt clearance
and therefore comes out the same width; flow is matched to the resulting band
pitch, keeping the sheet uniform and gap-free.

Three new controls, all belt-only:

  * Leading brim length - extends the brim ahead of the part along the belt,
    on every downhill-facing edge of its contact area.  This apron necessarily
    prints BELOW the object's first layer, since layer 0 is the part's leading
    contact, so it needs brim-only bands of its own.
  * Extra brim width - widens the brim sideways across the belt only.
  * Brim type "Leading edge only" - brim at the part's first belt contact and
    nothing after it.  Appended last in BrimType so no existing value shifts;
    degrades to an outer brim off belt printers, with a warning.

The apron bands are lightweight records rather than a Layer subclass, so no
fabricated Layer::id() can leak into initial-layer temperature selection, the
spiral vase probe, cooling or gradual interpolation.  They are generated in
posSupportMaterial because their print_z values must exist before ToolOrdering
is built at psWipeTower, and they are emitted from a short dedicated branch in
process_layer that runs before any layer pointer is dereferenced.

The footprint is closed before offsetting outwards: a belt contact patch is
often a broken-up strip, and the merged offset rings of two islands closer
than 2 x brim_width would otherwise fill the space between them - space that
lies under the part.

Also fixes a pre-existing bug where PrintObject::get_first_layer_bbox()
overwrote a valid bbox with an unassigned one on any belt printer with a brim
configured, because has_brim() was true while make_brim() returned early.

Belt brim is refused alongside the prime tower and spiral vase, and requires
one instance per PrintObject - translating an instance along the belt axis
changes its physical belt-floor Z.  Untilted belt printers are unchanged: they
still get no brim, since the plate brim is emitted out of skirt_brim_groups(),
which _make_skirt() never builds for a belt printer.
2026-08-06 01:08:44 -05:00
Clifford Garwood 7541d6a1e6 Merge upstream main: printer-specific OrcaFilamentLibrary profiles, convex_hull_2d test replacement
# Conflicts:
#	tests/libslic3r/test_3mf.cpp
2026-08-03 15:17:00 -04:00
Clifford Garwood 612af109f5 Merge upstream main: outer-only brim ears, Hilbert infill smooth factor, ImGui mouse capture and gizmo fixes, Wayland splash and Linux control styling, 32-bit and warning cleanups 2026-08-03 10:58:46 -04:00
Kris Austin 06ef58bad8 test: replace the disabled convex_hull_2d test (#14892)
test(libslic3r): replace the disabled convex_hull_2d test, closing #11269

The last "failing libslic3r test" from #11269 was the disabled
SCENARIO("2D convex hull of sinking object", "[3mf][.]") in test_3mf.cpp.
It checked ModelObject::convex_hull_2d for a sinking object against
PrusaSlicer's reference hull, but Orca's convex_hull_2d does not clip
geometry below the bed the way PrusaSlicer's its_convex_hull_2d_above does,
so the reference never matched. The test also wrote a debug mesh to a
hardcoded /tmp path and its comparison loop was inverted.

Remove it and add tests/libslic3r/test_model.cpp characterizing
convex_hull_2d on non-sinking transforms (identity and scale+offset),
where the projected footprint is unambiguous. Homed in a Model test file
since it exercises ModelObject, not 3MF.
2026-08-03 22:29:00 +08:00
Valerii Bokhan fb36d5e73b Feature: Smooth Factor for the Hilbert Curve sparse infill (#14969) 2026-08-01 17:58:04 -03:00
Clifford Garwood bbcd2e2a80 Merge upstream main: cyclic print ordering, brim overlap fix, perimeter and support fixes 2026-07-31 01:42:48 -04:00
Maksym PyrozhokandIan Bassi ef7bfeda9c Cyclic ordering (#13578)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-07-27 19:52:29 -03:00
Rodrigo Faselli fccd9d52ce Merge branch 'main' into main 2026-07-25 19:19:07 -03:00
Tommaso BianchiandClaude Opus 5 8c6df84acc Merge upstream/main into cad-mainline (530 commits)
Catches the fork up from 449a4cf9fc (2026-06-28) to d6cb667b89 (2026-07-24).
Upstream touched 2326 files; 17 of them overlap the 164 this branch touches.

16 of the 17 auto-merged, including all three CMakeLists.txt, the build_all.yml
CI workflow, and every GUI file. The CAD core never conflicts: CadDocument,
SketchEngine, SketchSolver, McpControl and test_caddocument are files this fork
adds, so upstream does not touch them.

The one conflict, tests/libslic3r/test_3mf.cpp, was purely additive in all three
hunks and is resolved as a union: our test pinning that store_bbs_3mf embeds the
CAD recipe as Metadata/SnapOrca_cad.bin, upstream's multi-nozzle plate-metadata
round-trip tests, and both sets of includes. All three were verified present
after resolution rather than assumed.

NOT BUILD-VERIFIED, for a reason that predates this merge and is not caused by
it: this fork cannot be configured on nativedev at all. Its CMakeLists has
required Eigen3 5.0.1 since before the merge (line 592 pre-merge), while the
only deps image on the machine is snaporca-deps, built for snaporca's
find_package(Eigen3 3.3). CMake fails at configure, so nothing compiles.

That means this fork's Catch2 suite has never run. Every "suite green" figure
recorded for M1-M8 was snaporca's suite; the ports were verified by patch-apply
plus the CAD sources being byte-identical to snaporca's. Building an orca_cad
deps image with Eigen 5.0.1 is what would finally close that gap.

Pre-merge state is preserved at branch cad-mainline-pre-upstream-2026-07-25
(30d54f0074).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 12:28:33 +02:00
Kris Austin b8cfa32a41 fix: multi-material slicing crash with line width 0 (#14455) 2026-07-22 16:49:37 -03:00
SoftFever 5cae3337a7 Merge branch 'main' into feature/texture_displacement 2026-07-21 19:50:35 +08:00
Clifford Garwood 58b4a68a10 Merge upstream main: Python plugins, Bambu device rework, macOS fixes
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.
2026-07-19 18:33:58 -04:00
Ian Bassi 9f1722ed3b Merge branch 'main' into feature/texture_displacement 2026-07-17 09:07:31 -03:00
SoftFever 8cb0cb7693 Merge branch 'main' into feat/plugin-feature
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).
2026-07-15 17:18:46 +08:00
Clifford Garwood fdb0e20f36 Merge upstream main (Bambu H2C/A2L multi-nozzle support) into IMEX branch
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.
2026-07-13 16:22:22 -04:00
Clifford Garwood 0ba09780d1 Merge upstream main into IMEX parallel printing branch
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.
2026-07-13 13:17:45 -04:00
SoftFever 13cd8d4864 feat(config): keep per-(extruder x volume-type) slots in variant expansion
- get_extruder_nozzle_volume_count derives per-extruder volume-type slot
  lists from extruder_nozzle_stats (absent stats = one slot per extruder)
- update_values_to_printer_extruders learns the slot layout: when any
  extruder mixes volume types, option arrays keep one slot per
  (extruder x volume type), extruder-ascending then volume-ascending;
  single-slot resolution takes the filament's volume type on mixed
  extruders
- update_values_to_printer_extruders_for_multiple_filaments applies a
  per-filament nozzle_volume_type override from filament_volume_map
  (when sized to the filament count) and remaps filament_self_index
  through the same pipeline as every other filament key
- get_config_index_base + is_auto_filament_map_mode helpers (consumers
  land with the per-filament config-index resolvers)
- callers updated: PresetBundle composition paths, PrintApply (counts
  hoisted above the extruder_applied guard), Print write-back
- new tests: slot counting, Hybrid slot expansion incl. stride 2,
  per-filament override, non-Hybrid degeneracy

Non-Hybrid printers keep their variant layout and values (proven by a
19-fixture byte gate; the only header delta is filament_self_index now
flowing through the same variant pipeline as its sibling filament
keys). Hybrid slices grow the config-block variant arrays to one entry
per sub-nozzle volume type; motion g-code is unchanged until the
g-code writer consumes the new slots.
2026-07-11 00:51:10 +08:00
Tommaso BianchiandClaude Opus 4.8 c618965a4c Add -DSLIC3R_CAD compile-time gate for the Design/CAD tab
Gate the entire parametric Design/CAD subsystem behind a single CMake
option so the fork can be built with or without it. With SLIC3R_CAD OFF
the build is behaviour-neutral against upstream OrcaSlicer; this is the
"parallel build" for upstream integration discussion.

Gated surface:
- option(SLIC3R_CAD) + add_definitions(-DSLIC3R_CAD)
- deps/OCCT/OCCT.cmake: BUILD_MODULE_ModelingAlgorithms=${SLIC3R_CAD}
  (OFF matches upstream OCCT exactly; ON adds only TKFillet + TKOffset)
- TKFillet/TKOffset link, add_subdirectory(slvs) + libslvs
- CAD kernel + GUI sources, GLGizmoPrimitive (needs GeometryEngine),
  CAD Catch2 tests
- 11 upstream C++ hook sites (GLCanvas3D, MainFrame, GLGizmosManager)
- TabPosition and gizmo EType enums switched to implicit numbering so
  OFF reproduces upstream indices exactly

Verified on behemoth both ways: OFF and ON link snapmaker-orca +
libslic3r_tests (exit 0); ON shows the Design tab and passes 8 [design]
+ 1 [Deviation] tests, OFF omits them and shows upstream's tab layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-07-10 18:12:53 +02:00
SoftFever b2eeed2622 feat(slicing): enforce filament flow-type restrictions in auto grouping
Filament grouping already consumed per-filament forbidden nozzle volume
types, but every call site passed an empty map, so a variant-restricted
filament (e.g. one limited to "Direct Drive TPU High Flow") could be
auto-grouped onto an incompatible nozzle flow type on multi-variant
printers.

- add convert_to_nvt_type() to parse extruder variant strings
- add Print::get_filament_unprintable_flow(): forbidden volume types =
  printer extruder variants minus the filament's declared variants;
  filaments declaring no variants stay unrestricted
- feed the map into grouping at the by-object path (Print.cpp) and all
  six mapping/planning sites in reorder_extruders_for_minimum_flush_volume
- unit-test the string parser

Non-restricted configurations produce an empty map, so existing
printers' grouping and g-code are unchanged.
2026-07-10 15:10:46 +08:00
SoftFever 9810397546 test+i18n: multi-nozzle filament-group goldens and ported strings
Filament-group golden harness (config_a subset) and .3mf multi-nozzle round-trip tests, plus i18n msgids for the ported H2C/A2L strings.
2026-07-09 01:16:26 +08:00
ExPikaPaka 7f2598d0d6 POC 2026-07-08 08:50:47 +02:00
raistlin7447 2860353b9f fix: multi-user slicing crash on shared temp dir (#14607)
On Linux every account shares /tmp, but slicing builds temp paths there under
fixed, app-owned names via temporary_dir() (model backups, STEP import,
part-skip). The first user to slice creates and owns those dirs, so the next
user cannot write under them and slicing crashes with "No such file or
directory".

Tag the app temp root with the user id at startup (<temp>/orcaslicer_<uid>)
so every temporary_dir() consumer is isolated at once. The id stays at the
top level of the world-writable system temp so each user's dir is created
directly there; a shared parent dir would be owned by whichever user made it
first. The root is pre-created because STEP import writes into it directly.
Windows keeps the plain temp dir since it is already per-user.

Fixes #10108. Same root cause as #5969.
2026-07-06 09:18:04 +08:00
Ian Chua ecddf3d18f feat: Python Plugins 2026-07-02 17:49:36 +08:00
Clifford Garwood 17584e2ffb Merge remote-tracking branch 'upstream/main' 2026-06-30 01:55:14 -04:00
raistlin7447 f13f67959c fix: PA pattern calibration crash with first layer line width 0 (#14447)
CalibPressureAdvancePattern::line_width_first_layer() returned the raw
initial_layer_line_width, so a value of 0 (which means "use the default")
fed 0 into the Flow spacing math and threw FlowErrorNegativeSpacing,
crashing the whole app when slicing a PA pattern calibration.

Mirror the guard already present in the sibling line_width(): when the
configured width is non-positive, fall back to auto_extrusion_width.

Add a libslic3r regression test covering the width resolution.

Fixes #13188
2026-06-29 09:22:23 +08:00
Clifford GarwoodandClaude Opus 4.8 4677c79e18 Merge upstream/main into iXex PR branch (#13086)
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>
2026-06-28 12:02:29 -04:00
Tommaso BianchiandClaude Opus 4.8 2c0140afb9 Mirror CAD persistence (K1+K2+G1) from snaporca-cad onto mainline OrcaSlicer
Dual-fork mandate: port the parametric-recipe 3MF persistence from
snaporca-cad commits ed19eac+147e1c4 so a saved project reopens with the
editable CAD feature tree, not just the baked mesh.

Shared kernel/format/GUI (identical to snaporca-cad):
- CadDocument serialize_recipe/deserialize_recipe (cereal BinaryArchive,
  versioned) + CadFeature split save/load + imported_solid<->BRep string.
- Model::cad_recipe carried through 3MF zip entry Metadata/SnapOrca_cad.bin
  (writer + binary-verbatim reader branch).
- DesignPanel on_commit() stamps the recipe; on_tab_shown() rehydrates a
  loaded project via load_recipe() (deserialize -> feed_bodies + refresh_tree).

Mainline-only adapters (no snaporca-cad counterpart — Catch2 v3 vs v2):
- tests/libslic3r/test_caddocument.cpp: <catch2/catch_all.hpp> +
  `using Catch::Approx;` (v3 scopes Approx under Catch::).
- tests/libslic3r/CMakeLists.txt: register test_caddocument.cpp (the
  original CAD port had left it out of the test build).

Verified on behemoth (snaporca-deps toolchain): libslic3r_tests clean;
[CadDocument] 17/18 (only the pre-existing tangent-to-circle SIGABRT fails,
identical to snaporca-tkz); K1 serialize round-trip + version-reject pass
(13 assertions); new [3mf] "CAD recipe blob survives a 3mf save/load cycle"
passes byte-for-byte; orca-slicer GUI links clean (186/186, DesignPanel.cpp
compiled). Interactive :10 click-through pending (no Design-tab automation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 17:05:44 +02:00
SoftFever 8cb2e4e01e profiles: deterministic setting_id from vendor/type/name (#14432)
* profiles: enforce globally-unique, per-vendor-namespaced setting_id

Many non-Bambu vendors copied Bambu's generic setting_ids (GFSA04 alone
appeared in 1557 files), so setting_id was not globally unique. This
namespaces every vendor's ids and reserves Bambu/OrcaFilamentLibrary space.

- Reserve "G*" (Bambu) and "O*" (OrcaFilamentLibrary) id spaces.
- Assign each other vendor a 2-char prefix (first+last letter, collision
  resolved) and renumber every instantiated preset to <PREFIX><NNNN>.
- Strip setting_id from base profiles (instantiation:false) per Bambu's
  convention; assign one to instantiated presets that lacked it.
- Remove the pre-existing misspelled "settings_id" key (91 files).
- filament_id is left untouched (it is a per-material id).
- Add one-time migration script scripts/assign_vendor_setting_ids.py with a
  persisted registry resources/profiles/vendor_prefixes.json. Re-runs freeze
  existing ids; only new vendors/profiles get new ids.
- Bump version in each changed vendor index file.
- Extend scripts/orca_extra_profile_check.py with a CI guard: global
  uniqueness, in-namespace, no base setting_id, no gaps, no settings_id typo.

7425 profile files changed across 61 vendors; 0 cross-vendor collisions;
validator clean; migration idempotent. BBL and OrcaFilamentLibrary id spaces
untouched.

* profiles: add setting_id authoring guide for new vendors / profiles

* profiles: drop in-repo README; setting_id guide now lives in the wiki

* profiles: derive setting_id deterministically from vendor/type/name

* bump profile version
2026-06-27 20:11:25 +08:00
Clifford GarwoodandClaude Opus 4.8 c5d0cdbcff Merge upstream/main into iXex PR branch (#13086)
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>
2026-06-26 23:29:35 -04:00
raistlin7447 7b3228d10d Cover the libnest2d nesting engine and fix an NfpPlacer crash (#14267)
* fix(libnest2d): skip the excluded-region alignment pass when there are none

NfpPlacer::finalAlign(), run from clearItems() and the destructor, always
ran the "find a best position inside the NFP of fixed items" pass even when
no items are fixed. With nothing to avoid, calcnfp() computes the inner-fit
NFP of the pile and can feed clipper a coordinate outside its allowed range.
On Linux/clang the value stays in range so it went unnoticed; on MSVC the
clipper "Coordinate outside allowed range" exception escapes the noexcept
destructor and aborts the process (exit 0xC0000409).

Build the excluded set up front and only run the pass when it is non-empty.
The block exists solely to keep the pile clear of fixed items (excluded
regions / wipe tower), so it is a no-op when there are none and the
wipe-tower behaviour is unchanged.

* test(libnest2d): remove dead nesting tests and split the suite by feature

Seven of the suite's hidden [.] test cases drove code paths Orca abandoned
at the BambuStudio fork: BottomLeftPlacer (used nowhere in src/) and the
stock default NfpPlacer backend, which returns zero bins in Orca. They have
been red since the fork and are never registered with ctest. Remove them.

Split the 1,000-line libnest2d_tests_main.cpp into per-feature files, per the
repo convention, sharing a header for the no-fit-polygon backend setup that
every translation unit must agree on (ODR):

  libnest2d_tests.cpp       Item and nest() basics
  test_geometry.cpp         geometry primitives
  test_nfp.cpp              no-fit-polygon machinery
  libnest2d_test_utils.hpp  shared includes and the NFP backend specialisation

Along the way: drop a debug exportSVG() helper that only wrote a file on test
failure (so the suite never leaves stray assets), convert the deprecated
Catch::Approx to WithinRel/WithinAbs matchers, and give the tests descriptive
names.

* test(libnest2d): add NfpPlacer unit tests

NfpPlacer is the placement engine the arranger drives, but the suite only
covered the geometry primitives. Add a fixture and five tests that exercise
pack()/accept() directly: a single item lands in the bin, an oversized item
is rejected, the first item is seeded for every starting point, many items
pack without overlap, and the rotation candidates are searched. This lifts
nfpplacer.hpp line coverage from 42% to 87% in the libnest2d suite.

* test(libslic3r): add arrangement::arrange() integration coverage

The libnest2d suite cannot reach Orca's real nesting entry point because it
does not link libslic3r. Add test_arrange.cpp driving arrangement::arrange():
items land on the bed and within bounds, do not overlap, are spaced by their
inflation, an oversized item stays unplaced, overflow spills onto virtual beds,
an empty input is a no-op, and the DONT_ALIGN and USER_DEFINED final-alignment
paths are exercised. A self-test guards the overlap check the other cases use.
2026-06-18 23:40:37 +08:00
raistlin7447 fe0eafc02b Fix Unit Tests CI job that silently ran zero tests (#14175)
Fix Unit Tests CI job silently running zero tests

scripts/run_unit_tests.sh selected tests with `ctest -L "Http|PlaceholderParser"`,
but catch_discover_tests() was called without ADD_TAGS_AS_LABELS, so Catch2 tags
were never registered as CTest labels. The -L filter matched nothing and the job
passed green while running no tests ("No tests were found!!!"). Tests have not run
in CI since PR #11485 added that -L line (2025-12-23).

Register tags as labels via a shared orcaslicer_discover_tests() wrapper in
tests/CMakeLists.txt (passing ADD_TAGS_AS_LABELS), routed through all five test
suites. Restore full-suite execution by replacing the narrow -L selection with a
`-LE NotWorking` exclusion, so all reliable tests gate PRs again (the suite ran in
full before #11485).

Tag the two OrcaCloudServiceAgent display-name tests [NotWorking]: their
constructor reaches wxStandardPaths::Get().GetUserDataDir(), which dereferences
the null wxTheApp in the headless test binary and segfaults on every platform.
Excluded until the agent can be constructed without the wx app context.

CI now runs 151 tests (was 0) and passes.
2026-06-14 17:44:20 +08:00
Clifford Garwood e502175030 Sync upstream main
124 upstream commits including CrealityPrint integration (added include
in Plater.cpp alongside the existing IMEXHelpers include), profile fixes
and version bumps (#14084, #14085, Polymaker), CI artifact publishing,
test refactors (arachne walls test added; test_3mf/test_config/
test_gcodewriter content moved/removed upstream — IMEX test file
preserved as it is feedback-only), translations.
2026-06-08 01:26:33 -04:00
AlexanderandSoftFever 1bbf8b64f4 Fix Arachne duplicate extrusion caused by bead count mismatch (#14031)
* Add test for Arachne duplicate wall segment detection

Add test cases that reproduce an issue where Arachne generates
duplicate/coinciding extrusion segments at certain min_bead_width settings.

Test configuration:
- Profile: 0.28mm Extra Draft @BBL X1C (0.4mm nozzle, 0.28mm layer)
- outer_wall_line_width: 0.42mm, inner_wall_line_width: 0.45mm
- wall_loops: 2, precise_outer_wall: enabled
- Test polygon: outer rectangle (0,0)-(20,20) with inner cutout (0.5,0.5)-(19.5,19.5)
  This creates a 0.5mm wide frame around the perimeter.

Results:
- 50% min_bead_width (0.20mm): FAILS - detects 4 duplicate segments (all 4 sides)
- 60% min_bead_width (0.24mm): PASSES - no duplicates

At 50%, Arachne generates two separate closed loops that share all 4 edges
of the inner square. At 60%, Arachne generates a single closed loop.

SVG output is exported to /tmp/opencode/ for visual debugging.

* Fix Arachne duplicate extrusion caused by bead count mismatch

WideningBeadingStrategy::compute() used optimal_width (inner wall width)
to determine if a thin wall should produce a single bead. However,
getOptimalBeadCount() uses optimal_width_outer (outer wall width) via
RedistributeBeadingStrategy to decide the bead count.

This inconsistency caused situations where getOptimalBeadCount() returned
2 beads, but compute() produced only 1 bead at full thickness. The single
bead was then generated for both inner and outer contours, resulting in
duplicate extrusion paths.

Fix: Use getTransitionThickness(1) instead of optimal_width. This method
returns the exact threshold for the 1-to-2 bead transition, ensuring
consistency between bead count calculation and bead generation.

Reproduces with: 50% min_bead_width, 0.42mm outer wall, 0.45mm inner wall,
0.5mm polygon inset creating ~0.38mm wall thickness.

Fixes #13917

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-06-06 22:55:37 +08:00
Clifford Garwood 493a9e96d2 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	src/libslic3r/Preset.cpp
2026-05-02 01:17:02 -04:00
SoftFever c04be9ab37 Introducing Orca Cloud: https://cloud.orcaslicer.com (#13414)
* Add OrcaCloud sync platform and preset bundle sharing system

  Introduce OrcaCloud, a cloud sync platform for user presets, alongside
  a preset bundle system that enables sharing printer/filament/process
  profiles as local exportable bundles or subscribed cloud bundles.

  OrcaCloud platform:
  - Auth to Orca Cloud
  - Encrypted token storage (file-based or system keychain)
  - User preset sync with
  - Profile migration from default/bambu folders on first login
  - Homepage integration with entrance to cloud.orcaslicer.com

  Preset bundles:
  - Local bundle import/export with bundle_structure.json metadata
  - Subscribed cloud bundles with version-based update checking
  - Thread-safe concurrent bundle access with read-write mutex
  - Canonical bundle preset naming (_local/<id>/... and _subscribed/<id>/...)
  - Bundle presets are read-only; grouped under subheaders in combo boxes
  - PresetBundleDialog with auto-sync toggle, refresh, update notifications
  - Hyperlinked bundle names to cloud bundle pages

  Co-authored-by: Sabriel Koh <sabrielkcr@gmail.com>
  Co-authored-by: Derrick <derrick992110@gmail.com>
  Co-authored-by: Mykola Nahirnyi <mnahirnyi@amcbridge.com>
  Co-authored-by: Ian Chua <iancrb00@gmail.com>
  Co-authored-by: Draginraptor <draginraptor@gmail.com>
  Co-authored-by: ExPikaPaka <112851715+ExPikaPaka@users.noreply.github.com>
  Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
  Co-authored-by: Ocraftyone <Ocraftyone@users.noreply.github.com>
  Co-authored-by: yw4z <ywsyildiz@gmail.com>
  Co-authored-by: peterm-m <101202951+peterm-m@users.noreply.github.com>

* Fixed an issue on Windows it failed to login Orca Cloud with Google account
2026-05-01 18:01:29 +08:00
Clifford Garwood 77c32a2e15 feat(imex): plate ghost renderer + per-plate filament map
Replaces the plater-icon popover with colored transparent ghost copies
of primary-head instances on the plate, one per secondary active head
under its Copy/Mirror role transform. Left-click on a ghost opens a
compact filament picker popover for the ghost's head (MMU lane override).
Ghosts track the primary through drag/rotate/scale/mirror and invalidate
on mode or pem changes.

Key pieces:
  IMEXHelpers -- imex_head_transform (Primary/Copy/Mirror), shared role
    parser, per-head filament resolution with X-axis Mirror anchor.
  PartPlate -- ghost state, volume rebuild on mode/map/object mutation,
    primary_origin plumbed for Mirror reflection across the primary-row
    gantry plane.
  GLCanvas3D -- ghost rendering with per-head filament color and
    translucent blending; picking routed via volume composite id.
  Plater -- ghost click + tooltip; plater icon left-click always cycles.
  IMEXFilamentPickerPopover -- BitmapComboBox row for one secondary head,
    writes imex_head_filament_map on selection.
  bbs_3mf -- round-trip the per-plate imex_head_filament_map option.
  PrintConfig -- add imex_head_filament_map as a plate option.

MMU/AFC routing for parallel modes relies on the printer profile's
physical_extruder_map (see prior commit for authoring format). Primary-
row heads and their per-plate filament overrides are resolved through
that map, so PA and temperature emission address the correct physical
extruder when multiple logical slots share one carriage.

Tests: IMEXHelpers coverage for Primary/Copy/Mirror transforms
including a 2x2 off-row regression guard for the X-axis reflection fix.
2026-04-21 14:56:22 -04:00
Maciej Wilczyński 0df673b0d3 Implement support for loading custom plugin binaries 2025-12-14 16:05:55 +01:00