Commit Graph
119 Commits
Author SHA1 Message Date
Kris AustinandRodrigo Faselli 6e0f04815b perf: speed up G-code export by up to 7% via post-processing fixes (#16031)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-10-03 13:29:55 -03:00
Kris AustinandRodrigo Faselli c67b54b39d perf: speed up G-code export by 4-17% via parallel overhang precompute (#16050)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-10-03 11:50:36 -03:00
HanifKoh 84657ff11e Add Missing Includes Across the Remaining Sources and Tests (#16071)
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy

Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp.

* Ignore minilzo's Config Headers in clang-tidy

lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes.

* Add Missing Includes Across the Remaining Sources and Tests

Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo.

* Make the GUI and Test Headers Compile on Their Own

Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone.

* Keep Windows and nanosvg Setup Ahead of the Added Includes

OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build.

* Add the GUI Includes the First Pass Missed

Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass.

* Keep the Added Test Includes Below the NOMINMAX Guard

test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
2026-10-03 13:45:21 +08:00
Kris Austin eb30ea1eb8 perf: speed up G-code export by 3-9% via cached config lookups (#16028) 2026-10-02 19:34:47 -03:00
Ian BassiandRodrigo Faselli 222c6a2df5 Improve performance by migrating to Clipper2 2.0.1 (#15969)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-10-02 17:33:41 -03:00
Kris Austin d1d14329d9 fix: exporting a sliced print again gives different G-code (#16025)
extrude_infill() and extrude_support() reversed the layer's extrusion
entities in place while chaining them, so each export started from the
previous one's reversed toolpaths, and each copy of an object from the
copy before it. The export-time region lists now hold const pointers,
and chaining reverses a clone instead.
2026-10-01 08:08:03 -03:00
HanifKoh 92d30fbc55 Clamp Ironing Line Spacing to a Usable Minimum (#15949)
An ironing line spacing of 0 reached the fillers from a 3MF, the CLI or
the per-filament override, which has no GUI guard. Concentric ironing
then never finished slicing, because a zero inset never shrinks the
region, and rectilinear ironing was silently dropped. Tiny positive
values produced an unprintable number of lines.

Top surface and support ironing now clamp the spacing to the 0.05 mm
floor the process GUI guard already enforces, so these configurations
iron at that spacing. Spacings at or above the floor, including every
shipped profile, are unchanged. The concentric filler also returns early
on a non-positive step so no other caller can hang it, and the filament
settings page now resets a too-small override the same way the process
page does.
2026-10-01 16:53:16 +08:00
SoftFever 8aa5b1130a Allow nozzle variants to specify different cooling parameters (#16007)
# Description

Include variant-aware validation, temperature and pressure controls,
named nozzle selection, and filament sidebar refresh.

## Support nozzle-specific filament cooling and tuning

Filament presets can require different cooling and tuning for Standard
and High Flow nozzle variants. This change makes part and auxiliary
cooling, pressure advance, temperature limits, and multitool ramming
settings follow the selected variant, with matching UI controls and
profile validation.

The Snapmaker U1 profiles in #15755 / Snorca illustrate why this
matters:

| Profile | Standard cooling | High Flow cooling |
|---|---|---|
| Snapmaker ABS | Part fan: 15–15% | Part fan: 10–60% |
| Snapmaker PETG HF, 0.4 mm | Part fan: 20–40% | Part fan: 30–60% |
| Snapmaker PETG-CF | Part fan: 0–20%; auxiliary: 0% | Part fan: 5–40%;
auxiliary: 20% |
| Snapmaker PLA Matte | Auxiliary: 80% | Auxiliary: 100% |

These differences need to survive variant selection, editing, and
slicing. Shared single values continue to apply across variants, and
short filament arrays fall back to element zero, matching the loader.

### Additional changes

- Preserve named nozzle selections when refreshing the diameter
selector.
- Enable or disable the pressure-advance input for the selected variant.
- Initialize profile-validation slicing with the printer’s declared
nozzle volume type.
- Refresh filament controls after preset loading.

Profile changes remain separate in `u1-hf`.

### Validation

- All 13 focused variant-tool tests passed.
- Broader checks encountered an existing Windows path-separator
assertion failure, reproduced with upstream code.
- C++ build and GUI validation have not been run.

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-10-01 13:53:22 +08:00
SoftFever ba361d9882 Texture displacement (#14662)
## Summary

Adds a new paint-style **Texture Displacement** gizmo that stamps
grayscale
height-map textures onto a model's surface and turns them into real
relief -
engraved or embossed detail - either as a live preview or baked into
actual mesh
geometry.

You paint where a texture applies, stack up to **8 blended texture
layers**
(image-editor semantics: Add / Subtract / Multiply / Divide), choose how
each is
projected onto the surface (Triplanar / Cylindrical / Spherical / LSCM
unwrap /
From-view), and - for the LSCM projection - lay the charts out by hand
in a new
dockable 2D **UV Editor** pane. Coarse models can be **Subdivided** or
**Remeshed** first so there are enough vertices to carry fine detail,
and the
result is committed with **Bake**, restricted to the painted area only.

The tool only ever affects the **painted** region; everything left
unpainted
keeps its original surface, and bake blends the relief seamlessly into
it with no
remeshing or hole-filling at the seam.

---

## User-facing features

- **Paint the affected area** with Brush (circle/sphere), single-Face,
or
Connected-area flood fill; or **Select whole model** - reusing the
existing
`TriangleSelector` / `FacetsAnnotation` painting machinery, one full
mask per
  layer slot.
- **Up to 8 texture layers**, each with its own paint mask, texture, and
  parameters, combined in slot order like image layers.
- **Per-layer controls:** Depth, Tile size, Rotation, Midlevel
(bidirectional
  emboss/engrave), Smoothing, Edge smoothing, Invert, Blend mode, Tile
  (Repeat / Mirrored-repeat / decal), and Projection.
- **Projection methods:** Triplanar (blended, seam-free across sharp
edges),
  Cylindrical, Spherical, **Unwrap (LSCM)** - a real CGAL conformal
  parameterization - and **From view** (slide-projector decals).
- **UV Editor pane** for LSCM layers: move / rotate / scale / snap / cut
/ join
islands, average texel density, Checker and Distortion overlays, manual
mark-
  seam workflow, live model update while dragging.
- **View modes:** Normal (true displaced geometry = what Bake produces),
Fast
(GPU bump-shaded approximation of the active layer), Checker, Distortion
  heatmap, and an independent Wireframe toggle.
- **Mesh prep:** Subdivide (1–5* uniform 1->4 split) with cyan-wireframe
preview,
  and CGAL isotropic **Remesh** to a target edge length.
- **Texture library:** 10 shipped seamless 512×512 grayscale height
maps, plus
import of any PNG/JPG/BMP (converted to an 8-bit grayscale map and
copied into
  the user data dir so app updates can't clobber it).
- **Bake** runs in the background (off the UI thread); the preview is
free to
  explore and only Bake changes the real mesh.

---

## How it works (implementation)

- **Bake is accumulate-then-displace and topology-preserving.** The
output mesh
  has exactly the input's vertices and triangles in the same order; only
displaced vertex positions differ. Each layer is evaluated against the
**base
mesh** and folded per-vertex into a shared accumulator via its blend
mode, then
every touched vertex moves once along its precomputed undisplaced
normal. This
replaced an earlier sequential re-mesh-per-layer design that was the
root cause
of the "second layer never applies" bug and made blend modes impossible.
- **Boundary vertices are pinned.** Any vertex shared with an unpainted
triangle
is never displaced, which is what keeps bakes seamless with zero
remeshing.
- **LSCM unwrap** uses a new `MeshBoolean::cgal::parameterize_lscm()`
built on
CGAL's already-vendored `Surface_mesh_parameterization` package - **no
new
  external dependency**.
- **Fast GPU preview** perturbs the shading normal from the height
gradient
(analytic mm-per-mm slope for triplanar; Mikkelsen's
screen-space-derivative
method for the conformal LSCM path), so apparent depth matches the bake.
- **Background jobs:** preview compute and bake both run off the UI
thread on the
shared job worker (queued, not `replace_job`, so a preview never cancels
an
  in-flight bake); a generation counter discards stale results.
- **UV Editor** shares the app's single real `wxGLContext` and reuses
the
registered `flat`/`flat_texture` shaders; island drags update one affine
matrix
  per island rather than re-uploading geometry.


---


## Backward compatibility & constraints

- **Feature is fully gated behind the new gizmo** - it adds no new
default
behavior and does not touch existing slicing, profiles, or defaults.
Models
  that never open the tool are unaffected.
- **Cross-platform** - pure `libslic3r` / `libslic3r_gui` /
`libslic3r_cgal`
code; no new dependency and no `deps/` rebuild. (Built and tested on
Windows;
  no platform-specific APIs introduced.)
- **`.3mf` compatibility:** **baked** relief round-trips fine, since it
becomes
ordinary mesh geometry via the existing serialization path. **Unbaked**
paint
masks and layer definitions are **not yet serialized** - see
Limitations. No
  existing project data is affected.

---

## Testing

Unit tests in `tests/libslic3r/test_texture_displacement.cpp` - **run
and
passing** (7 cases, 116 assertions). Coverage:

- `decode_height_texture` round-trip
- Empty-layer no-op
- Full-cube uniform displacement
- Boundary-vertex pinning on a hand-built fan mesh
- Regression: a **second layer over the same area actually contributes**
(the
  bug the bake rewrite fixed)
- Table-driven check of all four blend modes
- The lowest painted layer ignoring its blend mode

`BUILD_TESTS` is `OFF` in the checked-in cache; enable to run:

```bash
cmake -S . -B build -DBUILD_TESTS=ON
cmake --build build --config Release --target libslic3r_tests -- -m
./build/tests/libslic3r/Release/libslic3r_tests.exe "[TextureDisplacement]" --order rand
```

---
2026-10-01 12:40:33 +08:00
SoftFever c03f4925a9 Apply per-variant cooling, ramming and temperature range on nozzle-rack slices
Fan speeds, multi-tool ramming, the tower interface and flush temperature
fallbacks and the custom G-code placeholders now use the extruder variant a
filament prints with on each layer, instead of reading by filament id.
2026-10-01 02:54:18 +08:00
Ian BassiandRodrigo Faselli 97700c5ab5 Gyroid Optimization (#16002)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-09-30 10:21:24 -03:00
SoftFever 1e4489eb16 Merge branch 'main' into feature/texture_displacement 2026-09-30 15:28:08 +08:00
789f848694 Write the estimated printing time comment after the config block, not before (#15897)
Co-authored-by: Fernando Marino <f.marino@rheagroup.com>
Co-authored-by: yw4z <ywsyildiz@gmail.com>
2026-09-29 19:18:15 -03:00
SoftFever ef0c656932 Tune pressure advance separately for each extruder variant
Pressure advance, adaptive pressure advance and its model can now take a
different value for each extruder variant of a filament, such as Standard and
High Flow nozzles, like the other per-variant filament settings. Projects
saved with one value per filament apply it to every variant of that filament,
and the addnorth BBL filaments in the Orca Filament Library are updated to the
per-variant layout.
2026-09-29 17:52:13 +08:00
ExPikaPaka 75b6175988 Merge remote-tracking branch 'origin/main' into feature/texture_displacement 2026-09-29 08:36:11 +02:00
Rodrigo FaselliandIan Bassi 11e9e07f20 Non-crossing infill optimization (#15931)
* Non-crossing infill optimization

* test triangles

* test grid

* cleaning

* Align and clip rectilinear infill paths

Generate infill coverage in the pattern's local frame, rotate triangular patterns by layer, and clip centerlines to the surface vicinity. Start closed outlines outside the surface so clipping splits them cleanly.

* Update test_fill.cpp

* Update multiline-infill.md

---------

Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-09-28 15:13:57 -03:00
SoftFever 9d8257d2eb Support extruder variants on every printer (#15964)
# Description

Extruder variants (Standard, High Flow, extra high flow) now work on any
printer. Any vendor profile can declare them, and a multi-variant
filament picks up the right variant on every printer. In the sidebar,
users can switch the printer variant and set the nozzle volume type of
each extruder on multi-extruder printers. This also fixes a later
filament printing at the first filament's temperature on a P1S or X1C
with a High Flow nozzle. The profile checks now reject variant arrays of
the wrong size and outdated variant strings. Every shipped vendor
profile passes them, and the orca-profiles skill documents the rules.

Slicing output changes only where the wrong variant was used before. 
# Screenshots/Recordings/Graphs
<img width="393" height="218" alt="Screenshot 2026-09-28 at 11 28 07 PM"
src="https://github.com/user-attachments/assets/8bee4b0e-c38c-4039-8c11-096ace6fbad0"
/>
<img width="448" height="267" alt="Screenshot 2026-09-28 at 11 28 37 PM"
src="https://github.com/user-attachments/assets/e767cd97-a5d0-4728-b010-c8ea2bc94ca7"
/>
<img width="746" height="603" alt="Screenshot 2026-09-28 at 11 28 54 PM"
src="https://github.com/user-attachments/assets/23c8af3b-c679-46e5-9fd0-2e43df0449b3"
/>




https://github.com/user-attachments/assets/10d75d72-86a3-42e8-8a95-b1627bd58e91



## 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)
2026-09-29 01:57:01 +08:00
1846407e93 Add Precise Seam placement feature (#12974)
Co-authored-by: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com>
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-09-28 14:40:55 -03:00
SoftFever d48e63b5e3 Merge branch 'main' into feature/add-multi-variant 2026-09-28 23:30:14 +08:00
SoftFever 71bb400e46 Add multi-variant support to the app 2026-09-28 19:08:35 +08:00
Ioannis Giannakas 7707487252 Fix overhang slowdown and fan applied to whole walls ahead of an overhang (#15945) 2026-09-28 10:59:39 +01:00
Ian Chua d347a80ef8 Merge branch 'main' into fix/slicing-evt-name 2026-09-27 17:57:40 +08:00
peachismomo 58842bab05 test: test for SliceStarted ensuring stable model ID is presetn when model name is absent 2026-09-27 17:29:01 +08:00
peachismomo 04204ec0d3 test: cover slicing lifecycle event context 2026-09-27 17:25:56 +08:00
0ddc730854 No fuzzy skin on bridge like overhangs perimeters (#13891)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-09-26 16:42:44 -03:00
Ian Bassi ea280ba6f6 Wipe tower sparse layers combination (#15841) 2026-09-26 16:27:15 -03:00
Ian BassiandRodrigo Faselli 8c03985818 Add Cubic Non-crossing multiline strategy (#15887)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-09-26 11:40:49 -03:00
ExPikaPaka 7766c2e003 Test that a baked texture still slices
The bake is covered in the libslic3r suite, but nothing carried its
result through the slicer - where a mesh it cannot use shows up as a
crash or as a print with no toolpaths, which is what was reported on
macOS and Linux.

Paints a cube, bakes it as the gizmo commits it (mesh replaced, hull
recomputed, paint cleared), slices it and checks the G-code has
toolpaths and layers. Once under its budget and once capped, since a
capped bake also goes through the simplification and the repair.
2026-09-25 10:31:04 +02:00
SoftFever da951ad7f3 Load profile includes so synced Bambu Lab presets get their G-code back (#15869)
# Description

This brings back the Bambu Lab profile sync with BambuStudio, reverted
from main, along with its bed-model offset fix. The synced printers and
filaments share their start and end G-code and dual-nozzle settings
through template files that Orca did not read, so those printers had no
machine G-code. Orca now loads these templates the same way BambuStudio
does, so every synced preset comes in complete. `profile_include_dump`,
a new developer tool, compares the result with BambuStudio's.

Other vendors' profiles are unaffected. Bambu Lab profiles move to
version 02.08.00.10, so installs that took the earlier sync update too.

<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
  > * What issue does this PR address or fix?
  > * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->

# Screenshots/Recordings/Graphs

<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->

## Tests

Unit tests cover how template settings combine with inherited and preset
settings, loaded from JSON and from the preset cache. The profile
validator passes on every shipped vendor, and every Bambu Lab preset
gets the same template values in Orca as in BambuStudio.

<!--
> 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)
2026-09-25 13:17:43 +08:00
HanifKoh db10c719f6 Keep the Scarf Seam Free of Sub-Millimetre Segments (#15832)
A scarf joint split the loop at exactly the scarf length, so the remainder
of the segment the split landed in became the first flat segment, often a
fraction of a millimetre. The seam insertion also leaves segments of a few
micrometres at both ends of the loop, which a scarf extrudes through where a
plain loop would start or stop. With junction deviation the planner treats
such short moves as tight corners, limited by the Z axis acceleration at the
end of the ramp, and slows to a third of the wall speed or nearly halts at
the seam.

Extend the ramp to the next vertex when the remainder would be shorter than
half a scarf step, capped at a millimetre, beyond which planners treat a move
as ordinary; the scarf only grows, never shrinks. Drop the vertex next to the
seam point at either end when that segment is shorter than an eighth of a
common line width, so the loop still starts and ends at the seam; a trimmed
path loses its arc fitting and prints as line segments. Clamp the scarf
length to the trimmed loop so a scarf covering a whole loop still ends at
full flow. The descending pass reuses the same path, so both wedges stay
consistent, and a flat part that would collapse to a single point is dropped.
2026-09-25 12:32:05 +08:00
HanifKoh af52da061f Report Per-Object Slicing Errors in the CLI (#15834)
G-code generation collects errors raised per object, such as an empty
first layer, into one SlicingErrors exception whose own message is just
"Errors". The CLI's generic handler printed that word and recorded the
generic slicing error text, so a headless caller had nothing to act on.

Let Print render the per-object messages with each object's name, and have
the CLI catch SlicingErrors ahead of the generic handler, print that text
and record it as the result's error string. The exit code is unchanged. A
unit test lifts a cube off the bed and checks the message names the object.
2026-09-25 08:37:28 +08:00
SoftFever 434ff3011f Fix: Update tree support wall count default value and improve G-code loading for Bambu Lab profiles 2026-09-24 15:45:35 +08:00
Kris Austin b4b4438a47 fix: custom G-code keyword check uses the wrong list and skips the editor (#14908) 2026-09-20 10:24:55 -03:00
Kiss Lorand caa15491c3 Fix duplicate timelapse G-code on i3 printers (#15734) 2026-09-19 13:19:54 -03:00
Ian Bassi 8a17df4a89 Fix some overhang detection (#15694) 2026-09-18 14:23:38 -03:00
Ian Bassi 59e40a2c2e Print unsupported walls last (#15411) 2026-09-17 09:14:20 -03:00
packerlschupfer 9321f24959 CLI: --strict, and a warnings array in result.json (#14601)
# Description

Add `--strict` for CI and scripted pipelines, and a structured
`warnings`
array in `result.json`.

## `--strict`

A NON_CRITICAL slicing warning is logged and the slice succeeds: return
code
`0`, G-code written. That suits interactive use, but a pipeline then
ships a
slice with a warning nobody saw. With `--strict`, such a warning fails
the run
with `CLI_SLICING_ERROR` before the G-code is exported. Without the
flag,
nothing changes.

In FFF the warning that reaches this path is "support needed but
disabled"
(`PrintObject::generate_support_material`). `--no-check` skips that
check, so
`--strict --no-check` is rejected with `CLI_INVALID_PARAMS`.

`--strict` is read before any work, so it doesn't depend on argument
order and
`result.json` reports it for early failures as well.

## `result.json`

Two new top-level fields:

- `warnings`: `[{"class", ...details}]`. One class is wired:
`slicing_warning_non_critical` with `plate_id` and `text`, recorded
whenever
such a warning fires, with or without `--strict`. The array also fills
on
  runs that succeed, so `return_code` stays the verdict.
- `strict_mode`: whether `--strict` was on.

`record_exit_reson` writes `result.json` on Linux only, so both fields
exist
only there. The non-zero exit works on every platform.

## Tests

- `tests/fff_print/test_support_material.cpp` (all platforms): an
overhang
sliced with support off raises the NON_CRITICAL support-needed status,
and
  the no-check flag suppresses it.
- `tests/cli/test_cli_strict.sh` (Linux only): runs `orca-slicer`
without
flags, with `--strict`, and with `--strict --no-check`, and checks the
shell
status and `result.json` of each. It runs the built binary, so it
carries the
`RequiresApp` label, which `scripts/run_unit_tests.sh` excludes because
the
  unit-test job only receives `build/tests`. Run it with
  `ctest --test-dir build/tests -C Release -L RequiresApp`.
- CI: `unit_tests.yml` now passes `Release` on Linux too.
`build_linux.sh`
configures Ninja Multi-Config, and without a config ctest drops the
labels of
plain `add_test()` tests, so this test ran as "Not Run" instead of being
excluded. The docs that assumed Linux was single-config are corrected
too.

Built and run locally on Linux (GCC 14) on current `main`: both tests
pass,
and the touched files compile clean under Clang with `-Werror`.
2026-09-16 12:54:48 +08:00
Valerii Bokhan 3e1daccd7c Feature: Add inward wipe for external perimeters (#15407) 2026-09-15 20:01:39 -03:00
Daniel Williams 70247ad298 Extract Layer::choose_ironing_extruder for unit-testable ironing routing (#13467)
* Extract Layer::choose_ironing_extruder for unit-testable ironing routing

The ironing extruder selection in make_ironing() was a 5-line nested
conditional inlined at the top of the loop, with no isolated test
coverage. Pull the gating into a static helper so the routing decision
is unit-testable without spinning up the slicing pipeline.

Pure refactor: the helper preserves the original logic bit-for-bit
(NoIroning -> -1; AllSolid always enabled; TopSurfaces and TopmostOnly
require some top shells or, in spiral mode, more than one bottom shell;
TopmostOnly additionally requires being on the topmost layer; enabled
ironing routes to solid_infill_filament).

Add tests/fff_print/test_choose_ironing_extruder.cpp covering:
- AllSolid regardless of layer position
- TopSurfaces with top_shell_layers > 0
- TopSurfaces with top_shell_layers=0 + spiral mode + bottom_shell_layers>1
- TopmostOnly + topmost layer
- NoIroning short-circuit
- TopSurfaces with top_shell_layers=0 (and not spiral) -> disabled
- TopSurfaces, spiral, but bottom_shell_layers=1 -> disabled
- TopmostOnly on a non-topmost layer -> disabled

* Move ironing routing test into the Fill subsystem file

Rename the test to tests/libslic3r/test_fill.cpp and tag it [Fill] to
match the subsystem it covers, use flat behavioral test cases with
GENERATE for the parameterized ones, and drop the history narration from
the code comments.

* tests: move ironing routing tests into fff_print/test_fill.cpp

Keeps the Fill tests in one file, alongside the existing ironing
rotation-template test.
2026-09-14 09:37:04 -03:00
Valerii Bokhan e8d35fadd4 Fix internal bridges over Hilbert Curve/Octagram Spiral sparse infill (#15206)
* Fix internal bridges over Hilbert Curve/Octagram Spiral sparse infill

For patterns with curved/turning anchor lines (Hilbert Curve, Octagram
Spiral), the bridge_over_infill algorithm produced incorrect results:

1. determine_bridging_angle: sampling curved anchor orientations
   produced noise across all turning directions (0/90/180/270°)
   instead of a single dominant one, yielding unstable bridge angles
   with 180° spread. Fix: use the configured infill_direction + 90°
   directly, bypassing the noisy sampling. The old blind +0.25*PI
   (Hilbert) and +1/16*PI (Octagram) offsets are removed.

2. construct_anchored_polygon: curved Hilbert/Octagram anchors
   intersected each vertical scan line many times at wildly different
   Y positions, producing chaotic polygon sections — holes in random
   places, bridges over air, rotated bridges. Fix: replace the curved
   infill polylines with synthetic straight lines parallel to
   infill_direction, spaced at the real infill line spacing
   (flow_spacing / density). Lines are centered on the limiting_area
   bbox center so that after rotation they span the full bridged_area.
   Anchors are left at full bbox length (not clipped) to guarantee
   every scan line finds an anchor.

Rectilinear and other straight-line patterns are unaffected.

Known limitation: some bridge edges may still terminate over air in
edge cases where the nearest synthetic anchor line is more than one
infill spacing away from the bridge boundary. This will be addressed
in a follow-up.

* fix: anchor internal bridges to actual sparse infill

Preserve real anchors across regions and align plane-path anchor origins with printed infill. Respect lower-layer rotation templates and model alignment, and sample curved bridge boundaries more finely.

Add regression coverage for anchor alignment, bridge angles and region isolation, with Orca comments explaining the geometry constraints. Verified 175 FFF tests before the comment-only follow-up; preserve CRLF in modified files.

* Fix internal bridge support contacts and separated infill origins

Restore anchor contact after bridge smoothing and share per-body pattern origins between anchors and printed infill. Recompute origins when preparation settings change.

Cover multiline counts 1, 2 and 3 and add regressions for printed bridge support, separated infill alignment and reslicing.

* Add explicit standard headers to PrintObject tests

* test: cover surface centering when infill settings change

Verify top and bottom Archimedean Chords and Octagram Spiral paths after switching centering modes or toggling separated infills. Compare reslicing against fresh slicing and document dependent infill invalidation.

* test: preserve directional surface infill when settings change

* perf: index layer islands for connected-body detection

* test: use public print pipeline for body centering checks
2026-09-10 08:03:50 -03:00
Hanif Koh 81357695c5 Verify WipeTower Footprint at Point of Generation
The clamps and validation work from estimates. Once the tower is
generated, _make_wipe_tower re-tests the exact first-layer footprint,
brim and cone base included, against the printable area and the
exclusion zone, so an off-plate tower fails with a clear error instead
of exporting unprintable G-code. The rectangle-wall mesh footprint
learns the Type2 cone base so that check and the post-generation
validation see the real outline.

Pre-generation, validation hard-checks the body plus an explicit brim
and warns on the estimated auto brim and cone base with the existing
"may collide" strings, so the user hears about a marginal position on
the first slice rather than only at generation time.

Two fff_print fixtures that print a tower at the default position move
it onto the 200 mm test bed, as the multifilament fixtures already do:
the shipped default y of 220 is off that bed, and the backstop now says
so instead of exporting the tower.
2026-09-09 15:45:16 +08:00
Hanif Koh 99627c8e93 Size the Footprint Estimate from the Planners
The shared estimate reserved every tower with one volume-per-purge rule
and the stability floor. Both planners do more: WipeTower (Type1) wipes
each filament's own prime volume in whole lines, one block per
adhesiveness category sized by its worst layer, rams the leaving
filament at every nozzle change, and squares a rib tower from the
planned depth; WipeTower2 (Type2) spaces its lines by
wipe_tower_extra_spacing, not the Type1-only infill gap, and its extra
flow cancels out of the depth. Both extend the ribs rather than the body
below the stability minimum, size every layer including a thinner first
one, and lay the brim in whole loops, WipeTower reporting half a spacing
of line width on top.

All of that now lives in estimate_wipe_tower_footprint, fed the planner
(resolve_wipe_tower_type mirrors Print::wipe_tower_type and the CLI's
Bambu Lab detection) and the filament ids rather than a count. Print
passes its own tool set; the PartPlate adapter derives the plate's ids
from the passed config and treats an explicit count as a floor, so the
CLI's count-only callers size per filament too. The placement clamp also
reserves a Type2 cone's base bulge, which the body box does not cover.

The planner-mirroring helpers sit beside the planners in WipeTower and
WipeTower2 so the two stay in sync; the libslic3r cases pin them to
footprints measured from generated G-code.
2026-09-09 15:45:16 +08:00
Hanif Koh e1efec7d6c Fix review findings in the shared wipe tower estimate
A raft is not a reason to reserve a tower. Print::apply runs
normalize_fdm_2, which clears enable_prime_tower for a plate that purges
one filament unless smooth timelapse or wrapping detection is on, so a
single-filament plate with a raft prints no tower at all and the estimate
was reserving bed area for one. Drop the input; need_wipe_tower is now
exactly the two exceptions normalize_fdm_2 honours, named there so the
next reason added has to be checked against it.

The GUI preview and the validation containment check each re-derived
"is a tower printed here" from the filament count instead of reading the
estimate, so both missed the towers printed with no tool change to purge
for. They now take the answer from the footprint, which is the drift this
shared estimate exists to remove. A tower that is not printed estimates to
zero, so its hull is degenerate and every check on it passes trivially -
the containment check needs no gate of its own.

WipeTowerData::width was written only by the pre-generation estimate and
left at zero for the whole post-generation life of the Print, while its
neighbour depth held the real value. Set it from the generator in both
branches.

The plate's height scan transformed every model part's full mesh per
instance on each scene reload, discarding all but the z extent. The
cached convex hull has the same z extent.

A plate loaded from a sliced .gcode.3mf holds no objects and its filaments
live in slice_filaments_info; the config-taking get_extruders overload
returned an empty list for it, which sized the tower for a placeholder two
filaments. It now answers the way the wx overload does, without reaching
the plater.

Also drop estimate_wipe_tower_size, which has no callers.
2026-09-09 15:45:16 +08:00
Hanif Koh 8df5e5e738 Extract and Unify Wipe Tower Estimation 2026-09-09 15:45:16 +08:00
HanifKohandraistlin7447 4deadc9dce Make Tree-Support Deterministic (#15565)
* Make tree support deterministic without giving up its parallelism

* Break equal-distance ties in the tree support MST by coordinates

* test: cover the determinism this PR fixes

The MST unit tests here cover the tie-break, but the drop_nodes rework
has no test.

Adds two cases to the tree support suite. The thread-scheduling one
slices five configs twice each and compares the support point sequence,
which is what the node ordering moves. The MST tie one pins the branch
diameter and line width that carry Prim's equal-distance ties into the
toolpaths.

slice_with_tree_support takes an optional config list so the second case
can add the tree parameters it needs, and the double-slice comparison is
shared rather than written twice.

Both fail on main without this PR. The first passes from 60d1ceb580, the
second from e148865dd6.

---------

Co-authored-by: raistlin7447 <kris.austin@gmail.com>
2026-09-09 12:33:42 +08:00
Kris Austin 5779274e5b test: cover support interface generation and tree support (#15575) 2026-09-07 18:02:14 -03:00
Rodrigo FaselliandIan Bassi 85dc866425 Spiral Inset infill (spiral-concentric infill) (#15085)
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-09-06 11:36:23 -03:00
Kiss Lorand e8115658e0 Fix overhang fan control when overhang slowdown is enabled (#15158) 2026-09-01 18:07:02 -03:00
SoftFever e342698d8e Update sublayer option check. Add validation warning for gradient mixed filament without sublayer mixing 2026-08-24 15:30:02 +08:00
SoftFever 2b1499a087 clean up comments 2026-08-23 22:43:41 +08:00