* fix tree support brim
* treesupport3d part 1: more diagnostic logging. (todo once things are fixed: remove this / gate it properly)
* make area under Z=0 in rotated slice pipeline not solid
* fix solid Z=0 layer for belt printers
* fix renderer
* clean up logging
* final review pass
# Description
<!--
> 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
<!--
> 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)
Refactor skirt and brim ownership and emission flow
Refactor skirt and brim generation around a common object/group
ownership model.
Skirts and brims are now emitted as a coordinated preamble
(skirt -> brim -> object) instead of being generated and emitted
through multiple independent code paths.
Changes:
- Fix repeated skirt emission caused by the previous skirt state
tracking logic.
- Restore local skirt/brim ordering for per-object skirts in
By Layer mode.
- Emit brims together with their owning object or object group.
- Handle combined brims independently from skirt grouping.
- Handle draft shields through the same ownership model as skirts.
- Fix draft shield generation when skirt height is zero.
- Generate draft shields after brim geometry is known, preventing
draft shields from overlapping brims.
- Reject unsafe grouped per-object skirt configurations in
By Object mode.
- Remove legacy skirt emission paths and state-management
workarounds.
Support brim generation remains unchanged.
Co-authored-by: SoftFever <softfeverever@gmail.com>
The `@FF AD5M 0.25 nozzle` filament variants carried the base profile's
full printer list (AD5M/AD5M Pro/AD5X 0.4/0.6/0.8) instead of the 0.25
nozzle printers. Combined with base profiles that also listed the AD5X
0.4/0.6/0.8 printers already covered by dedicated `@FF AD5X` variants,
multiple presets with the same alias became compatible with the same
printer. The filament combobox keys presets by full name but displays
them by alias, so these surfaced as duplicate entries (e.g. "Flashforge
PLA Silk", "Flashforge ASA Basic" shown twice).
Fix the `compatible_printers` lists (data only, no settings changed):
- Repoint the 15 `@FF AD5M 0.25 nozzle` variants to the actual 0.25
nozzle printers (Adventurer 5M 0.25 + Adventurer 5M Pro 0.25).
- Remove the redundant AD5X 0.4/0.6/0.8 entries from the base profiles
where dedicated AD5X variants already exist.
- Bump Flashforge profile version to 02.04.00.02.
Each affected filament now resolves to exactly one preset per printer,
and the previously uncovered AD5M 0.25 nozzle printers gain coverage.
* Snapmaker U1: add 0.2mm and 0.8mm nozzle profiles
Add machine and process profiles for the Snapmaker U1's 0.2mm and
0.8mm nozzles, and complete the 0.6mm process lineup. Follows the
same data-only pattern used to add the 0.6 / 0.4+0.6 nozzles in
commit afc3756.
The U1 ships with 0.4, 0.4+0.6 and 0.6 nozzle options today; the 0.2
and 0.8 nozzles are supported hardware but have no profiles, so they
cannot be selected. This adds them the Orca-native way: per-nozzle
machine presets plus a model-file dropdown entry, with their process
profiles filtered in via compatible_printers.
Machine (2): lean presets inheriting fdm_U1, mirroring the existing
SM_U1_06 (0.6) preset and overriding only the per-nozzle values;
setting_ids SM_U1_02 / SM_U1_08.
Process (21): 2 per-nozzle commons (fdm_process_U1_0.2_common,
_0.8_common) holding the nozzle line widths, plus 19 profiles
(0.2: 8, 0.6: 6, 0.8: 5) that inherit their per-nozzle common and
carry their own layer height, matching upstream's factoring. The two
0.24 Standard profiles that shared id GP029 are split into
GP029_06_024 / GP029_08_024.
Model dropdown: machine/Snapmaker U1.json nozzle_diameter
"0.4;0.4+0.6;0.6" -> "0.2;0.4;0.4+0.6;0.6;0.8".
Vendor index: register the new presets in Snapmaker.json.
The existing 0.4 / 0.6 / 0.4+0.6 presets resolve identically before
and after. scripts/orca_extra_profile_check.py and the profile
validator both pass.
* chore(profiles): bump Snapmaker vendor version to 02.04.00.04
Bump the Snapmaker vendor config_version so existing installs pick up the new 0.2mm and 0.8mm U1 nozzle profiles. PresetUpdater only re-imports a vendor bundle when the shipped version is strictly greater than the cached one.
---------
Co-authored-by: ni4223 <ni4223@users.noreply.github.com>
K1C: corrige erro 'End of file' ao enviar impressao (start_print)
A K1-family fecha o WebSocket 9999 assim que aceita o comando de iniciar
impressao. O start_print fazia um ws.read() bloqueante logo apos o write, que
estourava 'End of file [asio.misc:2]' e era reportado como erro -- embora a
impressao ja tivesse iniciado (o comando e entregue no write). Torna o read e o
close best-effort (overloads com error_code), eliminando o falso erro. Mesmo
padrao ja usado em feed_filament; cobre os caminhos single-color e multicor.
The Cartesian designed-view preview over-extended the toolpaths past the model
shell by a height-proportional amount (up to ~20mm tall parts), most visibly on
long multi-part prints; compact parts like a calibration cube looked fine.
Two coupled causes:
- Belt start G-code that primes with a Z advance and a 'G92 Z0' reset leaves a
constant machine-Z origin in the GCodeProcessor, so move positions are stored as
gcode_Z + origin. The linear back-transform mixes that constant with the
gantry-Y term, leaving a per-move designed-Y error that min-corner anchoring
cannot cancel when an elevated move (e.g. a bridge) happens to cancel it at the
bbox minimum. Expose GCodeProcessorResult::belt_z_origin (the m_origin[Z] left by
the start G-code) and subtract it before the back-transform.
- Elevated features (bridges/overhangs) are mis-mapped by the linear inverse to
outside the model body; build the anchor bbox only from moves within model_bb +/-
10mm, with a fallback to the full bbox when the clip would drop the bulk (object
placed away from the belt entry) so the gross-offset case still anchors.
Preview-only; G-code output is unchanged.
The belt designed (upright) preview back-transforms the machine-frame G-code
into model space with the linear belt inverse. That inverse recovers the
print's shape and orientation, but not the per-object placement/lift
translation: the object's position on the belt, the BeltSliceStrategy min-Z
lift, and the centering pre-translate are applied OUTSIDE
build_forward_transform() (see PrintObjectSlice.cpp), so its linear inverse
cannot undo them. The result was a constant offset (~20 mm on the belt-advance
axis) of the toolpaths from the model shell, on every model.
Recover the missing translation generally — independent of the offset's exact
source or the axis remap — by anchoring the back-transformed object body
(extrusions on layer_id >= 1, i.e. excluding the layer-0 prime/skirt) onto the
upright model bounding box, the same space the shells render in, and folding
that translation into the belt inverse before converting to libvgcode.
Replaces the previous Y=0 anchoring in LibVGCodeWrapper, which pinned the
toolpaths to the belt entry rather than to the model and so left the offset in
place for any object not sitting at the origin.
On a belt printer the emitted G-code is in the machine frame (45-deg sheared,
axis-remapped, scaled), so the toolpath preview shows the print as a sheared
slab floating off the bed. Map each toolpath vertex back to model/Cartesian
space for the "designed" view.
The back-transform is the inverse of the full G-code forward pipeline
(BeltGCodeWriter::to_machine_coords):
model = [BeltForward^-1 if !gcode_back_transform] . AxisRemap^-1 . MachineFrame^-1
built from config, so it handles any rotation / shear / scale / axis-remap
combination, not just plain 45-deg belt slicing. Computed in load_as_gcode()
from print.config() and applied per-vertex inside libvgcode::convert (display
position only; layer_id, times and the volumetric/flow math keep the raw
machine values, so the layer slider and stats are unaffected).
- Toggle with the existing "Show designed view" checkbox / hotkey B; off shows
the raw machine-frame G-code (useful for debugging the transform itself).
Defaults to on.
- Belt printers skip the same-result-id load cache so the upright view applies
and the toggle takes effect even when the G-code is unchanged.
- The object extrusions (layer_id >= 1) are anchored to the belt entry to drop
the constant machine-origin offset (start-G-code belt advance) that the linear
back-transform alone does not capture; start-G-code prime lines are excluded
so they don't steal the anchor.
Several Artillery and Flashforge machine profiles set the first-layer nozzle temperature with M104 (set, no wait) immediately before the purge/prime line. The purge then runs before the nozzle reaches temperature, so filament is extruded through a nozzle that is not yet hot enough to melt it. Changed M104 to M109 so the printer waits for the target temperature before purging.
Affected profiles:
- Artillery Sidewinder X3 Plus / X3 Pro / X4 Plus / X4 Pro (0.4 nozzle)
- Flashforge AD5X (0.25/0.4/0.6/0.8)
- Flashforge Adventurer 5M / 5M Pro (0.25/0.8 overrides + shared fdm_adventurer5m_common, which also covers the 0.4/0.6 variants via inheritance)
Refs #4337
Build the Linux AppImage for ARM64 (aarch64) alongside x86_64: the Linux CI
job now matrixes over both architectures, with arch-aware deps caching and
artifact/asset names (amd64 keeps its existing names). The aarch64 AppImage is
published to the nightly and release pages like the x86_64 one.
Run the unit-test suite on the aarch64 runner (faster GitHub arm runner); the
tests are built on that leg. Self-hosted keeps tests on the amd64 server.
* fix(libnest2d): skip the excluded-region alignment pass when there are none
NfpPlacer::finalAlign(), run from clearItems() and the destructor, always
ran the "find a best position inside the NFP of fixed items" pass even when
no items are fixed. With nothing to avoid, calcnfp() computes the inner-fit
NFP of the pile and can feed clipper a coordinate outside its allowed range.
On Linux/clang the value stays in range so it went unnoticed; on MSVC the
clipper "Coordinate outside allowed range" exception escapes the noexcept
destructor and aborts the process (exit 0xC0000409).
Build the excluded set up front and only run the pass when it is non-empty.
The block exists solely to keep the pile clear of fixed items (excluded
regions / wipe tower), so it is a no-op when there are none and the
wipe-tower behaviour is unchanged.
* test(libnest2d): remove dead nesting tests and split the suite by feature
Seven of the suite's hidden [.] test cases drove code paths Orca abandoned
at the BambuStudio fork: BottomLeftPlacer (used nowhere in src/) and the
stock default NfpPlacer backend, which returns zero bins in Orca. They have
been red since the fork and are never registered with ctest. Remove them.
Split the 1,000-line libnest2d_tests_main.cpp into per-feature files, per the
repo convention, sharing a header for the no-fit-polygon backend setup that
every translation unit must agree on (ODR):
libnest2d_tests.cpp Item and nest() basics
test_geometry.cpp geometry primitives
test_nfp.cpp no-fit-polygon machinery
libnest2d_test_utils.hpp shared includes and the NFP backend specialisation
Along the way: drop a debug exportSVG() helper that only wrote a file on test
failure (so the suite never leaves stray assets), convert the deprecated
Catch::Approx to WithinRel/WithinAbs matchers, and give the tests descriptive
names.
* test(libnest2d): add NfpPlacer unit tests
NfpPlacer is the placement engine the arranger drives, but the suite only
covered the geometry primitives. Add a fixture and five tests that exercise
pack()/accept() directly: a single item lands in the bin, an oversized item
is rejected, the first item is seeded for every starting point, many items
pack without overlap, and the rotation candidates are searched. This lifts
nfpplacer.hpp line coverage from 42% to 87% in the libnest2d suite.
* test(libslic3r): add arrangement::arrange() integration coverage
The libnest2d suite cannot reach Orca's real nesting entry point because it
does not link libslic3r. Add test_arrange.cpp driving arrangement::arrange():
items land on the bed and within bounds, do not overlap, are spaced by their
inflation, an oversized item stays unplaced, overflow spills onto virtual beds,
an empty input is a no-op, and the DONT_ALIGN and USER_DEFINED final-alignment
paths are exercised. A self-test guards the overlap check the other cases use.