Commit Graph

140 Commits

Author SHA1 Message Date
SoftFever
126e4d5445 refactor(plugin): split orca.host bindings into host/ by domain
PluginHostApi.cpp had grown into one TU holding the module entry point plus
three unrelated domains (presets, model/mesh graph, app access), and
PluginHostSlicing.cpp mixed ownable geometry value types with the
non-owning live print graph. Reorganize the orca.host surface into
plugin/host/ with one registrar per domain:

- PluginHost.hpp/.cpp        entry point (replaces PluginHostApi)
- PluginHostBindings.hpp     internal per-domain registrar declarations
- PluginHostGeometry.cpp     BoundingBox, Point, Polygon, ExPolygon + ndarray parsing
- PluginHostMesh.hpp/.cpp    TriangleMesh snapshot (own TU ahead of planned
                             mesh construct/mutate APIs)
- PluginHostPresets.cpp      Preset, PresetCollection, PresetBundle
- PluginHostModel.cpp        scene graph: Model, ModelObject, ModelInstance, ModelVolume
- PluginHostApp.cpp          Plater + plater()/model()/preset_bundle() accessors
- PluginHostSlicing.cpp      live print graph only, now with a single lifetime story
- PluginHostUi.hpp/.cpp      moved unchanged

PluginBindingUtils.hpp stays at plugin/ root: it is shared with pluginTypes/
and tests, not host/-specific.

No Python-visible change: same submodules, class names and docstrings.
Verified with slic3rutils and fff_print suites.
2026-07-11 16:18:59 +08:00
SoftFever
21b46044d0 feat(gcode): resolve per-filament variant slots per layer
- the g-code writer tracks the current layer id and resolves
  FILAMENT_CONFIG/NOZZLE_CONFIG (plus every non-macro variant lookup,
  toolchange placeholder scalars, and the change-filament flush
  overrides) through Print's per-filament, per-layer config-index
  resolvers instead of the filament->extruder collapse
- update_layer_related_config refreshes the per-layer
  extruder/volume/nozzle maps in the writer config;
  update_placeholder_parser_with_variant_params remaps the
  filament-variant arrays into filament-id space for custom g-code
  (Orca's flush placeholder computation moves inside it)
- the engine's concrete per-filament volume assignment now merges into
  the config write-back (the temporary hold from the producer commit
  is lifted together with these consumers), and the background process
  reads the computed volume map back to the plate
- append_full_config dumps the resolved filament_map_2 slots
- update_used_filament_values gains a bounds guard
- tests: per-filament Hybrid slot resolution + null-result fallback

Result: on a Hybrid extruder, each filament's features slice with its
assigned sub-nozzle's variant values (speeds, volumetric limits,
retraction). Verified on a 4-filament H2C Hybrid project: outer walls
split into three feedrate populations (30/50/200 mm/s), toolpath
geometry byte-identical, deterministic across repeated slices. All 18
non-Hybrid reference fixtures stay byte-identical except the
filament_map_2 header value now showing the real slot. Auto grouping
ties (multiple zero-flush perfect matchings) may pick a different
filament-to-nozzle isolation than other slicers; verified co-optimal.
2026-07-11 15:00:33 +08:00
SoftFever
03a704df7c feat(engine): wire the per-filament volume-map producer pipeline
- Print::update_filament_maps_to_config takes filament/volume/nozzle
  maps, backfills an empty volume map from extruder types, rebuilds
  filament_map_2, re-expands the per-filament variant arrays, and
  recomputes retract overrides keyed by resolved slots
- grouping writes its result back in every non-sequential mode;
  manual multi-nozzle grouping validates the user mapping and raises a
  translatable error on deviation; the engine's concrete volume
  assignment is deliberately not merged yet (per-filament arrays are
  already consumed by filament id, so materializing High Flow now
  would change motion before the layer-aware resolvers land)
- Print::apply treats the three map keys as engine outputs in auto
  modes (erased from the diff and adopted), compares them against used
  filaments in manual mode, and keeps the pre-expansion snapshot in
  sync with the late normalization pass so rebuilt headers reflect the
  sliced state instead of resurrecting stale values
- volume/nozzle maps and extruder_nozzle_stats join the invalidation
  group of filament_map (wipe tower + skirt/brim)
- PresetBundle composes full configs with an optional per-filament
  volume map (plate map, else defaults derived from each extruder's
  flow type); project config keeps the map sized across filament
  count changes
