They now sit above the features' framed list as fixed view switches:
a click no longer selects them, they stay put while the features scroll,
their eyes line up with the features' eyes, and their labels dim when
hidden. Ctrl+Shift+O toggles the Origin from the keyboard, as
Ctrl+Shift+B does the Bed. The test script's position for the first
feature row is calculated, not measured, and needs re-measuring on the
test setup.
The bed's show/hide state is now remembered across sessions like the Origin
row's, shown by default. The GUI ladder's ribbon x-coordinates are shifted by
the removed checkbox's derived width and still need re-measuring on the rig.
Sketch on a picked flat face or reference plane opens the sketch on it at once. With nothing
picked it no longer enters sketch mode: the reference planes and axes come up, and the plane or
flat face clicked next opens the sketch and puts them away. Esc or Cancel leaves without one.
A picked plane is used up by the sketch on it and dropped by Esc or a click on nothing, the plane
prompt is no longer replaced by a stale tool hint, and clicking the face a sketch was just
cancelled on picks that face again rather than the whole body.
Esc and Cancel now put the body back, and Confirm keeps the new position. A click off the
gizmo only moves the camera and no longer leaves the Move card and its buttons dead. Starting
another edit or a rebuild keeps the position, and undo is refused until the Move is confirmed
or cancelled.
The XY, XZ and YZ planes no longer cross through the bed. Each is a small square in its axis
colour, set off from the axes into the corner that faces the default front view, with its name
written in the plane. Dash-dot axes run between the squares and replace the bed's axis triad
while they show. Hovering a plane greys it and selecting one makes it solid, and picking a
solid face now clears a previously picked plane.
Grabbing an arrow anywhere along its length snapped the body's centre to that point as soon
as the mouse moved. The body now moves by how far the cursor travels from where the arrow
was grabbed, including when it is grabbed while looking straight down the axis.
The XY/XZ/YZ planes are cut along each other and drawn back to front, with
lines along every crossing, and their fills are strong enough for the order
to show. Before, they blended into one grey smear and were too pale to work with.
In the Design tab the button always swung the camera to the plate view and framed the whole
bed, whatever was selected: the tab's picks and sketches are neither the canvas's selection
nor its volumes. It now frames the selected faces, body, edges, vertex, sketch region or
sketch entities, and with nothing selected everything on show — the visible bodies, the
feature preview and the sketches — keeping the current view direction. An empty tab still
frames the bed as before.
The line started at a fixed inset scaled like the ImGui style, while the navigator and the
round canvas buttons scale with the monitor's DPI on Windows, so at 150% the buttons covered
its first words. It now starts past the edge the canvas reports for that corner.
Panning or orbiting with a right-drag no longer ends the polyline chain or drops
the point already placed. Only a right-click that doesn't move does. In the
Touchpad camera style, Alt+move and Shift+move now orbit and pan even while a
draw tool is armed.
The bodies now always draw over the preview on every face a feature leaves unchanged, for
all features. Since a hole's cut sits inside the body, the Hole preview now hides the
bodies and shows the result alone, as Fillet/Chamfer and Draft do.
# 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)
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.
* 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.
Selections are drawn as opaque faces in the selection colour with a cased outline instead of a
translucent tint over the body, so they read on a body of any colour. Selecting a Feature tree
row lights the faces that feature made rather than its whole body, which also makes fillet and
chamfer rows highlight again.