* claim: #12069
* wip: Sketch preference: a quick double Esc can be kept from finishing the sketch (#12069)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* wip: profile key count includes the new sketch preference (#12069)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #11978
* wip: Parameters filter and completion match the starts of a name's words (#11978)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* wip: describe the Parameters filter's word-start matching in the guide (#11978)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Parameters autocomplete: list word-start matches after substring matches (#11978)
A name matched only by the starts of its words now comes after every name that contains the typed word, so it never pushes an earlier suggestion out of the list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #12208
* wip: Center Point Arc three-click regression test (#12208)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch Center Point Arc: keep the Radius box off the cursor so a click places the start (#12208)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Arc click test: is_dimension is on the constraint's kind
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch value boxes: a box that would sit on the pointer moves beside it (#12208)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #12543
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* wip: Insert Mesh origin option (#12543)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Insert Mesh: name the Move to origin checkbox's handle mesh_units:origin (#12543)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Insert Mesh origin: measure in the active component's frame, first placement when it has no path (#12543)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #12494
* German: call Look At "Senkrecht auf" instead of "Ansehen" (#12494)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* German: the navigation bar's Look At is "Senkrecht auf" too (#12494)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #11057
* Sketch Dimension: the value box stays clear of the pointer when tall or in a small view (#11057)
Place the type-first value box by its drawn size and try the four corners around
the pointer; where none fits, keep the 30 px gap on one axis and slide along the
other, instead of clamping both axes back over the pointer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch Mirror: a curve clicked while the mirror line is active joins the entities (#11700)
With entities preselected, the Mirror window opens on the empty Mirror line field.
A circle clicked then was refused without a word, so it was left out of the mirror.
The commands whose first input is the shared Entities list now take such a pick
there and stay on the input they were on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch modify: candidate stays the active input's pick; clicks fall back to Entities
sketch_modify_ui::candidate again answers only for the active input, so the
Mirror line still refuses curved and external references. The Entities fallback
for a click moved to pick_candidate, which Dialog::candidate_on uses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #4850
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch: test Symmetry of two corners of one rectangle edge about the origin (#4850)
Already fixed on main by #4626; this guards it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8969
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch: Divide Curve places points at equal lengths along curves (#8969)
A new PointAlong constraint holds a point at its share of a curve's
length (measured along the exact curve), so the points follow edits.
sketch.point.divide places them on lines, arcs, circles, ellipses,
splines and conics; trim and break loosen them to point-on-curve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Divide Curve: use the solidcore_record segment and vector types after the layer split
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Divide Curve: exempt sketch.point.divide from kernel cases and show PointAlong glyphs
PointAlong constraints now get a glyph on their point (the midpoint icon),
light their point and curve, and hold an end against Extend like
PointOnCurve does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #8923
* Sketch palette: drag it by its header to move it (#8923)
The palette docks at the right edge as before; its status header now drags it like a
command dialog's title, and it keeps its place for the rest of the session. It stays on
screen and never goes so low that Finish scrolls out of view. A wide dialog docked at
the left no longer shrinks to the sliver left of a palette that was moved there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Dialogs: drop the token the palette's room no longer needs (#8923)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch palette: keep the token binding the dialog still uses after the rebase
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #2398
* Extrude: the distance arrow stops at a parallel face and outlines it (#2398)
While Extrude's distance arrow is dragged, a flat face parallel to the
profile and lying over it takes the distance exactly once the tip comes
within 8 screen points of its plane, and the face is outlined as a hovered
face is. A cut dragged through a block so stops at its far side. Faces
beside the profile don't catch the arrow; Alt/Ctrl (free drag) turns it off.
The distance stays a number in the existing parameter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Extrude face stop: clippy (test-only current, +=)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Extrude face stops: a preference, on by default, keeps the old round steps (#2398)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Extrude face stops: follow world_state returning a Result (#2398)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Extrude face stops: import Vec/Plane from solidcore_record after the layer split
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #2217
* Dialogs: drag a value's label sideways to change it (#2217)
A value row's label (expr_row, hint_row) now scrubs a literal value: about a
hundredth of its size per point of drag, on that step's grid, Shift ten times
finer, Ctrl/Cmd ten times coarser. The unit and decimal mark stay as typed, a
size never turns negative, and expressions and parameters are left alone. The
text changes as if typed, so previews follow and OK still makes one command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Label drag: measure from the press point, cap values, keep scrub kit-private
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9236
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* GPU path tracer: don't rerun a setup that crashed in the driver (#9236)
A driver that takes the process down while it compiles the path tracer
(RADV on an RX 7600) is beyond error scopes and unwind guards. A running
setup now keeps gpu-path-setup.json (its adapter key) in the settings
folder, removed when the setup answers or the app closes normally. A
launch that finds it for the same adapter leaves the setup failed with an
explanation and a Try again button; CPU ray tracing stays available, and
a driver update changes the key and so tries again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9719
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Dynamics: rigid-body solver core with joints, gravity and springs (#9719)
A new L1 crate, solidcraft-dynamics (geom only): rigid bodies in maximal coordinates, joint constraint equations with analytic Jacobians for rigid, revolute, slider, cylindrical, planar and ball joints, gravity, linear spring-dampers and constant loads; the index-1 equations of motion solved through a rank-revealing Schur complement (repeated joint equations are solved, not refused); RK4 and Dormand-Prince 5(4) with position and velocity projection; joint values, rates, reactions and energies at every output sample; caps on bodies, joints, rows, steps and samples; Result errors only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Dynamics: take Vec3 from the record crate after the layer split, refresh the lock file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #8823
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sheet metal: returns on a notched tray close at the corner away from the notch (#8823)
Closing two returns at a corner was refused when either return already lay
over another flange in the flat pattern, even far from that corner. On a tray
with a notch, the walls on either side of the notch's inner corner both unfold
into the notch, so the return on one of them lies over the other there; the
return's opposite convex corner was then left open ("closed, the flanges would
overlap in the flat pattern") and the two returns ran through each other.
A closure is now refused only when it makes the two returns overlap or adds to
what either already shares with another flange in the flat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9274
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Browser: placements start closed (#9274)
A large assembly opened with every placement unfolded, so the browser was a
long list to scroll through. Placements now start closed; opening one shows
its own placements still closed, and closing and reopening it leaves them as
they were. Find in Browser, a pick in the view, Expand All and Collapse All
open and close them as before.
Preferences > Interface > Components start open (browser_components_open)
keeps every placement open from the start, as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Browser: scenarios and the icon audit open placements, which now start closed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Browser: tests that read rows inside placements set the open-placements preference
Three tests added on main since this branch started (joint folders, Features
folder marks, group rename) look at rows inside placements, which now start
closed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <tenbee91@gmail.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #9234
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Colour popover: step buttons, H/S/V fields and recent colours (#9234)
Every colour field of the app opens the same ui_kit popover. It gains:
- step buttons beside each number (R, G, B and the new H, S, V): a press
steps once, holding repeats, for live fine-tuning;
- H (degrees), S and V (percent) fields on the same gamma HSV as the square;
- a row of the last 12 colours picked in any colour field. A colour joins
when an edit is finished; fine-tuning in one opening replaces its entry.
The list is saved with the app's settings (`recent_colors`), hostile
saved entries dropped and the list capped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Recent colours: keep the shared list outside ui_kit, crate-visible only (#9234)
The store and the per-frame sync with the saved settings move to
crate::recent_colors; the ui_kit colour popover only shows the list and
adds finished picks. No plain pub escape from the gallery's ui_kit rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8706
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Properties: measure faster, show progress, and stop when closed (#8706)
Properties on a large assembly measured every placed copy of every body
afresh (transform plus three fine tessellations each), so it took minutes.
#5203 (in #8103) already moved the measurement beside the window; this
builds on it.
- A rigid placement reuses the body's own cached measurement: volume, area
and counts unchanged, centre placed, box from the placed corners (quarter
turns) or from the body's shared mesh placed (other turns). Scaled or
mirrored placements are still measured as placed.
- Bodies are grouped by component once and the subtree traversal groups
occurrences by parent once (both were quadratic).
- The measurement beside the window is watched by a Progress: the card
says "Measuring... n of N bodies" with a bar, and closing it (or
switching designs) cancels the worker at its next body instead of
leaving it running.
- component.properties and occurrence.properties are answered on a copy for
control-channel requests too, as inspect.measure is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Properties: count the measuring work instead of timing it in the reuse test (#8706)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A switch between design tabs cancels the open dialog and tool of the design
left and shows MODEL. With the new Interface preference "Keep dialogs and
tools open when switching designs" (keep_work_on_tab_switch, off by default)
each tab keeps its dialog (with its picks and values), its editing state, its
tool and its toolbar tab, and has them back when it is shown again. A feature
still computing after OK is cancelled as before. A feature edit's saved source
revision follows the view refresh of the switch, so its Cancel still restores
the history.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9715
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Assemblies: mass, centre of mass and inertia per occurrence and rigid group (#9715)
assembly.mass_properties (and Session::mass_properties) gives, for every
occurrence and every rigidly-joined group, mass (kg), centre of mass (mm) and
the inertia tensor about it in world and frame axes (kg mm2), the input
the multibody dynamics work needs. Bodies are measured as Properties
measures them (kernel volume and centre, mesh gyration), once per body,
then moved by each placement and combined by the parallel-axis theorem.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9619
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Settings: edit an added AI agent (#9619)
Agents you added in Preferences > AI get an Edit button between Test and
Remove. It reopens the Add agent dialog filled with the agent's name and
command, or its protocol, preset, endpoint, model and request timeout, and
Save changes the entry in place: same id, permission override and
always-allowed tools. The stored key is never read back into the dialog;
an empty key field keeps it (still only sent to HTTPS or this computer),
a new key replaces it. The control channel gets `edit_dialog`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9258
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch: paste sketch geometry copied in another design (#9258)
Sketch geometry copied or cut in a sketch (sketch.copy / sketch.cut) now pastes into a sketch of another open design with Ctrl+V or the context menu, at the cursor or at the copied coordinates, with the constraints and dimensions among it. A dimension whose expression names the copied design's parameters keeps its value, in its unit; a text keeps its numbers. SketchClip::for_another_design prepares the clipboard; the app keeps the last sketch copy beside the cross-design body/component copy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9293
* Assistant: a sign-in confirmed in one tab holds in every tab (#9293)
The latest sign-in evidence per agent is window state: keep it across
tab switches, new tabs and replaced designs instead of resetting it with
the tab's conversation, so a new tab no longer marks the agent as signed
out when discovery's login probe is older than the chat's proof.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9641
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Insert SVG: say why a drawing has nothing to import, and read UTF-16 files (#9641)
An SVG with nothing SolidCraft draws (only an embedded picture, shapes
pulled from another file with <use>, or not an SVG at all) was refused with
"invalid parameters for sketch.insert_svg: the drawing has no geometry
SolidCraft reads". It now names the file and says why, pointing pictures at
Insert Canvas and Canvas to Sketch. SVG files with a byte-order mark or in
UTF-16 now read, and a gzip-compressed (.svgz) file is refused clearly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Insert SVG: decode UTF-16 with as_chunks (clippy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9041
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Render: start the GPU path tracer setup only when the GPU image method is chosen (#9041)
Entering the Render workspace started the GPU path tracer setup even with
the default Raster image method. The setup compiles the path shader, which
some Vulkan drivers (Mesa RADV/ANV, NVIDIA) take gigabytes over: the memory
climb reported while orbiting in Render. The setup now starts only while
Render is open with the GPU path method.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9465
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Face attachments: a piece of a face its certificate finds the other pieces of keeps that certificate (#9465)
The nightly action matrix has refused a sketch and an offset plane on the
sensor enclosure lid's underside (`examples/sensor_enclosure :: Lid/F2:top`)
since #8278. The lid's lip, joined below it, parts the underside into a ring
and a panel; the ring rests on the case and is named after the case's top,
so the lid's cap certificate (via certified_pieces) finds only the panel.
#8278 then refused the certificate because it doesn't find the picked face,
and the history-name fallback can't take a name made by another body's
feature.
A face that is no pattern or mirror copy and lies on the same oriented plane
as the pieces the certificate finds is another piece of that face: the
certificate stands for it, as before #8278. Copies (the #8278 case) still
fall back to their own history name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8510
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Measure: drag the labels away from the part (#8510)
The distance and X/Y/Z labels in the view follow a drag of the pointer and keep
a leader to what they measure; a double-click or a new measurement puts them
back. A press on a label picks nothing, starts no box selection and opens no
Select Other.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9105
* Sketch: alignment guides from any hovered point while drawing (#9105)
While a drawing tool waits for a point, hovering a line or arc end, a
rectangle corner or a free point wakes the same temporary horizontal/
vertical tracking guide as a circle centre or line midpoint. Idle
hovering keeps centres and midpoints only. Preference
sketch_tracking_points (on) turns it off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9130
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Browser: a Joints folder under each placement lists the joints that attach it (#9130)
Each component placement in the Browser gets a Joints folder (closed at
first) listing the joints whose Component 1 or Component 2 is that
placement, each beside the placement it joins it to. The rows are the
root folder's joints: click picks, the eye hides the glyph, double-click
edits and the menu is the joint's menu. The root Joints folder is
unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8275
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Settings: written to disk in the frame they change, not only at a clean exit (#8275)
eframe saves app.ron every 30 s and when the window closes normally. A
change made since the last save was lost whenever the app didn't close
normally: ended from the Task Manager, stopped by a sign-out or shutdown,
or crashed or hung in the graphics driver on the way out. The next start
then showed the old settings (View navigator back to Axes, Display quality
back to Normal).
The desktop app now writes its settings and flushes them in the frame they
change (frames with input and the one after), as the web app already does
(#8644). Unchanged settings are not written again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Settings: write at most once a second, and only after input that can change them (#8275)
Review: pointer motion came in every frame while the mouse moved, so the
settings were serialized every frame; and some settings change in every frame
(a panel's width while its edge is dragged), which would have flushed app.ron
on the UI thread each frame. Only clicks, keys, text, paste, wheel and pinch
count as input now, and the file is written at most once per second: a change
made in between waits, a repaint is asked for when its second is over, and it
is written then, so an idle app still writes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9062
* Sketch drag: a line is never shrunk to a point to follow the cursor (#9062)
A line's end on a horizontal construction line through the origin, dragged
up off it, made the construction line vanish. A horizontal row is
b.y - a.y, which a line a hair long meets at any tilt, so the drag's held
solves met the point-on-line by shrinking the construction line: to 1e-5 mm
on the first frame, 1e-7 mm by the tenth, and the end went up.
A drag step (held solve, the tangent-ends-held solve, and each cursor
correction pose) that shrinks a line or circle from over 1e-3 to under
1e-4 now counts as failed, as a step that wraps an arc does. The end then
stays on the construction line, which keeps its length.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9034
* Assistant: say when an installed agent can't start, and how to reinstall it (#9034)
An agent whose program is found but fails its `--version` check without
printing a version (npm's opencode.exe left as a placeholder when the
package's setup script did not run, which Windows refuses with "not
compatible with the version of Windows you're running") was listed like
a working one, and connecting only said "The agent stopped." with the
system's message.
Discovery now keeps why the program did not start: the spawn error
(Windows' `%1` replaced with the program) or, through a `.cmd` shim, the
first stderr line or the exit status. A probe that times out still says
nothing. The picker shows "Installed, but it does not start: ...", and
connecting first explains it with the agent's install command and Refresh.
The control channel status carries `problem`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9142
* Exploded View: grey it out until the design has two components (#9142)
On a part made of plain bodies (the sample plate) Exploded View opened its
dialog and failed on OK with "an exploded view needs two or more
occurrences". The command is now disabled until the design has two or more
occurrences, and its tooltip says why and which commands make components.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #1044
* Continuous orbit turns about the Orbit around point (#1044)
With Orbit around set to the point under the cursor (or the origin), Continuous
orbit still turned about the view's centre. Cursor orbits move that centre off
the model, so the model swung across and out of the view while it spun. The
spin now turns about the origin, or the model point in the middle of the view
(else the middle of the bodies in view), held from start to stop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #2153
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Zebra: flat faces keep one stripe colour while the view turns (#2153)
A face whose normal lies in the upright plane through the view (every
horizontal face) reflects straight ahead, where the zebra's sideways
coordinate is zero: exactly on the edge between a black and a white
stripe. Rounding then picked one or the other from frame to frame, so
the face flickered while the camera orbited. Straight ahead is now white.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9407
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Section caps: a body touching another along a curved face keeps its own cap (#9407)
Seen through a cut, a far wall and another body's face lying on it (a shaft
in its bore, a ring in its housing) are the same surface faceted two ways, so
the marking pass let the other body's face win in streaks. The section's
passes now first count the faces behind the cut in the stencil (back +1,
front -1): where the count says the cut runs through a body but a front face
won, the back faces are drawn again pulled toward the eye by a few pixels and
take the cap back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9279
* Parameters: an option to hold edits until Apply or OK (#9279)
"Apply each change as you leave its field" (on by default, remembered in
the preferences as parameters_apply_live). Off: an expression edit is
checked when its field is left but waits, without a preview; Apply or OK
sets every held edit in one parameters.change {changes}, so the design
rebuilds once and one undo takes them back. Cancel, the close button and
Escape drop them. Turning the option back on applies what waits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: the parameters_apply_live preference in ui.prefs (#9279)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Parameters: the hint says edits wait for Apply or OK when they do (#9279)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9144
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* DXF export: the full release 2000 file structure strict readers need (#9144)
The view and flat pattern DXF left out parts of the AC1015 file that a
strict reader expects: the CLASSES section, the VPORT, VIEW, UCS, APPID
and DIMSTYLE tables (with *Active, ACAD and Standard) and the ACAD_GROUP
dictionary under the root dictionary. They are written now, along with
$DWGCODEPAGE; the active viewport looks at the whole drawing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8776
* Crash reports: a window opened after startup no longer labels the run "during startup" (#8776)
egui-wgpu reports "window surface" and "surface configure" for every native
window, also the ones opened after startup, such as the agent chat in its own
window. Each one overwrote the journal's "running" phase, so a later unclean
exit was reported as "during startup (surface configure, N s after launch)".
crash::startup_step records a startup step only until the app runs, and the
app's egui-wgpu hook calls it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #2227
* 3D mouse: optional orbit while a sketch is open (#2227)
A new Navigation preference, "Turn sketches with the 3D mouse"
(space_mouse_sketch_orbit, off by default), lets the cap and a device
app turn the view while a sketch is open and seen square on, as the
mouse already can. Off keeps today's behaviour: pan and zoom until the
view is tilted away from the sketch (#6687). Restore defaults on the
3D mouse section resets it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* 3D mouse: keep the settings list in order after the rebase
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #8563
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Parameters: sort each section by name (#8563)
The Name heading of every Parameters table steps through A to Z, Z to A and the
listed order. Each section sorts on its own: Favorites, User Parameters and each
model group (the groups keep the design's order). Names compare in natural order
(d2 before d10, letters ignoring case). The choice is kept in egui's persisted
memory like a section's open state. While sorted, a user parameter's move arrows
are disabled. The sortable heading and natural_cmp live in ui_kit::table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Parameters sort: gallery entry for the sortable heading, natural_cmp private
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8398
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Closing: stop the Home picture builds instead of waiting for them (#8398)
Dropping SolveApp waited up to 10 s for the Home picture threads to end
(#6063). The thumbnails thread imports and rebuilds every cold recent
file (STEP and mesh imports, designs without a stored picture) one after
another, and its channel only closes once all are done, so closing the
window froze until every cold recent was built or the 10 s ran out.
The picture threads now build under a shared progress watch that
finish_pictures cancels first: the design being built stops at its next
feature (a STEP import at its next step), the remaining cold files are
skipped, and a build stopped part way draws and caches no picture.
Pictures already on the GPU are still waited for, so the driver crash
#6063 fixed stays fixed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #9001
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch: a projected face follows a resize that moves its corners far (#9001)
A sketch on the face of an angle kept its projected face boundary (and
reported "projected face boundary identity is ambiguous") when the wall
thickness changed: the inner corner moved by more than a tenth of the face,
past the nearest-point match, and the same-order fallback refused faces.
Accept the same-order layout when, for every point, the point read in that
order is also clearly the nearest one on the same loop with lines the same
way. Rims and holes, and rotated readings of a rectangle, stay refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #7971
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Toasts: a close (×) with a countdown ring instead of a Close button (#7971)
Every toast the user may close (the status, the 3D mouse offer and the
stand-up note) has a close (×) at its top right, handle toast:<name>:close,
in place of a Close button; it does what the button did, is a kit-drawn
button with an accessible name and hover text, reachable by Tab, and dead
behind an issue report. Toasts that go by themselves draw a thin ring
around it that shrinks over their time; pointing at the offer or the note
starts their time again, as before, so their ring is full while pointed at.
The 3D mouse offer keeps three buttons, Calibrate…, Use Direct Driver (the
detail in its tooltip) and Never show again, on one row: the corner
toasts are 400 points wide, as the row's estimated widths need 356.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Toasts: lay buttons out at their drawn widths; corner toasts 360 wide (#7971)
The toast's button rows used an estimate of each button's width that ran
about 40 points over the kit button as drawn, which wrapped the 3D mouse
offer's three buttons and left the main action short of the right edge.
Each button's drawn width is now remembered and the rows laid out with it
(the estimate stands in for the one frame before a button was first
drawn), so the main action is flush right; the corner width is the
smallest round one that fits the offer's three buttons in a row: 360.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Toasts: keep the analysis status test whole after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #7944
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Theme: System follows the desktop's dark/light setting on Linux (#7944)
On GNOME (Wayland, or X11 through XWayland) the window toolkit never reports
the desktop's dark or light preference, nor its changes, so Theme: System kept
its colours. The Linux app now reads org.freedesktop.appearance color-scheme
through the XDG Desktop Portal's Settings interface (then GNOME's color-scheme
and gtk-theme when it has no preference) on a thread of its own, follows the
portal's SettingChanged signal, and falls back to gsettings or a slow poll.
The window reads the answer through Services::desktop_dark; the decision from
the raw values is prefs::desktop_prefers_dark. Windows and macOS keep the
window toolkit's theme.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8100
* History: say why an edited feature behind the marker changes nothing (#8100)
Editing a feature that sits after the history marker (double-clicking its
greyed-out item) rolls back to it, previews the change, and on OK puts the
marker back where it was: the feature stays rolled back, so nothing in the
view changes and nothing says why. That is the silent "pattern of a cut
does nothing" in #8100 (the reporter's design has its pattern behind the
marker; on main the pattern itself builds fine once rolled forward).
- timeline.redefine replies `rolled_back` and, when true, a `note`; it also
carries the feature's `warning` (for a rolled-back feature, the one its
constructor met building it at its place).
- The window shows that note in the status line after such an edit.
- A rolled-back item's tooltip in both History layouts says it is after
the history marker and not built.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Pending locale: Arabic, Hebrew, Japanese, Vietnamese and Chinese for the rolled-back notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #8692
* Browser: remember the folded card across runs, optional reveal on hover (#8692)
The browser card's fold (the chevron in its header) is now a preference,
saved with the other layout state, so the next run starts the way the user
left it. Preferences > Interface > Layout adds Shown / Reveal on hover: the
browser then stays out of sight until the pointer comes over its place or
the thin tab at its left edge, fading in like the navigation bar's Hide
until hovered, and stays while the pointer is inside or a menu, drag or text
edit started from it is open. It never folds in that mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Browser: move the reveal-on-hover messages to a pending locale file (#8692)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8561
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Dialogs: disable Apply until something changed (#8561)
The dialog footer gets a disabled state for Apply (Footer::nothing_to_apply,
Window::apply_enabled): drawn with the theme's dim ink, not clickable, not
reached by Tab and reported disabled to accessibility. Preferences enables
Apply only while something differs from its snapshot (what Cancel would put
back), so it is disabled when the dialog opens and again after Apply.
ui.prefs replies with apply_enabled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8382
* Browser: Show/Hide context menu on origin axis rows (#8382)
Right-clicking an origin axis row (X, Y, Z) now opens its own menu with
Show/Hide (V), through ui.originPart and browser.visibility like the
origin planes' entry. An axis takes no sketch, so Create Sketch is not
offered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #7834
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Viewport: vertex markers where edges are drawn (#7834)
Each body's vertices (the ends of its pickable edges, once each) show as
small screen-space squares in the edge colour in the styles that draw
edges: shaded with edges, wireframe, and shaded with hidden edges, where
hidden vertices show faintly like hidden edges. Plain shaded draws none.
A marker is a lifted line from the vertex to itself in the body's block,
so it is instanced with the edges, cached with them, and depth-tested
like a highlight band. The existing vertex hover ring stays on top.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Viewport tests: count edge segments apart from vertex markers (#7834)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Vertex markers: an option, off by default (#7834)
Adds the Vertex markers preference (Preferences > Graphics, off by default) and draws the dots only when it is on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
* claim: #7861
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Sketch dimensions in a colour of their own in every theme (#7861)
Dimension lines, arrows and values were drawn in the same near-black or
near-white as fully constrained sketch curves, so they were hard to tell
apart in a busy sketch. Every theme now sets its own dimension colours:
plum on Light, orchid on Dark, and a hue from each built-in theme's own
palette. Colour vision tests measure them against the curves, the
construction lines and the conflict red, and a new test holds every
shipped theme to readable, distinct dimension colours.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #7587
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Naming: name a long history of one body from the oldest up (#7587)
A body's face names are worked out from the names of the body it was made
from, recursively. After a few hundred features in a row whose names
nothing asked for, reordering or moving an earlier feature re-evaluated
them all and the first name lookup (a fillet at the end) recursed once per
feature, overflowing the 1 MB window-thread stack on Windows. Name every
16th earlier version oldest first so no lookup recurses through more than
16 of them; the names are the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8104
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Windows: an export over a file another program holds briefly waits for it, up to 2 s (#8104)
write_atomic replaces the target with one rename. Windows refuses that rename
(os error 5 or 32) while another program, such as an antivirus or indexer
scanning a file written a moment earlier, has the file open without delete
sharing. The retry gave up after 127 ms of waiting, which a scan under load
outlasts, so render.export and library.export over an existing file failed
with "Access is denied".
The retry now keeps doubling its wait up to 250 ms, about 2 s in all. If the
file is still held after that, the error says the file is in use by another
program, followed by the system's own message. The old file stays whole
throughout, as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Saving over a read-only file fails at once, and says why Windows refused
Access denied (os error 5) is also what Windows gives for a read-only or
ACL-denied target, which waiting does not fix. A read-only target is now
refused without the 2 s wait, with "the file is read-only". Any other refusal
that outlasts the wait says another program may have the file open or it is
read-only, followed by the system's own message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #8097
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Insert design: file names get the width the size and actions leave (#8097)
The web app's "Files in this browser" window listed stored files in an egui
Grid sized from cell content: the wide action buttons took most of the fixed
window width, the name and size columns were cut, and the rest was empty.
Add ui_kit::name_list on the kit's table grid: the name column takes the
width the other columns leave, the other columns are as wide as their widest
cell (measured as drawn, a changed measurement discards the frame), and a
name is cut with an ellipsis and its full text on hover only when it does
not fit. The window is a little wider (still capped at the browser width).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>