- PartPlate stores per-plate volume/nozzle maps; Plater injects them
  at every slice-composition site (incl. g-code reload and wipe-tower
  estimation); BackgroundSlicingProcess reads engine results back to
  the plate in auto modes
- per-filament map trust guards relaxed to size-match everywhere now
  that every producer sizes the map; single-filament explicit flow
  assignments are honored
- tests: grouping volume maps stay concrete, merge semantics of
  update_used_filament_values, single-filament override honoring

Motion g-code is byte-identical fleet-wide including Hybrid projects
(19-fixture gate + repro determinism double-slice). Header deltas:
the map keys now dump real values, and stale pre-normalization values
(e.g. enable_prime_tower on single-used-filament prints) no longer
leak into the config block.
2026-07-11 04:38:31 +08:00
SoftFever
a04ce5f81e docs(plugin): make comments self-contained; drop design-doc and dead-code references
Review the slicing-pipeline plugin comments for context a reader of the source
alone cannot follow, and rewrite them to stand on their own:

- drop pointers to uncommitted design/plan material ("§3.6 (Twistify design)",
  "the brief's note", "Fix 4(a)/4(b)")
- fix dangling references to code this branch removed: the retired set_slices()
  and view mutators, the former G-code post-processing capability/trampoline,
  the "Post-processing" capability family, the pre-refactor array helper
- drop "v1"/"in v1" phase labels, keeping the behavior they described
- correct stale cross-references: Twistify.py -> the real sample path;
  test_plugin_host_api.cpp:32-40 -> import_orca_module in python_test_support.hpp;
  "the binding"/"graphs above" -> the named source

Comment/string-only; no code behavior change.
2026-07-11 03:30:05 +08:00
SoftFever
18b9279c26 feat(print): add per-filament config-index resolvers and filament_map_2
- Print::get_nozzle_config_index / get_filament_config_indx resolve a
  filament's variant slot per layer from the nozzle group result, with
  hashed index caches; when no group result is published (sequential
  prints), they fall back to the static filament->extruder mapping so
  behavior is unchanged
- filament_map_2 caches each filament's resolved print-variant slot;
  rebuilt in Print::apply after the filament_map diff handling and in
  the filament-map write-back
- filament retract overrides now key by slot indices: apply_override
  fallback indexing flips to 0-based, Print::apply passes
  filament_map/extruder indices, the write-back passes filament_map_2
  (identical resolution while slots equal extruders)
- filament_volume_map/filament_nozzle_map/filament_map_2/
  filament_self_index become PrintConfig static members (required for
  member access); grouping input guards tightened so their registered
  1-element defaults are never mistaken for real per-filament maps
  (single-filament manual mode keeps the mix-marker fallback)
- update_filament_self_index_cache refreshed at every full-config
  assignment
- tests: 0-based apply_override fallback, get_config_index_base
  hit/miss/mixed-type cases

The resolvers are not consumed by the g-code writer yet. Non-Hybrid
g-code is unchanged except the config header, which now serializes the
three new static keys (defaults until the per-filament producer lands);
verified by the 19-fixture byte gate: 3 added header lines per fixture,
zero motion changes.
2026-07-11 02:29:40 +08: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
SoftFever
19352215da feat(plugin)!: merge G-code post-processing into the slicing pipeline as psGCodePostProcess
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.
2026-07-10 19:57:35 +08:00
SoftFever
21ed68963f refactor(plugin): prefix SlicingPipelineStepPlugin values with pos/ps to mirror Print steps 2026-07-10 17:28:26 +08: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
9e8ac03476 test(filament_group): don't assert max_group_size cap for MatchMode
The FilamentGroup property/golden harness checked a per-extruder
max_group_size cap unconditionally in check_constraints. That cap is an
invariant of the flush-partition solvers only (calc_group_by_enum /
calc_group_by_kmedoids, reached via calc_filament_group_for_flush), which
partition filaments subject to each extruder's capacity.

MatchMode (calc_filament_group_for_match) does not partition by capacity:
it maps every filament to the extruder holding the nearest-color loaded
AMS filament, and its solver capacity is the used-filament count, not
max_group_size (FilamentGroup.cpp:1067). So a legitimate MatchMode result
can place more than max_group_size filaments on one extruder.

The prop_a/b/c_mode_match specs run MatchMode, and their scenarios are
generated with std::uniform_int_distribution / std::shuffle, which are
implementation-defined. For a fixed mt19937 seed, libc++ (macOS), libstdc++
(Linux) and MSVC (Windows) draw different scenarios, so the CI failure only
surfaced on Linux/Windows while macOS passed. Verified locally: 248/600
config-A MatchMode seeds exceed the cap under libc++ — it is reachable
everywhere; seed 90400 just isn't an exceeding draw on macOS.

