Follow-up to the feature/OrcaSonar review. Scopes the new behavior to the
OrcaSonar agent, fixes several AMS-sync and lifecycle bugs, and makes the
MQTT tests run in CI. Non-OrcaSonar agents keep their existing behavior.
## Changes
Discovery
- Gate the background SSDP scan to a configured OrcaSonar machine instead of
running for every non-BBL profile; drive discovery on demand from the
machine-select popup and back off idle rounds from 5s to 60s.
- Add NSLocalNetworkUsageDescription and NSBonjourServices to both macOS
Info.plist templates.
AMS sync
- Resolve id-less printer-set trays by material type in get_ams_cobox_infos
and the sidebar badge loop, matching sync_ams_list, so combo arrays and
badges stay aligned.
- Keep a printer-set tray that resolved by type out of the "unknown or
incompatible filaments" dialog.
AMS device UI
- Gate the "Empty" tray classification, and the editable temperature fields,
to the OrcaSonar agent; Bambu keeps "?" and read-only presets.
- Validate AMS material temps on confirm: reject out-of-range values and
min > max before the command is sent.
Storage tab
- Bind the show/hide handler on the panel's ancestors (StoragePanel and
MonitorPanel) and unbind on destruction, so the Bambu file system stops
when the tab is left.
Transport
- Load /etc/ssl/cert.pem on macOS in add_platform_root_certificates, after
set_default_verify_paths.
- Release lifecycle_mutex before start()'s connect wait so stop() can cancel
the attempt and signal completion instead of stalling the UI thread.
Localization
- Add OrcaFilesPanel.cpp to list.txt and regenerate the catalogs.
## Tests
- Un-hide the loopback MockBroker integration tests (ephemeral port, no
network) so ctest registers and runs them.
- Mock broker tracks SUBSCRIBE/UNSUBSCRIBE and delivers push_report only to a
subscribed topic; the reconnect test asserts the re-SUBSCRIBE.
- Add bbl empty-tray cases, an AMS combo-alignment case, and unknowns
assertions to the AMS sync tests.
run_clang_tidy.ps1 had not been run on Windows before.
- Run native commands through Invoke-Quiet. Under
$ErrorActionPreference = "Stop", Windows PowerShell made CMake's
first stderr line fatal, so configure always failed.
- Pass the --line-filter name with native separators. clang-tidy
matches it against the end of the file's native path, so on Windows
every misc-include-cleaner finding was dropped.
- Decode subprocess output as UTF-8 and let stdout replace characters
it cannot encode. A changed line with text such as 打印 crashed the
script under cp1252.
- Check VCToolsInstallDir and WindowsSdkDir in VsDevCmd's output
before applying it, so a failure names the command to run and leaves
the calling shell untouched.
- Log the git_commit_hash_header build, use -LiteralPath for logs, and
hide VsDevCmd's stderr as build_win.bat does.
On every platform, git quotes non-ASCII paths and appends a tab to a
+++ header whose path contains a space, and parse_diff dropped both.
changed_files and the workflow's changed-files step now pass
core.quotePath=false, and parse_diff strips the tab.
* plates-toolbar-scrollbar-size
* update
* filament grouping dialog
* mixed filament list
* Update StepMeshDialog.cpp
* moves plot scrollbar
* fix position of popups
* printer agent combo box width
* match multiline text control background
* add dots to configure button
* also correct label color for multiline input
* side tools connecting text color
* recenter dialog text color
* preferences experimental features
* upgrade panel hyperlink color + right margin
* fix position of + sign on printer selector
* speed control popup
* bbl fan control window
* AMS materials setting
* monitor > ams section
* match background color of multiline text editor on project page
* Fix SwitchButton colors
* bbl camera popup
* BBL > Send print dialog
* Revert "BBL > Send print dialog"
This reverts commit 128e145897.
* Revert "bbl fan control window"
This reverts commit 4a0db62790.
* Revert "bbl camera popup"
This reverts commit e2301e3237.
* Revert "monitor > ams section"
This reverts commit 66e6894eb1.
* Revert "fix position of + sign on printer selector"
This reverts commit 1523ba24c0.
* Revert "upgrade panel hyperlink color + right margin"
This reverts commit 541f2514c5.
* Revert "side tools connecting text color"
This reverts commit a9ab074247.
* Revert "recenter dialog text color"
This reverts commit f4670d32b2.
* Revert "AMS materials setting"
This reverts commit b12827f9b5.
* Revert "Fix SwitchButton colors"
This reverts commit 2d4f1d1fe9.
* match object list background color
* match compare dialog wxDataViewCtrl background color
* fix centering of iconized buttons on linux
* fix compare dialog background color not applied on linux
* edit gcode dialog components background color
* Update Plater.cpp
* fix dev button font size
* Fix scaling issue on SwitchButton while using 150%
* transfer or discard changes dialog wiki label
* "Transfer or Discard changes" / "Unsaved Changes" dialog header color
* object table colors & header spacing
* progress dialog
* fix progressbar look on linux
* fix build
* fix build
* fix centering of iconized icon again
* fix header background color
* revert bbl fan control
* add includes
---------
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
# Description
Follow-up to #15238. A review of the Design tab, and then testing its
Linux AppImage on desktops, turned up UX inconsistencies, kernel bugs
and a crash. This PR fixes them and fills the gaps found along the way.
Everything stays behind `SLIC3R_CAD` and the `enable_cad_feature`
preference. With the preference off, Prepare and Preview behave and
render exactly as before.
The first four commits are Design-tab fixes that landed on the fork
after #15238 and were never sent upstream: the value-field label, the
`GUI.hpp` include, sketch tool batches 9–14 and honest tool messages.
The later commits build on them.
**Interaction: one rule for mouse, Enter and Esc** (charter
`docs/CAD/cad_ux_guidelines.md` §4.2)
- Enter does what ✓ does; Esc does what ✗ does. Esc steps back one level
(value field → gesture → tool → selection) and never deletes anything.
- A click on empty space clears the selection and never applies a
pending operation.
- A right-click with nothing pending opens the offer. The click is
recognised by drift alone; the 200 ms timing rule is gone, since §6.2
forbids timing-dependent gestures.
- The panel's CHAR_HOOK owns Delete, Esc, Ctrl+Z/Y and F, so the
duplicate handlers in `GLCanvas3D` are removed.
- Ctrl+Z/Y work inside a sketch, and Edit ▸ Undo/Redo drive the Design
history while that tab is shown.
- A value the geometry cannot take (zero length, sweep > 360°, …) is
refused inside the field, and the field says why.
**Kernel**
- Solver: tangency and point-on-line pick the correct side;
circle–circle tangency is handled; the partitioned solve maps sentinel
references; constraints that could not be applied are reported instead
of silently dropped.
- Trim, extend, offset and mirror are fixed for arcs and ellipses.
Negative scale is handled, and zero-radius circles no longer produce
geometry.
- Feature → body references resolve by identity, so hiding, reordering
or deleting a feature no longer re-targets later features.
- Hole standards table corrected: inch countersinks are 82°. New threads
use the nominal diameter; new patterns use inclusive spacing. Both are
gated by flags, so existing recipes rebuild unchanged.
- **A closed loop that crosses or folds back is not a region.** Such a
loop passed the closed-loop check and MakeFace, and extruded into an
invalid solid with no caps. `SketchEngine::wires_to_face` now checks the
face (BRepCheck) and fails with a reason; `sketch_loop_defect()` finds
the crossing or cusp exactly, and the sketch tints the loop red and
marks the point.
- Recipe: saves origin, body colours and the loop auto-close setting in
a trailing block; the v4 reader is frozen as `load_flat_v4`; the 3MF
reader caps the entry at 1 GiB and the legacy entry name never overrides
the current one. New fields (`dressup_edges`, the Text parameters,
`revolve_axis_entity`) are appended at the end of the framed recipe, so
existing projects load and rebuild unchanged.
- OCCT failures are caught before `std::exception` in the new code (OCCT
≥ 8).
**Modelling**
- **Several solid edges in one Fillet/Chamfer.** Shift/Ctrl+click adds
or removes edges of the picked body; one feature dresses them all at one
size, every id resolved against the same body. The card and the offer
name the count.
- **Sketch Offset takes the whole outline** the picked curve belongs to,
with a live preview, instead of one segment (on a text outline a segment
is a fraction of a millimetre, so nothing seemed to happen).
- **Revolve about a line of the sketch.** The axis was only the sketch
plane's X or Y axis. It can now be any line of the profile sketch: a
construction centerline (preselected when the sketch has exactly one) or
an edge of the profile. The gizmo draws the axis dashed. A profile on
both sides of the axis is refused with the reason (MakeRevol failed
there with none). Surface Revolve takes the same axes.
**Panel, offer, text**
- The offer menu: its strings are translatable (the generator emits
`L()` markers, and the files are added to `list.txt`); it opens with a
title naming the selection; blocked verbs stay in place, greyed, with
their reason; each verb has one refusal wording.
- Extrude defaults to Join when the profile touches a solid, otherwise
New body. All result menus use one vocabulary: New body / Join / Cut /
Intersect.
- Interference and volume/area reports go to the status line, in
mm³/mm². Delete Body no longer asks for confirmation, since it is
undoable.
- **Text is its own feature** ("Text N" in the tree). Its dialog offers
any installed font (bold, italic) and the height in mm; it is modeless
and opens at the top right of the window, and the outline is drawn in
the view where it will go while typing. Editing the feature reopens the
dialog with its string, font and height. The outlines are saved too, so
the project opens the same on a machine without that font.
- New feature names match the card header (`Extrude 3`) and are
translated. Terminology and units are unified ("Coordinate system",
"Angle (°)").
- The Prepare Sketch/Primitive gizmos can be selected only when the CAD
feature is on.
- MCP: write methods are refused while the tab is busy (including while
the Text dialog is open); a timed-out command never runs; only a socket
is ever unlinked; `fillet`/`chamfer` accept an array of edges.
**Rendering in the Design view**
- Once extruded, a part was hard to read: both lights of the object
shaders sit near the camera, so the sides of a part came out in nearly
the same tone, and nothing marked where one face ends.
- The phong shader gains a studio lighting model, selected by a new
`lighting_model` uniform: a sky/ground hemisphere in world space, a key
light from the upper left and a weak fill, a plastic-like highlight, and
a darker base with a faint sheen toward the silhouette.
`GLCanvas3D::set_studio_lighting()` enables it per canvas; only the
Design canvas does. Every canvas sets the uniform on each use (0 for the
slicer's canvases), so Prepare and Preview render exactly as before.
- Every B-rep edge of a body is drawn as a 2 px dark line, depth tested
and pulled a few pixels toward the eye, so it hides behind the faces in
front. Seams of closed surfaces and degenerate edges are left out
(`GeometryEngine::display_edges`).
**Crash fix (Linux AppImage)**
- Drawing anything in a sketch crashed the AppImage: the constraint list
labels were formatted from narrow literals holding `—`, `·` and `°`;
`AppRun` sets `LC_ALL=C`, so wx's conversion returned NULL and
`wxString::Format` dereferenced it. They now go through
`wxString::FromUTF8`, as the panel's other non-ASCII literals already
do.
Docs updated to describe the design as it now stands: `design_tab.md`,
`interaction-model.md` and the portability note.
No change to slicing, profiles or presets. Existing 3MF recipes load and
rebuild as before: the v3/v4/v5 fixture tests pass.
# Screenshots/Recordings/Graphs
None attached. The behaviour was checked on the fork's Linux tester
AppImages, driven under Xvfb (see Tests).
## Tests
- `libslic3r_tests` on this branch, rebased on `main` (dc0e26918): 943
of 944 cases pass (1 skipped), 79,733 assertions. Linux, system OCCT.
- New or updated cases cover: the solver side and tangency fixes;
trim/offset/mirror on arcs and ellipses; body identity across history
edits; datum remapping, expressions, bindable fields; circular pattern,
hole standards, threads; the round trip of colours, origin and
auto-close; `body_touching_sketch`; multi-edge fillet/chamfer and its
save/load; the crossing/cusp loop analysis and the extrude refusal; the
Text parameters' save/load; `display_edges` on box, cylinder and cone;
revolve about a centerline, about the profile's own edge, refused
through the profile, stale axis index, axis save/load. The
truncated-recipe test accounts for every new tail field.
- All touched GUI translation units compile with GCC, and with clang
`-fsyntax-only` under the macOS job's warning flags. The modified
shaders pass `glslangValidator`.
- `gen_offer_table.py --check` passes, and `xgettext` + `msgfmt
--check-format` are clean on the CAD sources.
- On the fork's Linux tester AppImages (same code on `cad-mainline`),
driven headless:
- drawing lines and rounded rectangles no longer crashes;
- Offset on one side of a rectangle selects and previews the whole
outline; Enter adds it;
- Text: the dialog opens at the top right, "Text N" appears in the tree
and the outline in the view while typing; double-clicking the feature
reopens it and a new string redraws in place;
- a block with a through hole and fillets: faces separate by
orientation, fillets shade round, edges are drawn and hidden behind the
part;
- a half-profile beside a construction centerline: Revolve preselects
the centerline, shows the axis dashed and builds the expected tube
(4000π mm³).
- **Not verified by hand:** multi-edge selection and the red loop
marking; Windows and macOS were not run.
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
## Summary
Adds the remaining OrcaPrinterAgent work on top of feature/OrcaSonar:
connector capability gating, AMS filament mapping, and the printer
Storage tab. Contains no changes to the other printer agents (Moonraker,
Qidi, Snapmaker, BBL, Creality) — that refactor belongs to its own
branch.
## Changes
Capability gating (IPrinterAgent, OrcaPrinterAgent)
• Parse supported_features, capabilities.protocol.features, and
supported_commands from get_capabilities, including replies without a
flags block.
• Add supports_command, supports_feature, and uses_filament_mapping
queries with defaults that preserve existing agent behavior.
• Gate macro-backed AMS commands on fms plus the advertised command, and
slot metadata writes on filament_slots. Unknown capability means not
supported.
## AMS filament mapping
• Serialize ams_mapping2 into print.gcode_file.filament_mapping, keyed
by array position, dropping {255,255}; omit when empty so unmapped
prints stay byte-identical.
• Refuse a mapped print visibly until the correlation flag and
filament_mapping capability are satisfied, and refuse partially mapped
prints with an unmapped used filament. The GUI predicate shares the
serializer's definition.
• Resolve printer-set trays to the matching Generic preset by material
type and color; skip forced external-spool selection on printers without
an AMS.
• start_local_print_with_record returns non-success so PrintJob falls
back to start_print.
## AMS device UI on non-Bambu agents
• Resolve the printer model from the agent model id or selected profile
so the AMS Materials Setting dropdown and Confirm button work;
third-party trays keep editable temps.
• Render explicitly-empty trays as "Empty" via a wire-derived is_empty,
keeping the slot editable.
• Hide flow-dynamics K/N controls for non-Bambu agents, leaving Bambu
behavior unchanged.
## Storage tab (printer G-code files)
• New IPrinterAgent file APIs — list_printer_files,
get_printer_file_thumbnail, delete_printer_file,
get_printer_file_metadata — with ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED
defaults.
• NetworkAgent forwards to the bound agent; OrcaPrinterAgent implements
them against /server/files.
• New StoragePanel / OrcaFilesPanel and a Printer/ file-grid abstraction
(IFileGridModel, RemoteFileGridModel, BambuFileGridModel).
## Tests
Covers serializer keying/omission, GUI/agent gate agreement, payload
shape, capability parsing and per-command AMS gating, model resolution,
empty-tray classification, and AMS sync.
The only use of Slic3r::create_thread in this file sits behind
!BBL_RELEASE_TO_PUBLIC && __WINDOWS__, so the include looked unused in
every configuration CI builds. Windows Debug and RelWithDebInfo builds
failed without it.
A Linux job configures without the precompiled header and runs clang-tidy over the C++ lines a pull request changes. The only check for now is misc-include-cleaner for missing includes; .clang-tidy is where further checks get enabled.
scripts/run_clang_tidy.sh (Linux, macOS) and scripts/run_clang_tidy.ps1 (Windows) run the same check locally: the same configure, the clang-tidy version pinned in scripts/clang_tidy_requirements.txt, and the same comparison against OrcaSlicer's main. They offer to install what is missing, or print the command to do it by hand.
Resolve the filament list's printer model from the agent-reported model id or the selected printer profile, so the AMS Materials Setting dropdown and its Confirm button work on OrcaSonar. Third-party trays pre-fill and allow editing their temps, and the popup's initial selection no longer overwrites them.
Render explicitly-empty trays as "Empty" instead of "?" using a wire-derived DevAmsTray::is_empty, while keeping the slot editable.
Hide the flow-dynamics K/N controls for non-Bambu agents — tile, dialog, validation and sends — with Bambu behavior unchanged.
Tests cover model resolution, the K/N gate and empty-tray classification.
Drop the index-correlation gate so mapped prints are gated only on the filament_mapping capability
Resolve AMS trays set on the printer UI to the matching Generic preset using their material type and color
Skip the forced external-spool selection on printers without an AMS and add coverage for the mapping gates
Parse connector-scope capabilities from get_capabilities: supported_features, capabilities.protocol.features and supported_commands are read for orca devices even when the reply has no flags block, reset before each parse, and left untouched for Bambu.
Gate macro-backed AMS commands on fms plus the advertised command (change filament, select tray, control, user settings, RFID, drying stop); gate slot metadata writes on filament_slots. Unknown capability is not support.
Serialize PrintParams::ams_mapping2 into print.gcode_file.filament_mapping with the array position as filament_index and {255,255} dropped. The field is omitted when empty, so an unmapped print stays byte-identical. A mapped print is refused visibly while ORCA_FILAMENT_MAPPING_CORRELATION_VERIFIED is false or the connector did not advertise filament_mapping; the GUI predicate shares the serializer's definition so both gates agree. Refuse a partially mapped print that leaves a used filament without a target.
Return a non-success result from start_local_print_with_record so PrintJob falls back to start_print instead of treating an unsent print as success.
Tests cover serializer keying and omission, GUI/agent gate agreement, payload shape, the with_record result, capability parsing, and the per-command AMS gate.
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced
Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes.
clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer.
* Remove Unused Project Includes From Files With Platform-Specific Code
A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block.
* Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass
The platform-file pass treated pchheader.hpp as an ordinary header and
emptied it, and left GUI_Preview.hpp and 14 other files relying on
headers they no longer reached directly.
* Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call
* Include Headers That Files Reached Through Ones the Cleanup Removed
* Drop Includes Duplicated by the Cleanup or by Main's Own Additions
* Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
The Design view drew sinking outlines by looking up its bodies in the
plate's model, reading past the end of an object's volumes once a body
was committed. The Design canvas no longer draws sinking outlines.
Merged by /bot merge on behalf of @peachismomo (id 52488812).
Grants: resources/profiles/OrcaFilamentLibrary/filament/Elegoo, resources/profiles/OrcaFilamentLibrary.json, resources/profiles/Elegoo, resources/profiles/Elegoo.json
Head: 00276bf8ee
Commit to Plate now sends all visible bodies to Prepare as one object with a
part per body, so their relative placement survives. A dropdown beside the
button switches to Commit to Plate (as bodies), the previous one-object-per-body
behaviour, and the choice is remembered.
GLGizmoSlaSupports, GLGizmoHollow, GLGizmoFaceDetector, GLGizmoText and GLGizmoAdvancedCut were already left out of the build, and GLGizmos.hpp, the only header including some of them, had no includers. VoxelizeCSGMesh.hpp uses types that no longer exist, SLA/bicubic.h does not compile, and Utils/ProfileDescription.hpp is included nowhere. Their CMake and gettext source-list entries go with them.