Commit Graph
32300 Commits
Author SHA1 Message Date
packerlschupfer d59155b27f Moonraker: pass print=true in upload — fix Upload & Print race (fixes #14945) (#15032)
* Moonraker: pass print=true in upload — fixes Upload & Print race with power-on-upload

Closes #14945.

Upload & Print on the Moonraker (Klipper) host type failed with
HTTP 503 "Klippy Host not connected" on any printer that Moonraker
powers up in response to an upload (the [power] on_when_upload_queued
feature). The file landed on disk, the print never started, and the
user hit an error dialog.

Root cause: after POST /server/files/upload succeeds we immediately
fire POST /printer/print/start. On a cold printer that Moonraker just
powered up, Klippy is still coming up when /printer/print/start
arrives, so Moonraker returns 503.

Fix: add `print=true` to the upload multipart form. Moonraker's own
upload endpoint queues the print inside the upload response — and
when a [power] device with on_when_upload_queued is configured, it
powers the printer on and waits for Klippy READY before starting.
That's the whole point of the power-on-upload feature; our second
POST was defeating it.

Also read `result.print_started` from the upload response — when
true, skip our explicit /printer/print/start (Moonraker handled it);
when false (older Moonraker or buddy-fork that ignores the print
flag), fall back to the explicit call so the existing behaviour is
preserved for those servers.

Reporter and root-cause identification: @RubenOllesch.

(cherry picked from commit bd442155ba)

* Moonraker: treat print_queued as Moonraker owning the print

Reading only result.print_started missed the exact case this PR set out to
fix. Moonraker's upload response carries two flags:

    print_started : it began the print immediately
    print_queued  : it accepted the job but has not started it yet

The power-on path (`[power] on_when_upload_queued`) is the second one:
Moonraker queues the job, powers the printer up and waits for Klippy to
report READY, so it answers print_started=false, print_queued=true.

With only print_started read, moonraker_started_print stayed false, the
fallback fired, and our explicit /printer/print/start hit the same not-ready
Klippy that produced the original 503 — i.e. the fix did not fix #14945 for
the configuration that reported it.

Verified the response schema against Moonraker v0.11.0 (API 1.5.0); an
upload with print=true on a ready printer returns:

    {"action": "create_file", "item": {...},
     "print_started": true, "print_queued": false}

Both fields are present, so reading print_queued is safe on this version and
the `false` default keeps older hosts on the existing fallback path.

Caught by @raistlin7447 in review of #15032; the fix is their suggestion.

(cherry picked from commit 43e8eff003)

* Moonraker: read the upload reply's fields at top level

Moonraker's FileUploadHandler writes the upload result straight to the
response instead of wrapping it in {"result": ...} like the endpoints
registered through register_endpoint. item.path, print_started and
print_queued are therefore top-level keys. Reading them under result.
silently fell back to the local filename and to "not started", so the
explicit /printer/print/start still ran after every upload.

Also correct the comments on when Moonraker queues a job instead of
starting it, and on what it renames on upload.
2026-10-10 09:27:05 -03:00
SoftFever 640dfad6e9 List IDEX/IQEX parallel printing in the README's main features 2026-10-10 19:11:57 +08:00
SoftFever 0a9e7f33e1 Link the IDEX/IQEX settings to their wiki sections 2026-10-10 19:09:14 +08:00
SoftFever 74493429fd Name extruders in the unsaved changes dialog like the printer tabs 2026-10-10 15:02:16 +08:00
Clifford GarwoodandClaude Opus 5.5 2ede6d1631 Arrange every IDEX/IQEX plate inside its own primary zone
Arrange read the zones of the selected plate only and applied them to
every bed it packed. Arranging all plates with a plate in Primary
selected spread a parallel plate's parts across its whole bed, and with
a parallel plate selected, a Primary plate's parts were squeezed into
the zone. Arranging a single plate other than the first also ignored its
collision strips: they were tagged with the plate's index, while the
plate packs into the arranger's bed 0.

The IDEX/IQEX constraints now live in ImexArranger (IMEXArrange), and
ArrangeJob only snapshots each plate's zones on the main thread and
calls it:
- When every bed, plates the arrange may add included, has the same
  primary zone, the bed shape is that zone, so parts stay centered in it.
- Otherwise each plate in a parallel mode fences off the rest of its bed
  with fixed items on its own bed, and its parts are then arranged again
  inside the zone, so they sit centered rather than piled against the
  zone edge nearest the bed's center. Plates in Primary keep the whole
  bed, and plates the arrange adds take the process preset's mode.
- Zone edges inside the bed get the bed's own edge margin, and strips
  also keep room for the brim.
- A part too big for its zone, which libnest2d's first-fit retry places
  across the fixed items, is left unarranged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:44:42 -04:00
Clifford GarwoodandClaude Opus 5.5 8b5280098f Merge upstream main: center of mass markers, adaptive TPMS, texture bake color mixing, post-processing preview fix, GLEW/OpenCSG removal
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:44:42 -04:00
SoftFever e4142db820 Let texture bakes create a chosen number of mixed colours (#16320)
# Description

Follow-up to #16242, which turned texture colour mixes into mixed
filament slots but created a slot for every possible mix, even when only
previewing. A new Mixed colors setting (default 8) caps how many mixed
filaments a bake adds. They are picked from the texture's own colours,
and only the ones the bake actually paints with are created. Previews no
longer touch the project's filaments, both previews show a mix in the
colour its slot will have, and the bake paints each mix with the slot it
got, which went wrong whenever the project already held mixed slots.

It also improves the colour preview: the green paint highlight no longer
covers the colours, and the colours a bake writes stay visible in the
gizmo.

Only texture displacement changes. Models without a colour layer behave
as before, and there is no change to project or profile formats.

# Screenshots/Recordings/Graphs

**Before**



https://github.com/user-attachments/assets/554a0d0d-cd9f-4095-840e-ca764dde6d52

**After**



https://github.com/user-attachments/assets/7fe10431-8c3f-4759-bd3f-78b4f7a12fc7



## 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-10-10 12:00:39 +08:00
SoftFever d629922060 Keep the paint highlight off every texture preview between strokes 2026-10-10 11:44:09 +08:00
Kris Austin 4a20168742 Fix loading a multi-toolhead 3MF that has no filament_self_index (#16331) 2026-10-09 22:07:33 -03:00
Kris Austin 1466c0e57f Fix rare hang in mcut mesh booleans (#16330) 2026-10-09 21:55:06 -03:00
yw4z c23ea82ad1 revert extruder term on printer settings and optimize dynamic paddings 2026-10-10 01:17:33 +03:00
Kris Austin cd02116242 ci: replace the Docker tag action with git commands (#16327) 2026-10-09 19:17:16 -03:00
Kris Austin 35bac4cb69 Remove unused OpenCSG, GLEW and GLU dependencies (#16318) 2026-10-09 16:50:19 -03:00
0f3e8fbf27 Add center of mass markers to Prepare and Preview (#16291)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
Co-authored-by: Kris Austin <kris.austin@gmail.com>
2026-10-09 16:48:48 -03:00
TheLegendTubaGuy 93c6ab93dc Merge branch 'main' into fix/16194-bbl-infill-retraction 2026-10-09 13:57:18 -05:00
SoftFever 901b14a723 Merge branch 'main' into feature/texture-color-number 2026-10-10 02:46:28 +08:00
SoftFever bef49a330b Keep extruder switch button padding after a DPI change 2026-10-10 02:45:18 +08:00
SoftFever 3755618146 Keep nozzle row label fonts after a DPI change 2026-10-10 02:32:18 +08:00
SoftFever ebaff19754 Merge branch 'main' into extruder-variants-ui-2 2026-10-10 00:42:48 +08:00
Misterff1 b5ef24e7ff Fix regression: Arc Fitting setting for BBL P2S (#16319)
Disable Arc Fitting for BBL P2S
2026-10-10 00:32:46 +08:00
Ian Chua 8585eae816 fix: hide symbols of the bundled static openssl (#16317)
* fix: hide symbols of the bundled static openssl

* fix: hide the bundled static OpenSSL symbols on Linux

* fix: relink _ssl/_hashlib when OpenSSL recipe changes
2026-10-10 00:26:02 +08:00
Lam Wei Lun e72ace164b feat(speed-dial): add plugin page capabilities as actions
Plugin Pages capabilities (top-level notebook tabs) were missing from the Speed Dial because ActionRegistry only ingested Script capabilities.

Enumerate and subscribe to Pages as well. Launching a page action switches the notebook to that page, swapping it into the visible slot first when it lives behind the overflow dropdown.
2026-10-09 23:44:52 +08:00
Ian BassiandRodrigo Faselli b5f5b50157 Adaptive TPMS (#16005)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-10-09 12:36:09 -03:00
e0b35f9ec9 Fix garbled G-code preview when a post-processing script is used (#15005)
* Rebuild the G-code line offsets after post-processing scripts run in place

* Clamp the G-code window reads to the mapped file size

* Add tests for rebuilding the G-code line offsets

* Include <mutex>, <ios> and boost/filesystem/operations.hpp where they are used

* Keep the preview's G-code lines and highlight in step with post-processing scripts

---------

Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-10-09 23:08:43 +08:00
SoftFever b8665b69b0 Merge branch 'main' into feature/texture-color-number 2026-10-09 22:58:10 +08:00
SoftFever 7d141bd691 Keep the texture displacement gizmo out of the assemble view 2026-10-09 22:26:19 +08:00
SoftFever 10787dd59d Show the model's painted colours in the texture displacement gizmo 2026-10-09 22:25:36 +08:00
SoftFever 1fb5da4148 Keep the paint highlight off the texture colour preview between strokes
The green highlight and tint no longer cover a colour preview, and return while a stroke is
painted. The Fast view also keeps the other parts of a multi-part object.
2026-10-09 22:24:40 +08:00
SoftFever 0473da4ef8 Let texture bakes create a chosen number of mixed colours
The new Mixed colors setting caps how many mixed filaments a bake adds. They are picked from the
texture's colours, and only the ones the bake paints with are created. Previewing no longer creates
filament slots, both previews show a mix in its slot's colour, and the bake paints each mix with the
slot it actually got.
2026-10-09 22:23:07 +08:00
Ian Chua eb28daf0fe fix: persist user id so that setting_id doesn't get wiped (#16246) 2026-10-09 21:00:27 +08:00
yw4z 96a1877447 optimize dynamic padding for printer settings dialog 2026-10-09 14:44:55 +03:00
Clifford GarwoodandClaude Opus 5.5 f970a607ae Merge upstream main: belt printing, texture displacement color mixing, 3MF component cycle checks, undo blocked during background jobs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:44:12 -04:00
ExPikaPaka 6ac7ae24a3 Block undo and redo while a background job runs (#16015)
* Block undo and redo while a background job runs

A job is queued against the model as it stands and hands its result back
when it finishes, so undoing underneath it leaves that result landing on
geometry it was never computed for. Undo and redo now wait for the job
and say so, and can_undo()/can_redo() report the same, so the toolbar
and the menu items stay in step.

* Say what to do about the running operation, not just that it blocks

Review feedback: "Stop it first" is the only way out the old text offered,
and stopping is rarely what the user wants. Waiting for the operation to
finish works just as well, so the notification now names both.
2026-10-09 19:26:37 +08:00
ExPikaPaka d55e32fed4 Stop reading a missing AMF metadata type as a string (#16060)
A `<metadata>` element without a `type` attribute makes
`get_attribute()` return nullptr, which was then assigned to a
`std::string` and read as a C string.

Check it the way the sibling metadata handler already does, and stop the
parse.

Regression test in `tests/libslic3r/test_amf.cpp`, a new file: the suite
had no AMF test at all.
2026-10-09 19:25:53 +08:00
SoftFever cd0b529e31 Reject 3MF component references that form a cycle (#16059) 2026-10-09 19:23:20 +08:00
yw4z 81e523e8fb fix m_variant_combo expands vertically 2026-10-09 14:21:52 +03:00
yw4z 86a6841a06 optimize dynamic padding 2026-10-09 14:21:27 +03:00
SoftFever a124b7d2df Reject cyclic 3MF components without running out of memory, however many there are 2026-10-09 19:15:24 +08:00
yw4z f2d3e14f2b fix scaling of multi_extruder and extruder_sync icons on top sizer 2026-10-09 13:59:10 +03:00
yw4z d496ebfd69 Update OG_CustomCtrl.cpp 2026-10-09 13:38:05 +03:00
yw4z b83e4d2890 fix build 2026-10-09 13:33:28 +03:00
yw4z 1b310c1a6d macos placement fix 2026-10-09 13:27:39 +03:00
SoftFever 3d2b219d6a Merge branch 'main' into fix/3mf-component-cycle 2026-10-09 18:14:00 +08:00
ExPikaPaka 62b829d1cb Texture displacement: mix filament colours in the slicer (#16242) 2026-10-09 17:52:35 +08:00
SoftFever 1bddcf3ab6 Retire the separate belt-printer nightly builds (#16308)
# Description

Belt printer support is now part of `main` (#14394), so the separate
`_belt` nightly builds from the `belt-printer` branch are no longer
needed. Nightly builds are published from `main` only again, under their
usual names. The README drops its section on the parallel belt builds
and lists belt printer support among the main features, crediting its
main author, Joseph Robertson (@HarrierPigeon). The nightly release page
has already been updated to match.

No change to slicing output or to main's nightly asset names — CI and
README only.

# Screenshots/Recordings/Graphs

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

## Tests

<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->

<!--
> A guide for users on how to download the artifacts from this PR.
-->

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-10-09 16:25:31 +08:00
SoftFever 18b9b0840f List belt printer support among the README's main features 2026-10-09 16:23:53 +08:00
SoftFever 6026100f83 Stop publishing separate belt-printer nightly builds 2026-10-09 16:23:53 +08:00
TheLegendTubaGuy a3005a96ac Merge branch 'main' into fix/16194-bbl-infill-retraction 2026-10-09 02:33:14 -05:00
SoftFever 489e337bad Merge Belt Printing Into Upstream (#14394)
# Belt printing for OrcaSlicer

This merges the `belt-printer` branch into `main`. It adds support for
conveyor-belt ("infinite Z") printers like the BabyBelt Pro, the
IdeaFormer IR3 V2 and the CR-30 family, along with the things that had
to grow around it: tilted-plane slicing, supports that terminate on the
belt, belt-aware brims, a purge tower that works without a flat bed,
multi-colour belt prints, a preview that shows the part the way it was
designed, and starter profiles.

It has been a long road (the first attempt was #12733 back in March, the
pipeline has been rebuilt twice since) and a lot of people have put work
into it. Credits are at the bottom; please tell me if I've missed
anyone.

Closes #2628, closes #11344, closes #6885, closes #9004, closes #14188.

---

## How belt printing works

Slicers assume the bed sits on the XY plane and layers stack along Z. A
belt printer breaks that in two ways at once: the belt is tilted
(usually 45°) and the axis that advances the belt is the printer's Z, so
the "bed" lives on the XZ plane and is, in principle, infinitely long.

<img width="6360" height="2702" alt="A flat bed vs a tilted belt"
src="https://github.com/user-attachments/assets/3f5542f2-6dab-42bf-9233-f96d863b40c8"
/>

Rather than teach every part of the slicer about tilted beds, the branch
leaves the slicing engine alone and transforms what goes in and what
comes out. The pipeline has five steps.

![printer
pipeline](https://github.com/user-attachments/assets/4d2f9965-f768-4b22-afbe-b3fda05354c4)

<details>
<summary><b>The five steps in detail</b></summary>

### 1. Pre-slice rotation
The mesh is rotated by the belt angle before slicing
(`BeltSliceStrategy`, `BeltTransform`), so that the ordinary horizontal
slicer produces layers that are actually tilted planes relative to the
part. Rotation is about X by default (belt along Y); Y rotation and a Z
lift are supported too. A "global" mode rotates every object about one
common origin, which is what keeps several parts on one belt consistent
with each other.

### 2. Slice
Nothing special. The mesh is rotated, the slicer does what it always
does. This is the reason most of Orca's features (walls, infill, seams,
ironing, painting, …) just work on a belt without belt-specific code.

### 3. Supports
Supports are generated after slicing against a virtual floor: the belt
surface, expressed in the rotated frame (`BeltFloorContext`). Normal,
tree and organic supports all terminate on that plane instead of on Z=0,
and nothing may be generated below it. Painted supports and seams are
transformed with the same `trafo_sliced()` as the layers.

![adding
supports](https://github.com/user-attachments/assets/39c1a858-23e2-48ee-8eb3-7b1abb9be172)

### 4. G-code back-transform
The G-code is rotated back into the model's Cartesian frame
(`BeltBackTransform`). A nice side effect: with step 5 switched off you
can slice at a non-standard angle and print the result on a normal
printer. The first belt-sliced Benchy was printed exactly that way, on a
Sovol SV08.

### 5. Machine frame
The printer doesn't know its bed is tilted. To make straight walls come
out straight, the axes are remapped (the default mapping is X → reversed
X, Y → Z, Z → Y) and the result is sheared and scaled:

```math
\begin{bmatrix} X \\ Y \\ Z \end{bmatrix}
\longrightarrow
\begin{bmatrix} X \\ \dfrac{Y}{\cos\alpha} \\ Z + Y\cdot\tan\alpha \end{bmatrix}
```

This lives in `GCodeWriter` behind a small `MachineKinematics` strategy
(`BeltKinematics` on belts, identity otherwise), so the writer itself
has one code path. The slicing angle and the machine angle can differ if
you want to, e.g. slice at 30° on a 45° machine — mind your nozzle
clearance if you do.

</details>

A short recording of the back-transform from the original PR:


https://github.com/user-attachments/assets/cdb9cc83-711d-48b7-9d86-a014a32c5e8e

---

## What had to change to make it work

Belt mode is gated on the `belt_printer` printer setting; with it off,
every code path below is the old one.

<details>
<summary><b>Slicing and geometry</b></summary>

- `PrintObjectSlice` / `PrintObject`: the rotation, Z lift and
per-object layer-grid shift, plus the invalidation that goes with them.
Modifiers and painted volumes are transformed with the same matrix as
the model.
- `FirstLayerPlane`: "the first layer" on a belt is a band along the
belt, not the first slicing layer. First-layer speed, line width and the
fan band are measured against it.
- `Print::validate`: clearance checks against the gantry instead of the
printable height; skirt, raft, draft shield, the classic prime tower,
arc fitting, spiral vase with brim, and scarf-joint seams are refused or
disabled on belts because each of them either doesn't exist on a belt or
moves the belt the wrong way (a scarf seam starts one layer low, which
on a belt is a 0.28 mm back-step into the previous layer at every seam).
- Z-hop defaults to 0 on belt profiles; a lift on a belt is a belt move.

</details>

<details>
<summary><b>Supports</b></summary>

- `SupportMaterial`, `TreeSupport`, `TreeSupport3D`, `TreeModelVolumes`:
a shared `BeltFloorContext` provides the belt plane; supports clip to
it, extension layers are numbered sequentially, and the first-layer
flange that used to be stamped under everything is gone.
- `build_plate_tilt_x/y` (from #12733) is now derived from the slicing
rotation in `Print::apply`, so GUI and CLI agree; it's capped below 90°.
- Organic supports that reach the belt no longer produce negative flow.

</details>

<details>
<summary><b>Brims (#15155)</b></summary>

A belt first layer is effectively a single line of contact, so a brim
matters more than usual. `BeltBrim` generates per-layer bands along the
belt plus an "apron" ahead of the part, in the object's brim filament.
Two belt-specific settings came with it: **Leading edge brim length**
(more lines on the side printed first) and **Extra brim width** (across
the belt), plus a **Leading edge only** brim type.

<img width="1849" height="1043" alt="belt brim"
src="https://github.com/user-attachments/assets/f963ed8e-53e7-48f8-a495-123cb9ae27f7"
/>

</details>

<details>
<summary><b>Multi-colour: the belt purge tower</b></summary>

The classic wipe tower can't exist on a belt (its G-code bypasses the
transform and it needs a flat bed to stand on). Instead the GUI
generates a long, thin "purge prism" beside the parts, flush with the
far edge of the belt, one per plate (`BeltPurgeTower.cpp`). It is a real
model object, so it is sliced like everything else, and
`Print::_plan_belt_purge` routes every filament change into it via
`flush_into_objects`. It's sized from the flush matrix, split into one
island per simultaneous tool change, snapped onto the parts' layer grid,
cut off after the last colour change and stripped of infill no change
claimed, so what prints is a good deal smaller than the model you see in
Prepare.

</details>

<details>
<summary><b>G-code generation and cooling</b></summary>

- `GCodeWriter` + `MachineKinematics`/`BeltKinematics`: the
back-transform, axis remap, shear and scale, lifts that are belt moves,
and the first-layer travel speed.
- `GCode.cpp` / `BeltGCode`: a belt header (slicing rotation, remaps,
machine tilt) that the preview reads back; it is written outside the
optional header block so printers with a BTT TFT thumbnail still get it.
Exclude-object outlines are emitted in the plate frame.
- `CoolingBuffer`: the "first layers" the fan stays off for are a band
above the belt, marked per extrusion segment by the generator
(`;_BELT_BAND_START/END`) and honoured on every layer.
- `GCodeProcessor`: belt header parsing, start-G-code Z handling, and
height checks that don't compare belt travel against the printable
height.
- `ToolOrdering` / `BeltPurge`: filament changes are detected by
scanning the ordering (an apron layer never carries the first-layer
flag).

</details>

<details>
<summary><b>GUI</b></summary>

- Printer settings tab: the belt group (slicing rotation, angle, global
mode, infinite Y, purge tower, floor settings). The axis remap and
pre-slice remap options are Develop-mode only.
- `ConfigManipulation`: everything that doesn't apply on a belt is
greyed out (skirt, raft, draft shield, the wipe tower group, scarf
seams, …).
- Preview: a "designed view" that back-transforms the toolpaths onto the
model so you see the part upright, with `B` toggling the raw
machine-frame G-code (`GCodeViewer`, `Shortcuts`). The tilt comes from
the belt header, so imported G-code behaves.
- Arrange: parts are packed from the end of the belt that prints first,
colours are grouped into runs so each filament change happens once, the
purge tower's strip and the brim width are reserved, and piles aimed at
an off-centre `best_object_pos` are clamped to the bed (`Arrange.cpp`,
`ArrangeJob.cpp`, one clamp in `libnest2d`).
- `PartPlate`: plate icons stay in the gap between plates on a long,
narrow bed; the plate is open along Y for containment tests on an
infinite-Y belt.
- Calibration: a belt temperature tower (overhang variant) that slices
correctly on a tilt.
- The old tilted-bed rendering in Prepare was dormant and has been
removed; the bed is shown as the slicing pipeline treats it.

</details>

<details>
<summary><b>Config options</b></summary>

Printer: `belt_printer`, `belt_printer_infinite_y`,
`belt_slice_rotation`, `belt_slice_rotation_angle`,
`belt_slice_rotation_global`, `belt_preslice_global`,
`belt_frame_tilt_decouple`, `belt_frame_tilt_angle`,
`belt_support_floor_mode`, `belt_support_floor_offset`,
`belt_support_z_offset_mode`, `enable_belt_purge_tower`,
`first_layer_plane`, `first_layer_plane_offset`,
`first_layer_plane_thickness`, `build_plate_tilt_x/y`,
`gcode_back_transform`, `gcode_remap_x/y/z`, `preslice_remap_x/y/z`,
`preslice_remap_global`.
Process: `belt_purge_tower_width`, `leading_brim_length`,
`extra_brim_width`, brim type `leading_edge_only`. Object:
`belt_purge_tower_object`.

All of them have defaults that leave non-belt printers untouched, and
old `belt_support_floor_mode` values map to `none`.

</details>

<details>
<summary><b>Tests</b></summary>

`tests/libslic3r/test_belt_brim.cpp` and `test_arrange.cpp`, and belt
cases in `fff_print` (`test_print.cpp`, `test_skirt_brim.cpp`,
`test_gcodewriter.cpp`, `test_gcode_processor.cpp`): scarf gate, fan
band, gantry clearance, organic supports on the belt, brim with and
without the purge tower, apron widths, machine mapping at non-45°
angles, first-travel lift, start-G-code Z, arrange clamp and colour
grouping. All three suites pass on Linux, and the tree-wide profile
check passes.

</details>

---

## Starter profiles

Three vendors ship belt profiles. Belt mode needs the printer settings
at **Advanced** or above to show its group.

<img alt="advanced mode"
src="https://github.com/user-attachments/assets/7a519ce5-b3b5-400c-a914-4f208bb577b0"
/>

| Printer | Vendor bundle | Nozzles | Processes | Filaments |
|---|---|---|---|---|
| **Generic Belt Printer** (`MyBeltPrinter`) | Custom | 0.2, 0.4, 0.6,
0.8 | 0.20mm Standard, 0.12mm Fine | library |
| **BabyBelt Pro** (Printcepts) | Printcepts | 0.4 | 0.20mm Standard |
Generic PLA, Generic PETG, eSUN PLA |
| **IdeaFormer IR3 V2** | IdeaFormer | 0.4 | 0.20mm Standard | Generic
PLA, Generic PETG, eSUN PLA |

To set up a printer that isn't listed: pick **Generic Belt Printer**,
set the belt width and length, save the profile, then copy in your
machine's start/end G-code and limits and tune from there.

<img alt="generic belt printer"
src="https://github.com/user-attachments/assets/90134d55-d6fe-4dba-8695-5ea44e78ec2b"
/>

<details>
<summary>BabyBelt Pro</summary>
<img width="2467" height="1392" alt="BabyBelt Pro"
src="https://github.com/user-attachments/assets/2b448cee-339e-43c9-964b-1ee9044044c7"
/>
</details>

---

## Contributions

### @HarrierPigeon
***Majority of design & implementation***

I did most of the work here by myself with AI tools (primarily Claude,
some Codex.)
PRs #12733, #12998, #14385, #15155, #15361, #15156, #15526, #16127

### The @Unlayered3D Team
***Rotation-Mode Pipeline***

The initial version of this sheared the model in the pre-slice pipeline.
Talking with them convinced me to switch to the current
rotate->slice->unrotate-> remap & shear method, which had significant
immediate improvements. Working with them has been a blast.


### @tommasobbianchi
***IdeaFormer IR3V2 Profile, eSUN PLA Tuning, G-Code Render / Preview***

TommyB came in at the perfect time to help keep me motivated and
contributed several things I hadn't had the werewithal to implemement
yet. Without their contributions and encouragement, we wouldn't be here
yet.


### The BabyBelt Community

**BabyBelt Pro** — @rexit1982 for the profile, and @RobMink of
Printcepts for the printer and a lot of patient testing.

**Field reports** — Many members of the BabyBelt community helped,
testing on their machines, providing G-Code and examples of issues, and
encouraging me to keep working on it. Among them:
- @RobMink - creator of the BabyBelt
- @rexit1982 - initial BabyBelt Pro profile, bug hunter
- @shubhracc - found a *lot* of technical bugs
- @NeoDLC - bug hunter
and BabyBelt Discord members who found bugs & gave feedback in no
particular order:
- @horatio42 - also provided a build machine while mine was down
- @HotCubCar - requested belt printer brim support
- Swap_File
- @Nyctelios
- Sup
- @matschi140
- @Rise-Run
- @shooby-dooby

### OrcaSlicer Maintainers
**Generic belt printer** — @SoftFever
**Keeping on top of upstream** @RF47 & @HanifKoh
**Review and fixes** — @HanifKoh (#15685 and the review on this PR).
Among them: plates after the first printed off the bed on belts; painted
supports and seams ignored the belt transform; support generation failed
at a 90° tilt; the object table crashed on the Support column on every
printer because tilt keys were in the per-object tables; apron brims
printed in the wrong filament; `build_plate_tilt` went stale outside the
GUI; the CLI reserved a wipe tower on belts; every G-code file was
treated as belt G-code because the config block carries the angle; tests
didn't compile on Clang/MSVC; plus a long list of smaller clean-ups and
the review questions that led to the clearance check, the header length
fix, the retired floor modes and the removal of the diagnostic logging.

### Additional Thanks

A special thanks to LDO Motors, who provided equipment for validating
multicolor, and my wife, who not only put up with with this obsession,
and the addition of three belt printers to our home, but has encouraged
me to keep going ever since I started this project six months ago.

---

## Known Issues

- The purge prism's first tool is chosen by the shared `ToolOrdering`
logic; on some layouts the print opens on the wrong filament and makes
one extra change at the thin tip of the prism (the "cannot absorb the
full purge volume" warning at a low height).
- Colour grouping in arrange is a soft cost: when the belt is too short
for clean runs, colours overlap rather than spill onto another plate.
- Three OrcaFilamentLibrary filaments still carry `filament_z_hop` 0.4;
belt profiles override it to 0.

Also: slicing at an angle other than the machine's (decoupled frame
tilt) is supported but not something the starter profiles exercise.
2026-10-09 15:24:47 +08:00
Ian Chua 86ff2a9de7 fix: avoid substring denies in audit path keywords (#16243)
## Summary

   Fixes #15944.

   The plugin audit deny-list matched `secret`, `cert`, and
 `conf` as substrings of every path component. This blocked
 valid imports during plugin capability execution, for example
 `numpy/__config__.py`, because `conf` appeared inside the
 module filename.

   This PR changes deny keyword matching to use whole path
 components instead of substring matches. It keeps the
 intended protections for sensitive locations and config
 files, while allowing dependency and stdlib modules whose
 names merely contain those strings.

   ## Changes

   - Match denied path keywords as whole components instead of
 substrings.
   - Keep denying sensitive directory names such as:
     - `secret`
     - `secrets`
     - `cert`
     - `certs`
     - `certificate`
     - `certificates`
     - `conf`
     - `config`
   - Keep denying config files by extension:
     - `.conf`
     - `.ini`
   - Allow legitimate Python module/package paths such as:
     - `numpy/__config__.py`
     - `numpy/_core/_ufunc_config.py`
     - `configparser.py`
     - `sysconfig.py`
     - `logging/config.py`
     - `certifi/cacert.pem`
   - Include the denied target and reason in `PermissionError`
 messages when the audit hook blocks an operation.
   - Remove an unused `<memory>` include from
 `PluginAuditManager.hpp`.

   ## Why

   The previous substring matching caused false positives for
 common dependency and standard-library paths. It also made
 failures hard to diagnose because the Python exception did
 not include the refused path.

   The new behavior is narrower: it blocks sensitive path
 components and config file extensions without treating
 unrelated names like `__config__.py`, `configparser.py`,
 `Conference`, or `Concert` as secrets.

   ## Testing

   - Added/updated unit coverage in
 `tests/slic3rutils/test_plugin_audit.cpp` for:
     - whole-component keyword matches
     - `.conf` / `.ini` blocking
     - case-insensitive matching
     - false-positive paths from #15944

Plugin used for testing:

[orca_audit_numpy_config_repro.py](https://github.com/user-attachments/files/33143848/orca_audit_numpy_config_repro.py)
2026-10-09 15:20:38 +08:00