Gate section 3 on FGMode != MatchMode. No test case is removed or skipped:
all 57 FlushMode specs still assert the cap, MatchMode still asserts the
unprintable-filament/volume correctness constraints (which it honors), and
MatchMode grouping regressions are still caught by the golden score gate at
3% tolerance. Test-only change; slicing behavior and g-code are unaffected.
2026-07-10 02:17:52 +08:00
SoftFever
b58dcf5978 test(libnest2d): fix use-after-free crash in NfpPlacer lifetime tests
NfpPlacer stores std::reference_wrapper to the items it packs and re-reads
them from finalAlign() in its destructor (via clearItems()). Two placer
tests declared the placer before the items in the same scope, so the items
were destroyed first and the destructor dereferenced dangling references.

On macOS this is a deterministic SIGSEGV: libmalloc poisons the freed block
on free, so the item's point vector reads back as ~null (deref at 0x8). On
Linux/glibc the freed bytes usually survive, which is why it slipped through
upstream CI (introduced by #14267).

Declare the items before the placer so they outlive it, matching the pattern
the sibling 'packs many items' and 'obstacle' tests already use. Test-only;
the library lifetime contract (items must outlive the placer) is unchanged
and honored in production via _Nester in Arrange.cpp.
2026-07-10 01:55:00 +08:00
SoftFever
00816968a2 Merge branch 'main' into feature/h2c_support_clean 2026-07-09 22:17:20 +08:00
Andrew
bcd98ea791 Add stable hashed identity for speed dial actions 2026-07-09 16:21:53 +08:00
Kris Austin
6fda82476d fix: out-of-bounds read computing tool-ordering max layer height (#14665)
* fix: out-of-bounds read computing tool-ordering max layer height

calc_max_layer_height() loops over the extruder count (nozzle_diameter)
but indexes max_layer_height with the same counter, reading past the end
when that array is shorter. Silent on release builds, aborts under a
bounds-checked STL (_GLIBCXX_ASSERTIONS).

Read via get_at(), which falls back to the first entry when the index is
out of range, as Slicing.cpp already does for this option.

Add a fff_print regression test slicing a two-extruder printer with a
single-entry max_layer_height.

* docs: clarify how max_layer_height ends up short in the regression test

Normalization sizes it to the filament count under single_extruder_multi_material,
not "a mismatch a profile can ship" as the earlier comment guessed.
2026-07-09 15:47:57 +08:00
SoftFever
26a0caff96 save exact (not standard-rounded) nozzle diameter in 3mf metadata 2026-07-09 13:13:29 +08:00
Kris Austin
2194037d16 test: cover floor/ceil and the built-in function boundary in the placeholder parser (#14667)
round() already had unit coverage; floor() and ceil() had none. Add the missing
positive cases for both signs, plus round()'s half-away-from-zero tie-break, and
one negative case asserting that a name outside the grammar's built-in function
set is treated as an undefined variable and throws, rather than being passed
through to a math library.
2026-07-09 09:57:06 +08:00
Kris Austin
7d17400443 fix: dangling static lambda crashes support G-code export on repeated slices (#14677)
GCode::extrude_support declared its per-path speed helper as a function-local
static lambda that captures `this` by reference. The closure is built once, on
the first extrude_support call, and reused for the rest of the process, so a
second G-code export in the same process runs the helper against a `this` from
the first export's stack frame, which has already returned.

The stale `this` flows through NOZZLE_CONFIG(...) -> cur_extruder_index() ->
GCodeWriter::filament(), reading a garbage current-extruder id and indexing
with it. It is silent whenever the reused stack still holds a usable pointer,
and an order-dependent SIGSEGV otherwise; AddressSanitizer reports it as a
stack-use-after-return in GCodeWriter::filament(). It is the only static
capturing lambda in libslic3r.

Drop static so the closure is rebuilt each call against the live frame. Add an
fff_print regression test that slices a support object twice in one process; it
fails without the fix (stack-use-after-return under ASan) and passes with it.
2026-07-09 08:56:03 +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
Kris Austin
dec67345be fix: prevent out-of-bounds crash in Arachne beading interpolation (#14656)
* 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
2026-07-08 20:58:39 +08:00
SoftFever
11dd078f64 feat(plugin)!: faithful mutable geometry bindings; edit slices via the class API
Replaces the plugin-only set_slices/set_fill_surfaces/set_lslices mutators with a
faithful, mutable binding of the core geometry types, so a plugin edits the slicing
graph through the same object model the C++ code uses.

- Point, Polygon, ExPolygon, Surface and SurfaceCollection gain constructors,
  writable accessors (contour/holes, set/append/clear, filter_by_type), transforms
  (rotate/scale/translate), boolean ops and offset. Polygon exposes a zero-copy
  writable numpy view via a make_writable_rows helper.
- LayerRegion.slices/fill_surfaces stay read-only refs but are now live,
  in-place-editable SurfaceCollections; Layer.make_slices() re-derives the islands
  and refreshes lslice bounding boxes.
- Rewrites the Inset and Twistify samples on the new API (in-place ExPolygon
  transforms, ExPolygon.offset, SurfaceCollection.set), dropping their numpy
  dependency; each touched layer calls make_slices() so downstream steps see the
  edited footprint. Adds tests covering in-place edits through a live collection.

BREAKING CHANGE: set_slices/set_fill_surfaces/set_lslices and the internal
parse_expolygon(_list)/surfaces_from_py helpers are removed. Plugins mutate through
the class API (SurfaceCollection.set/append/clear, Polygon.set_points/append,
ExPolygon.set_holes) instead.
2026-07-08 15:04:40 +08:00
Kris Austin
4188ed2e00 feat: add regex_replace() string transform to placeholder templates (#14650)
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.
2026-07-08 08:58:51 +08:00
SoftFever
fd2a489980 Merge branch 'feat/plugin-feature' into feature/plugin-slicing
Brings in the Plugins dialog as-you-type search with fuzzy match highlighting
and clickable column-header sorting (name, version, source, status) — PRs
#14610 and #14611.
2026-07-08 01:03:34 +08:00
SoftFever
f81a24abfb feat(plugin): expose the slicing print-graph as raw orca.host classes + Twistify sample
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.
2026-07-08 00:05:28 +08:00
Rodrigo Faselli
b7d0bb60d9 Update test_skirt_brim.cpp (#14630) 2026-07-07 10:41:19 +08:00
Robert J Audas
1717c0f263 Fix brim first layer speed (#14616)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-06 19:04:32 -03:00
raistlin7447
29f31b9b38 fff_print: a maintainable testing framework (proposal + coverage) (#14426)
* 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.
2026-07-06 22:24:24 +08:00
Andrew
cfe3673b22 Refine plugin sorting to use name-first base order
Ensure plugins are sorted alphabetically by name
when no other column is sorted, and resolve ties
by source, status, type, and plugin_key.
2026-07-06 18:14:26 +08:00
Andrew
ee7339b64b Refine plugin sorting to use name-first base order
Ensure plugins are sorted alphabetically by name
when no other column is sorted, and resolve ties
by source, status, type, and plugin_key.
2026-07-06 16:25:07 +08:00
Andrew
a11e442f1d Add version sorting for plugins
Enhance plugin dialog with semver-aware sorting
by version, enabling users to sort plugins based
on version comparisons.
2026-07-06 15:25:09 +08:00
Andrew
714fe54f77 Move plugin sort from dropdown to clickable column headers
Replace the toolbar sort dropdown with sortable Name/Source/Status column
headers that cycle ascending, descending, then clear. Add a Source column
and a PluginSortKey::None baseline for the cleared state. The whole header
cell is the click target and the sort triangle snaps in without a fade.
2026-07-06 15:03:14 +08:00
Andrew
b724cb6631 Implement plugin sorting functionality
Add support for sorting plugins by status, name,
or source in both ascending and descending order.
2026-07-06 12:31:34 +08: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
SoftFever
dd99549d20 fix gcode time estimiation error (#14573)
fix gcode estimiation error
2026-07-04 15:29:19 +08:00
SoftFever
b0bacdd00b feat(plugin): add the slicing-pipeline plugin capability
Introduces a plugin capability that runs Python at the seams of Print::process(),
letting a plugin read and rewrite slicing state as it is computed.

- New slicing_pipeline_plugin config option; selected plugin refs are serialized
  into the print manifest.
- Print gains an injectable hook fired at each pipeline step (posSlice,
  posPerimeters, posInfill, ...). It is a no-op when unset, fires only on genuine
  (re)computation, and never on the use-cache path.
- orca.slicing submodule: SlicingPipelineCapabilityBase plus a trampoline and a
  Step enum. Capabilities read the live graph through zero-copy int64 numpy views
  (contour/holes geometry with unscaled coordinates, flattened toolpath data) and
  edit it through 2D-geometry mutators with cache-invariant refresh.
- GUI dispatcher runs capabilities during slicing under the GIL, turns plugin
  errors into slicing errors, honors cancellation, and adds the plugin picker.
- Ships the InsetEverySlice sample plugin and binding/hook tests.
2026-07-04 04:33:20 +08:00
Ian Chua
3668b01721 Merge branch 'main' into feat/plugin-feature 2026-07-03 13:29:40 +08:00
raistlin7447
036bd7bcec feat: add {first_object_name} filename placeholder (#14497)
{input_filename_base} is meant to be the saved project's file name. Before
#13753 a bug made it fall back to the first object's name when a project was
saved; #13753 fixed it to use the project name. Some users relied on the old
behavior to get the part name into their output file name and had no
placeholder to recover it ({model_name} is the 3mf designer metadata, blank
for plain STL imports).

Add {first_object_name} as a dedicated placeholder for the first printable
object on the current plate, populated in update_object_placeholders()
independently of {input_filename_base}.

Closes #14493
2026-07-03 00:14:32 +08:00
Noisyfox
464a81d585 Support accessing coFloatsOrPercents values in gcode template (#14526)
* Support accessing `coFloatsOrPercents` values in gcode template (OrcaSlicer/OrcaSlicer#14522)

* Vector option values are separated by comma

* Fix wrong cast used for checking nullability
2026-07-02 23:51:20 +08:00
Ian Chua
ecddf3d18f feat: Python Plugins 2026-07-02 17:49:36 +08:00
SoftFever
f516f47c8e add profile validator checks 2026-07-01 21:55:19 +08:00
SoftFever
e39be23d6d fix compatible_prints/printers on load instead 2026-07-01 15:25:43 +08:00
raistlin7447
3cf0f4dba5 test(fff_print): re-enable tests disabled by the m_origin clipper throw (#14482)
PR #13712 fixed the uninitialized Print::m_origin (commit 99dea01cc3, "Fix coord
out-of-range exception caused by m_origin memory not initialized to 0") that made
headless slice() intermittently throw ClipperLib's "Coordinate outside allowed
range". With that root cause fixed, the three tests disabled for it pass again,
so drop their [NotWorking] tags.
2026-06-30 09:03:44 +08: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
SoftFever
14e572db5f Add nozzle flow variant & make some options multi-variant (#13712)
# Description

Port BBS per-extruder config variants toggle, thanks Bambu!

Also fix invalid num error when resetting multi-variant filament
overrides.

TODOs:

- [x] Make more configs multi-variant (such as speeds)
- [x] Add flow variant (normal/high flow) combo box
- [x] Add botton to sync config to other variant


# Screenshots/Recordings/Graphs

<img width="846" height="1494" alt="image"
src="https://github.com/user-attachments/assets/47abf053-f5b8-4c86-ac0b-c0323ed8b242"
/>

<img width="1478" height="1189" alt="707420e5be01c30af3e6ede1f3dc9b67"
src="https://github.com/user-attachments/assets/11268712-da65-42ab-9cb8-3cede7790a5c"
/>

<img width="1478" height="1189" alt="81d5d3877f4d5bf9dccd44d7f0b30aa7"
src="https://github.com/user-attachments/assets/cda5ea51-07c3-48fc-bfbb-1428dca14e26"
/>


## 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)
Fix #10336
2026-06-28 22:30:40 +08:00
Ian Chua
0e8288de36 fix: old preset names should resolved renamed_from field (#14429)
* fix: old preset names should resolved renamed_from field

* chore: remove misleading comments

* Merge branch 'main' into fix/consider_renamed_from

* normalize_inherits

* improve find_preset2 performace
2026-06-27 22:15:43 +08: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
Noisyfox
cdc336d80c Merge remote-tracking branch 'upstream/main' into dev/extruder-toggle-wip 2026-06-25 12:46:35 +08:00
Noisyfox
eae002da13 Add unit test for per-extruder motion limit 2026-06-25 12:44:43 +08:00
Noisyfox
b7240ab1c6 Use max limit when current extruder is unknown 2026-06-25 12:20:13 +08:00
SoftFever
da074043f2 Fix fuzzy skin artifacting regression (#14376) (#14382)
Fix fuzzy skin artifacting (#14376)
2026-06-25 10:52:19 +08:00
Noisyfox
d13958ac54 Emit max value of machine limit among used extruders 2026-06-24 14:16:13 +08:00