Code review items (raistlin7447):
1. PrintObject::slice() zeroes m_belt_min_z, m_belt_global_z_offset and
m_belt_global_xy_correction before slicing. They were only written in belt
mode, so a project switched to a normal printer, or whose tilt axis was set
to None, kept the old offsets and shifted the adaptive infill octree and the
organic support layers by them.
2. TreeModelVolumes shifts the support blockers into the raft-offset index
space; a test now pins the index the blocker lands on.
3. The final-alignment clamp in libnest2d is opt-in (NfpPConfig::clamp_to_bin)
and arrange sets it for belt printers only. Printers with an off-centre
best_object_pos keep their alignment; a flat-bed test pins that.
4. The preview's belt view follows the loaded G-code, not the selected printer:
GCodeProcessor carries the file's belt keys (and, for a belt file, its bed)
into export_config_for_render(), and GCodeViewer enables the belt view from
the header tilt.
5. belt_shift_layer_grid() also shifts the cached belt floor and the global Z
offset, so a support-only or brim-only change after the purge-prism snap
matches a fresh slice.
6. update_print_fff_config() resets raft_layers and draft_shield on a belt
printer instead of only greying out the fields Print::validate() rejects.
7. GCodeWriter takes a first-layer point test instead of the FirstLayerPlane;
GCode installs one that measures from the belt surface, like its
extrusions, so the first-layer travel speed and the second-layer
temperature change no longer depend on the gcode_remap_* convention.
8. belt_brim_clip_leading_edge() is exported and called by both the generator
and the test.
9. Both phong.vs shaders use slope.up_direction for the overhang highlight.
The pre-slice and G-code axis remaps are gated on belt_printer through
BeltTransformPipeline::axis_remap_enabled(), so belt keys left in a profile
cannot change a non-belt print.
Tests requested in the review: belt-only keys at non-default values leave
non-belt G-code unchanged; switching a sliced project from belt to non-belt
(and tilt axis None) matches a fresh slice; a support-only change on a belt
purge print matches a fresh slice; non-belt start G-code moves keep the
first-layer Z in the processor; the belt brim's segment count catches a band
emitted twice.
The belt-to-non-belt test exposed an unrelated gap: invalidate_step(posSlice)
re-invalidated posSupportMaterial but not posSimplifySupportPath, so after
any re-slice the regenerated support paths were exported unsimplified.
posSimplifySupportPath is now in that list.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The clang-tidy job on #14394 fails on 129 misc-include-cleaner findings:
the belt sources and tests use std::, Eigen, Point/PrintConfig and
BeltBrim symbols without including the header that provides them, which
only compiled because the precompiled header supplied it. Every include
the job names is added, in each file's existing include style ("../" in
the GCode/ and Support/ subdirectories, quoted libslic3r/ paths in the
GUI and tests). No code changes.
Verified with scripts/clang_tidy_diff.py -p build-tidy --base eb5b9a77b9
(SLIC3R_PCH=OFF compile database, clang-tidy 22.1.8): no findings left.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L6Kg5igmmMU2YLoK6HrsWV
The purge plan snaps every object onto one layer grid after the brim is built;
the per-layer brim bands follow their layers but the apron bands below the
first layer carry their own print_z and were left behind, which is why a brim
was refused next to a purge tower object. The shift now moves them too and the
combination is accepted again.
Drops the [BELT-DEBUG], [BELTRACE], [BELT-CALIB] and [BELT-PREVIEW] log
lines, the SLIC3R_BELT_DIAGNOSTIC_LOG blocks, and the counters and
temporaries that existed only to feed them. Six of the purge tower lines
logged at warning level, which is Orca's default, on every plan. Raised in
Hanif Koh's review of #14394.
ToolOrdering::has_wipe_tower() reads the first layer's flag. On a belt the first layer may
be a brim apron band, which carries neither object nor support and never gets the flag, so
with a brim the purge plan returned early and nothing was purged. Scan the layers for a
change.
Two independent leaks of filament on the belt purge prism, plus the
replan safety net the second one needs.
1. The early-truncation scan bounded itself with the prism's own
toolchanges. ToolOrdering covers the whole print and the prism is a
printed object in it, so the "last toolchange" the scan found was on
the prism's own top layers -- it runs past every model object by
design -- and the truncation cancelled nothing. Bound the scan at the
tallest non-prism object (support layers included; on a belt they can
top the object). On MCTEST5 that was 197 toolchanges over 39.4 mm of
tower that no swap ever needed.
2. On a layer with no toolchange, the prism's entire fill printed as
solid infill in its own filament. Drop the fills no toolchange
claimed, right after the purge marking and before
ensure_perimeters_infills_order() force-overrides whatever is left.
Perimeters stay so the bar keeps a continuous wall. An earlier version
of this deleted the entities and had to be reverted: psWipeTower can
rerun without regenerating infill, and a later tool ordering may claim
what this one did not. The entities are now stashed with their layer,
region and index and put back exactly, the same reversibility contract
layer truncation already had.
3. Both stashes go stale if an object step reruns: make_fills() clears
and regenerates fills over m_layers only, so a stale stash would put
old fills back next to new ones, and truncated layers would keep old
perimeters/fills. Undo the plan's edits at the top of Print::process()
whenever psWipeTower is not done. Every object-step invalidation also
invalidates psWipeTower, so that condition is exactly "some object
step may rerun"; when it is done nothing regenerates and the edits
must stay. This also covers a prism left behind after belt mode is
turned off, which previously stayed truncated forever.
WipingExtrusions::is_entity_overridden() becomes public so the prism can
tell claimed fills from unclaimed ones.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SsuY8Laiyh7q2zPVVKV3HZ