The plate's icons, number and name scale with the plate's depth, but they sit in
the gap to the next plate, which scales with its width. On a long, narrow bed
(a 95 x 500 mm belt) they came out 40 mm wide and ran across the neighbouring
plate. The scale is now also bounded by the gap, which leaves ordinary beds
unchanged.
* Fix CLI Crashes on Malformed Project, Assemble List and No-Input Runs
Four CLI paths indexed vectors without checking their size and crashed
with SIGSEGV on malformed input:
- A project inherits_group whose length is not the filament count plus
the process and printer entries was split by position. It is now
ignored with a warning, as if the project had none.
- An assemble list object with an empty filaments list passed validation
and was then read at index 0. It is now rejected as a config error, as
is a negative filament id.
- --slice N --arrange 1 on a project without plate metadata read the
missing plate data. It now falls back to the plate's own filaments,
like the other plate data reads.
- --assemble with no input model built an object with no volumes. It is
now rejected as invalid parameters.
A tests/cli script covers each case through the binary, since all four
live inline in CLI::run().
* Move the Assemble List Parser into libslic3r
Behaviour-preserving move of the --load-assemble-list JSON parser and
its plate/object structs from the CLI into libslic3r/Format/AssembleList,
so the format can be unit tested. The parser returns its own
AssembleListResult and takes the plate limit as a parameter; CLI::run
maps the result to the same exit codes as before. Every validation rule
and log message is unchanged.
Adds Catch2 coverage of the valid layout and each validation rule.
* Keep the Process and Printer of an inherits_group of the Wrong Length
A project whose inherits_group did not have one entry per filament plus
the process and printer entries was loaded as if it had none. The CLI
then looked for system presets under the names of the user presets,
found none and refused to slice a project that slices on main.
The group is now read as before: the process first, the printer last
and the filaments in between, up to the filament count. A filament
without an entry counts as a system preset. A group with fewer than two
entries is still ignored. The warning stays.
Plater::set_bed_shape read the belt keys from the plater's own config, which
never carries them, so the branch that tilted the bed model, drew the slicing
arrow and plane and switched the build volume to belt mode never ran. The
Prepare view shows the bed as the slicing pipeline treats it, flat; the
gravity arrow from build_plate_tilt stays, as does the preview's belt view,
which takes its angle from the G-code header.
The G-code viewer takes the belt tilt only from the belt header comments, but
they were written inside the header block that is left out when a BTT TFT
thumbnail is configured, so such a printer never got belt view. The comments
are not part of the header block; they go after it, and after the thumbnails
that firmware needs first.
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.
On a belt the parts print in belt order, so every colour change between parts
is a filament change. Arrange packs items in extruder order already, but it
grew the pile around its centre, so the colours ended up interleaved. A belt
print now packs from the leading end of the bed, each row filling across the
belt before the pile advances, and the objective charges an item for every
packed part of another colour it does not fully follow along the belt,
counting the tilted layers that reach cot(angle) * height past a part, so
each colour prints as one run. The direction follows the slicing rotation: a
rotation about X prints toward +Y, one about Y toward -X, and a negative angle
flips it. Packing from the edge also means the brim has to be kept on the
bed: a belt brim is printed brim_width wide for every brim type, so that much
is reserved along every edge (between parts the brims may overlap, as on any
printer).
The purge prism is regenerated from the arranged parts, flush with the far
edge of the bed, yet arrange moved it about like a part and packed parts into
the strip it comes back to. Arrange now skips the prism and reserves its strip
with a fixed virtual item, like a bed exclusion area, whenever the parts use
more than one filament.
The prism's length follows the parts plus a ramp per unit of height; with the
height at its cap that ran 100 mm past the end of a 500 mm belt and the project
could not print. The bar now stops at the plate end, and the purge planner's
existing warning reports what the shortened bar cannot absorb.
Release builds install each vendor as its preset cache alone. The
read-only preset load the CLI uses to resolve an inheriting user preset
passed allow_cache = false to keep caches from being written, which
also stopped them from being read, so every vendor fell back to JSONs
that are not installed and the CLI failed.
The flag now only gates writing: a read-only load reads caches and
writes none. The filament library is also read from its cache whenever
that is all that is installed, so a vendor updated over the air still
resolves against it.
* Refresh a CLI Project's Filament Settings From Their System Presets
The CLI loads a project's printer and process settings as the GUI does,
taking every key the project does not list as changed from the current
system preset, but it kept the stored filament values. A project saved
before a profile update then sliced with old filament values on the
command line and with the current ones in the GUI.
Every project filament that no loaded filament replaces is now resolved
by its system preset name and fed to the filament merge the up-to-date
path already uses, which keeps the keys listed in
different_settings_to_system and maps per-variant values onto the
preset's variants. This covers a plain run, --uptodate without
--uptodate-filaments, and the slots --load-filaments leaves empty. The
merge tells refreshed entries from loaded ones per entry instead of by
the global loaded-filament count, and the entries are kept in slot
order. A project filament saved under a name the presets have since
split per nozzle is resolved through the name conversion the GUI uses,
which PresetBundle now exposes.
* Check the Project Refresh Test's Result Directly
Shellcheck SC2181: test the checker's exit status in the if instead of
reading $? afterwards.
After undo, redo, New Design, a project load, a delete or a reorder, a sketch
profile picked beforehand stayed selected even though it was gone. The
right-click menu then offered "Sketch profile" over an empty design with Create
greyed out. Those operations now clear the selection.
The Confirm button no longer stays greyed in a sketch session after a card whose
preview was invalid has been closed.
Delete and reorder now wait while a sketch or constrain session, the Text dialog,
an Insert placement or the move gizmo is open, instead of editing whichever
feature took its place in the list.
* Save device url in all cases and load printer url after hot-reload finishes
* Recreate web view from scratch as only URL fix seems not robust enough
* Add the same robust browser recreation for WebViewDialog
It should eliminate possible issue with blank Home and other pages
in the same way as Printer page
* Remove redundant fallback leftover
* Fix webview reset state and replay Project info on page reload
The first-show webview reset now runs only on Windows, reloads the last
printer URL and resets the Project page's ready state. The Project tab
replays its 3MF info whenever the page reloads, so it no longer goes
blank after a theme switch or a slow first load. The Device tab no longer
loads an extra time on first open, and the Home tab no longer navigates
twice. NeedsRecreateOnShow() logs is_recreating_gui so one language
switch shows whether the reset ever fires.
* Build plugin pages on first show
A language switch rebuilt every plugin page's browser while the main
window was being recreated, which left plugin tabs blank on Windows.
Plugin pages are now lazy pages, never prebuilt, and are removed left
to right so removing pages never builds one only to destroy it.
A plugin page's script now starts when its tab is first opened;
messages posted before that are dropped.
---------
Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
The sidebar can move to either side, float, be resized, and collapse with
the canvas button or Shift+Tab. Its layout is remembered separately from
Prepare's, starts where Prepare's sidebar is, and View > Reset Window
Layout resets both tabs.
* Add Missing Includes Across src/libslic3r
Every libslic3r source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, with libslic3r headers spelled libslic3r/... so they resolve outside the library's private include paths. MultiMaterialSegmentation.hpp, Support/SupportParameters.hpp and Format/STEP.hpp are made self-contained by hand.
* Make the libslic3r 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. Left out: I18N.hpp, which errors on purpose when included from GUI code, and VoxelizeCSGMesh.hpp and SLA/bicubic.h, which nothing includes and which no longer compile at all.
* Add the Includes Missing From the Hand-Fixed libslic3r Headers
clang-tidy would not edit these headers while they failed to compile on their own, so the first pass skipped them. With the headers now self-contained, a second pass adds the rest.
* Keep Windows Setup Ahead of the Added libslic3r Includes
Print.cpp and Thread.cpp open with a _WIN32 block that has to come first; without the precompiled header, Print.cpp otherwise reaches windows.h through OCCT with NONLS defined and boost/regex fails. OpenVDBUtils.cpp and SLA/SupportTreeBuilder.cpp had includes inside #ifndef NOMINMAX, which libslic3r defines on Windows, 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.
* Re-Add libslic3r Includes After the Clipper2 2.0.1 Migration
Rebasing onto main took main's version of the files the Clipper2 migration rewrote, so their added includes are restored here, along with includes for main's new code. Clipper2's individual headers are now ignored by clang-tidy: they only build the Z variant through clipper2_z.hpp, which defines USINGZ first, so including clipper.core.h and the like directly broke ClipperZUtils.cpp.
* 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.
A page built on first click is now built before it is shown, as the idle
prebuild already does, so its controls are not created inside a visible
window. This takes the Design tab's first open on Windows from ~9 s to ~1 s.
A tool change added from the layer slider switches heads mid-print like a
painted color, but the parallel-mode checks only looked at the filaments of the
plate's objects, support and prime tower. A one-filament plate with a slider
change to a copying head's filament passed them. They now include those tool
changes, as the plate's warning badge already did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the primary and its Span tools print a Span plate's colors; the other
active tools replay them. The multicolor rule never checked where each color
went, so a filament on a copying or mirroring tool, an unused one, or past the
end of the physical extruder map was accepted. It is now refused, and the
message names the tools that print colors and where the map sends the
offending filament.
The plate's warning badge also read the raw physical_extruder_map rather than
the effective one slicing uses, so on printers that set no map it disagreed
with the slicer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three commits: G-code export caches its filament config slot and repeated
option lookups, per-plate bed type overrides follow the printer's multi-bed
support, and the gizmo checkboxes and texture displacement panel get styling
and refresh fixes. No conflicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The name field rebuilt its suggestions in wxEVT_COMBOBOX_DROPDOWN, which
ComboBox sends after it has sized and shown the popup from the items it
already held. With every suggested name taken, the popup opened around an
empty list: a small empty box on GTK, a black one on Windows. The list is now
rebuilt from the field's own mouse-down and double-click, which run ahead of
ComboBox's handlers. With nothing to offer the popup stays closed and the
click focuses the field instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor only replaced an empty name, so a row could be given a name another
row already had. A plate stores its mode by name and find_imex_mode() takes the
first row with it, so the second row was unreachable, and the plate's mode
list repeated the name: left-click stuck on it, or looped without getting back
to Primary.
An edited name that another row already carries, or the reserved Primary name
in any case, is now replaced when the edit is committed: "copy" becomes
"copy 2". The edited row yields, so plates keep resolving to the row they
meant, and tabbing through a field without changing it checks nothing.
Resetting a row to a saved name that another row has since taken does the
same. The plate's mode list comes from imex_plate_mode_choices(), which lists
each name once, so a profile that already has duplicates still cycles.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor took its background from the app's window default, which in dark
mode is a gray the dark-mode walk has no entry for. In dark mode it never
matched the page's palette color, and an editor built in dark mode kept that
gray after a switch to light while the controls inside it changed. It now
takes the page's color, which the walk remaps both ways.
Its labels and G-code text had no color of their own, so on Windows they took
the system's text color, which follows Windows' theme rather than Orca's. They
now start from the page's label and input text colors, which the walk maps
with the page.
The walk also ran the tool tiles' role colors through the palette map, which
turned their labels gray after a theme change. The tiles carry wxBU_AUTODRAW,
the flag it skips, so the role colors stay as set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The remove button drew imex_remove.svg, a redrawn delete.svg, and the help
button drew the mascot question icon. They now use delete and icon_qusetion,
the tip icon the send-print dialog uses, and imex_remove.svg is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Fix gizmo checkbox styling and Texture Displacement resize
Use shared BBL checkboxes in Texture Displacement and restore white toolbar checkmarks so other gizmos keep proper checkbox contrast. Also fix Texture Displacement resizing only after mouse movement by requesting additional frames while its layout is still changing.
* Fix gizmo checkbox styling and Texture Displacement resize
Use shared BBL checkboxes in Texture Displacement and restore white toolbar checkmarks so other gizmos keep proper checkbox contrast. Also fix Texture Displacement resizing only after mouse movement by requesting additional frames while its layout is still changing.
* Update GLGizmoTextureDisplacement.cpp
---------
Co-authored-by: yw4z <ywsyildiz@gmail.com>
The update merged the same upstream commits this branch already carries. Its
GLCanvas3D resolution kept the assembly view painter block after the ghost
render, which section view removed along with the members it calls, so that
tree does not build. This merge keeps the removal; nothing else differs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five commits: a section view for the 3D canvas, a faster G-code preview, user
preset values kept on extruder variants they don't list, debug build CMake
fixes, and a 30 minute timeout on macOS notarization.
Two conflicts, both in GLCanvas3D. The header's were neighboring
declarations, kept from both sides. In the transparent pass, the section view
removed the assemble view's painter block that followed our ghost render;
the ghost render stays where it was, at the end of that pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The band was a second pass over the finished layer that fought the fan commands
the layer pass had already written (overhang, bridge and resume requests). The
generator now marks where each segment enters and leaves the band and the layer
pass treats the band as the strongest fan request, so there is one place that
decides the fan.
The purge plan moves objects onto a common layer grid after the brim bands are
built, so the two cannot share a print. The prime tower setting alone still does
not block a brim. The missing-prism warning now counts the filaments the objects
use, as the GUI does.
notarytool submit --wait has no timeout. On 2026-10-02 it hung for
over 5 hours in a main build. Since #16044 a new push no longer
cancels a running main build, so nothing stopped it and six waiting
main runs were replaced without starting.
Over the last 30 days the step succeeded 206 times, with a median of
4.3 minutes and a maximum of 14.8.
With best_object_pos away from the bed centre the placer packs the pile
inside the bin and then translates it so its centre lands on that point,
without checking that it still fits there. A belt printer aims at the
leading end of the belt (BabyBelt Pro: 0.5, 0.05), so any pile longer than
the 50 mm around that point was pushed past the edge: four 90 mm parts on
the 95 x 500 mm belt ended with one across the edge and one outside while
290 mm of belt stayed free.
The final alignment now stops the pile at the edge of the bin; the items'
inflated boxes leave the object spacing as the margin. A pile that does not
fit along an axis is centred on it, as before.