Commit Graph

185 Commits

Author SHA1 Message Date
Rick Morgans 92af4a21c8 Control channel: a per-request param_check level, applied and confirmed by the app (#9184) (#9185)
* claim: #9184

* Control channel: a request's own param_check level, applied and confirmed by the app (#9184)

`engine.execute`, `engine.batch` and `engine.script` take an optional
`param_check: "off"|"warn"|"strict"` in their params. The app runs the
request at that level through the same `run_checked` path and batch
preflight a headless session uses, puts its own level back, and every
reply says the level it ran at as `param_check` beside `ok`. A command
that switches designs keeps the app's level; any other word is refused.
Readings and exports answered on a copy off the window thread keep the
level too.

`control.capabilities`, answered at once on the control-server thread,
lists what the channel does beyond the methods every version has:
`{"param_check": ["off", "warn", "strict"]}`. An older app answers
"unknown method".

The MCP bridge asks it once per connection. When the app lists the
level, every call and batch goes with it and the app checks against its
own commands; otherwise the bridge checks before sending, as #9073 does.
At strict, a reply that doesn't say the app checked the call is an error,
and the next calls are checked by the bridge. Also: `add_param_warnings`
takes the reply by `&mut`, and `with_param_check` sits beside
`Remote::new`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Control channel: a design-switching command is checked at the request's level

Review fixes for #9184. `component.edit_in_place`, `component.finish_edit`,
`view.next_tab` and `view.previous_tab` ran at the app's own level and
echoed `off`, so a misspelt call went through at strict. They now have
their parameters checked at the request's level before they run (and
still run at the app's own level, as each design keeps its own), and the
reply echoes the requested level. The MCP bridge at strict now requires
the echo to match its level, not just to be there. `param_check` is read
only by `engine.execute`, `engine.batch` and `engine.script`; other
methods ignore it. The off-thread test now shows the design change
computing off the window thread before it is refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:24:41 +00:00
AsTechEvolves 94b399e98f Preference: keep the view when a sketch opens; Look At faces it on request (#9188) (#9190)
* claim: #9188

* Preference: keep the view when a sketch opens, Look At faces it on request (#9188)

Preferences > Sketch > "Turn to face a sketch when it opens" (on by default,
so nothing changes unless it is turned off). Off: creating or editing a
sketch leaves the view as it is, a sketch started on a face no longer
re-centres on the picked point, and Look At (the palette button, Ctrl+8)
still turns to face the sketch. The control channel sets it as
`ui.prefs {"sketch_open_look_at": false}`.

Changes a default: no

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 05:32:56 +00:00
railconstr 81cbcef31c Sketch: add construction-line toolkit (#8239) (#8679)
Co-authored-by: railconstr <335242259+railconstr@users.noreply.github.com>
2026-10-30 05:02:54 +00:00
taylorhayis 313d2bdb41 Sketch: snap where two recent centre and midpoint guides meet (#8694) (#8744)
* Sketch: snap where two recent centre and midpoint guides meet (#8694)

The alignment guide remembered one reference and did not move the cursor. Keep the previous centre or midpoint as well, and snap a drawing point to where their guides cross.

* Sketch: keep the recent-guide crossing snap off until asked (#8694)

The crossing snap was on whenever alignment guides were. Give it its own Sketch preference, off by default, so the guides stay visual until someone turns the snap on.

* Sketch recent snap: ar/he/vi strings and clippy borrow fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 00:40:05 +00:00
tr1pp4 b43712cdb0 Command search: show a command's place in the ribbon, also inside section menus (#7287) (#7322)
* claim: #7287

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Command search: show a command's place in the ribbon, also inside section menus (#7287)

Hovering a command result in Search commands switches the ribbon to the command's
tab and marks its button with its tooltip; a command that has no button there
opens its section's drop-down on its row instead. Leaving the results (or closing
the box) goes back to the tab the user was on, so pressing S, typing and Enter
works as before.

Starting a command from the box makes its button or section label blink twice,
and a command started from a section drop-down marks that section's label while
it runs, like a pressed button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Command search: the ribbon reveal is a preference, off by default (#7287)

Preferences › Interface › Show search results in the ribbon (`ribbon_reveal`) turns on the hover
preview, the blink after a start and the running mark on a drop-down's panel label. Off, the
ribbon behaves as on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pending locale: Arabic, Hebrew, Japanese, Vietnamese and Chinese for the ribbon reveal setting

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>
2026-10-29 19:06:44 +00:00
CamWight a985b8ee17 Preferences: Perspective view's field of view, a slider or a typed value (#5364) (#5373)
Preferences > Graphics > Viewport gets a Field of view row under Perspective view: the UI kit's
slider in degrees, 15 to 90, dragged or typed and kept to whole degrees, enabled only while
Perspective view is on. The preference is perspective_fov, in radians (default 0.6, about 34°,
so the default view draws exactly as before), and Restore Defaults puts it back.

One place decides the angle the view is drawn with: SolveApp::view_fov(), the preference with
Perspective view on and 0 with it off or while a sketch is open. A saved value outside 15°-90°
reads as the default. projection and fit_bounds read it (fit_bounds' second hard-coded copy of
the 0.6, tan(0.3), now goes through Camera::half_height), and so does the headless fit.
perspective_view() stays, as view_fov() > 0, so #4291 needs no change.

When the angle changes from one perspective angle to another, the camera's distance scales by
tan(old/2) / tan(new/2), with a running view animation's ends, so the target keeps its size and
the slider changes the depth, not the zoom. prefs::follow_view_fov does it once per frame and
after ui.prefs, Cancel and Restore Defaults; a parallel view keeps the last perspective angle,
and while Render is open the camera is Render's own, so the change waits for the design view.

The Render workspace's Perspective check box turns perspective on at the preference's angle,
not π/4; a saved render setup keeps its own. ui.prefs takes perspective_fov and refuses values
outside the range; ui.camera reports the angle the window draws with, and checks a replayed
camera against it, so its reply still replays. Field of view is in en, ar, de, he, ja, ko, vi and zh;
the ui.prefs settings list in docs/control-protocol.md and the guide's tour describe it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 18:23:49 +00:00
Colin Faulkingham 3cdc68aaf1 Viewport: opt-in model zoom and Traced 3D mouse orbit (#7435) (#7991)
* claim: #7435

* Viewport: the 3D mouse, the bridge and drag-zoom stop at the model, like the wheel (#7435)

The wheel and pinch hold the model point under the cursor, so the view
comes up to the surface and stops there. Every other zoom path passed no
anchor, so the 3D mouse cap, the navigation bridge and drag-zoom zoomed
straight through the surface into the body.

A device has no pointer, so the cap and the bridge now hold the model
point in the middle of the view; drag-zoom holds the point under the
pointer, like the wheel. With "Zoom to the cursor" off the old
zoom-through-the-model behaviour stays, as it does for the wheel.

The orbit half of the issue is a design decision and is untouched.

* Viewport: drag-zoom holds the point where the drag started (#7435)

The zoom anchor followed the moving pointer, so the zoom slid away from
what was pressed on as the drag went on. It now holds the press point,
the way the wheel holds the point under the cursor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* 3D mouse: turn around the model in the middle of the view (#7435)

The cap and the navigation bridge turned the view around the view's
centre, which after a pan or from far away sits behind the face, so the
part swung away while it turned. They now turn around the model point in
the middle of the view (the middle of the bodies in view over empty
space), and keep it still on screen. Preferences > Navigation > "Turn
around the model in the middle of the view" switches back to the old
behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* 3D mouse: keep the turning point until the cap is back at rest (#7435)

The point the cap turns around was picked again every frame, so it slid
to whatever came into the middle as the view moved. It's now chosen when
the cap leaves rest and kept until the cap comes back, the way a mouse
orbit keeps the point it started on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* 3D mouse: show the point the view turns around (#7435)

While the cap turns the view, a faint ball in the accent colour marks the
model point it turns around, so it's clear what the turn holds still. The
point is now picked when the cap starts turning, not when it only pans or
zooms, so a pan shows no ball.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* 3D mouse: orbit is a choice of Traced or Classic (#7435)

The checkbox becomes a two-way choice on the 3D mouse section's form:
Traced turns around the model in the middle of the view when the turn
begins and marks it with a faint ball; Classic turns around the view's
centre as before. Traced stays the default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: the 3D mouse's Traced and Classic orbit (#7435)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Make model zoom and traced orbit opt-in (#7435)

---------

Co-authored-by: nomadsgalaxy <16734355+nomadsgalaxy@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 17:49:15 +00:00
Nathan Dane 6255a10e80 Viewport status item: engine list of what is on (#8545) (#8554)
* claim: #8545

* Declare ordered viewport status items (#8545)

* Keep legacy surface analysis coexistence behind a preference (#8545)
2026-10-29 17:11:34 +00:00
Lars Jansen a4274f9b59 Line tool: press and drag draws one line (#7247) (#7252)
* claim: #7247

* feat(sketch): press and drag in the Line tool draws one line (#7247)
2026-10-29 16:34:30 +00:00
raykholo 8a888ff0f3 Preferences: mouse-wheel zoom speed (#4176) (#4179)
* claim: #4176

* Preferences: mouse-wheel zoom speed (#4176)

A 0.25x to 4x multiplier for each wheel zoom step, applied in
navigation::handle so every canvas uses it. The 3D mouse keeps its own
speed. Values outside the range are refused when set and reset to 1x when
loaded.

* Control protocol: wheel_zoom_speed in the sorted ui.prefs list (#4176)

* Wheel zoom speed: its label in the complete catalogs (#4176)
2026-10-29 15:26:14 +00:00
austin62jake 3e01081ff9 Control token: a closing window removes only its own token and discovery files (#8794) (#8837)
* claim: #8794

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* Control token: a closing window removes only its own token and discovery files (#8794)

Under Flatpak each instance has its own loopback, so a second window
binds the same port number as the first and writes the same
<port>.token, <port>.pid and current.port in the shared data folder.
At exit the first window deleted them all, unconditionally, leaving the
second window running with no token file a client could read.

remove_token_file now takes this launch's token and removes the token
and process files only while the file still holds it; the process id
can't tell instances apart, as every Flatpak instance has the same one.
remove_current_port also takes the token and keeps the discovery file
while another launch's token file holds that port, and removes
current.pid with current.port (it was left behind).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-29 15:01:45 +00:00
raykholo dcae86e456 Trackpad: zoom with two-finger scroll while holding a key you choose (#8322) (#8584)
* Trackpad: zoom with two-finger scroll while holding a key, chosen in Preferences (#8322)

Holding the zoom key turns a vertical two-finger scroll (or a wheel) into zoom at
the pointer, with the wheel zoom's speed, direction and anchor, so a laptop user
zooms without pinching. Preferences > Navigation > "Zoom with two-finger scroll
while holding": Cmd on macOS and Ctrl elsewhere (default), Option/Alt, Ctrl, or
Off. That key with the scroll did nothing before, so no default changes; Off
keeps it that way. Shift keeps its orbit.

* Trackpad zoom modifier: off by default (#8322)

Scroll keeps its usual meaning until a key is chosen in Navigation.

* Trackpad zoom modifier tests: Off is the default; tests that zoom choose Cmd (#8322)

* Trackpad zoom modifier: zoom once alongside the Ctrl+wheel pinch from #8539 (#8322)

A wheel the chosen key claims is no longer also read as a pinch, and a key that is not
chosen keeps main's pinch handling unchanged.
2026-10-29 14:49:19 +00:00
cronos 28e26209f3 Assembly Move: drag allowed joint freedoms (#6679) (#6904)
* feat: add joint-aware assembly Move handles and live motion readouts

* test: improve render job failure diagnostics

* fix: preserve assembly Move compatibility and viewport theme colors

* ci: skip default label sync for fork PRs

* fix: keep Windows CI checks portable after main rebase

* test: cover RTL assembly strings and stable refraction job

* i18n: cover assembly Move in Vietnamese

* i18n: cover assembly Move in French

* fix: complete CGA palette for assembly motion handles

* fix: complete Assembly Move palettes and Turkish strings

* fix: retain assembly move cache answers and toolbar help

* style: format merged assembly Move navigation guard

* fix: align Assembly Move preferences and tests with main

* Fix offline update fixture synchronization and clipped prism intersections

Wait for all v5 manifest requests before deploying v6. Intersect hole-free prism sections over their common height, retaining the established B-rep path for newly clipped perforated sections. Preserve the failing property seed and add closed-form and cap-boundary regressions.
2026-10-29 13:57:31 +00:00
raykholo 884c47496b Render preview: geometry budget from the device, readable refusals (#4127) (#4154)
* claim: #4127

* Render preview: geometry budget from the device, readable refusals (#4127)

The Render preview refused every scene over a fixed 128 MiB of geometry. On
desktop the budget now follows the device's buffer limit (eight of its
largest buffers, at most 2 GiB; 2 GiB with the usual 256 MiB buffers). The
web keeps 128 MiB.

The product upload runs under its own GPU error scopes: an allocation the
device refuses is reported in the preview instead of reaching the device's
uncaptured-error handler, and the half-uploaded batches are dropped. Buffer
uploads map the buffer themselves so a refused buffer fails the upload
rather than panicking in create_buffer_init.

Refusals name the geometry size and the limit and say how to get under it,
on a theme panel card that stays readable on any preview background.

* Render preview: keep the previous geometry budget behind a preference (#4127)

* Render preview: adapt the device budget to main's GPU upload errors (#4127)
2026-10-29 13:33:39 +00:00
Karl Von Richter b2d727f4b2 Toolbar: choose visible tabs while preserving all defaults (#5717) (#8594)
* claim: #5717

* ui(feat): let users choose visible toolbar tabs

Keep Sheet Metal and Weldments visible by default while adding persisted tab visibility controls and restoring specialty tabs for designs that use them.

Signed-off-by: Karl Von Richter<karl@embeint.com>

* ui(fix): respect hidden toolbar tabs in every design

Remove feature-based visibility overrides for Sheet Metal and Weldments. Keep all tabs visible by default and preserve the user choice across feature creation, opening designs, selection and undo.

Signed-off-by: Karl Von Richter<karl@embeint.com>

---------

Signed-off-by: Karl Von Richter<karl@embeint.com>
2026-10-29 13:32:21 +00:00
Joseph 07d692ee0d Keyboard Shortcuts: several keys for one command (#6273) (#6288)
* Keyboard shortcuts: a command can have several keys

Click a key on the Keyboard Shortcuts page to replace it, or the + after it
to add another; every key runs the command and menus show the first. One
key is still saved as a string, several as a list. Taking a key over from
another command leaves that command its other keys. ui.shortcut takes a
slot and reports every key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keyboard shortcuts: follow main's search layout; fix prefs test for key lists

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>
2026-10-29 12:32:19 +00:00
Colin Faulkingham 81039a0e10 Pinch zoom: route Ctrl+wheel input to the camera (#8480) (#8539)
* claim: #8480

* Pinch to zoom on touchpad: native Ctrl+wheel pinch zooms the view (#8480)

The viewport's pinch path read only `egui::Event::Zoom`; `immediate_wheel` leaves
wheel events carrying the zoom modifier to egui. Native Linux and Windows
touchpads report a pinch as Ctrl+wheel in points, so the gesture reached neither
path and the view did not move. `pinch_factor` now reads those wheels too, in
every wheel unit and scaled as egui scales them, and `ui.scroll` can send the
same gesture (`ctrl: true`) so scripts and scenarios can replay a pinch.

* fix: finish Ctrl+wheel pinch handling and replay validation (#8480)
2026-10-29 10:40:10 +00:00
Lars Jansen 375dc01602 Navigation: Right drag orbits option; picking the SolidWorks preset turns it off (#6492) (#6497)
* claim: #6492

* feat(navigation): Right drag orbits option, off when picking the SolidWorks preset, which also fits on middle double-click (#6492)
2026-10-29 10:24:37 +00:00
PaddleStroke fe3f913d76 Dialogs: disable Apply until something changed (#8561) (#8728)
* 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>
2026-10-29 10:14:45 +00:00
Nathan Dane de5cee9bf1 Viewport status item: UI-kit element and row (#8544) (#8553)
* claim: #8544

* Add reusable viewport status items and fixture (#8544)
2026-10-29 03:02:43 +00:00
raykholo a1e7337d3c Toasts: one stack in the view's bottom-right corner, one width, buttons as in dialogs (#7893) (#7959)
* claim: #7893

* Toasts: one stack in the view's bottom-right corner, one width, buttons as in dialogs (#7893)

* Control protocol: toast_place in the sorted ui.prefs list (#7893)

* Toasts: a sketch test clears the status notice before clicking the view's corner (#7893)

The test's line end lands in the bottom-right corner, where notices now stack
and take clicks as they did at the bottom centre; the test is about the circle.

* Toasts: the pattern scenario's circle sits clear of the view's corner (#7893)

After the refit, a circle at y 0 landed in the bottom-right corner, where the
tool's prompt now stacks and takes clicks. The circle moves 40 mm up; the
pattern it checks is the same.
2026-10-28 22:35:24 +00:00
Lars Jansen fe265d74b1 Sketch: draw conflicting curves and points in the conflict colour (#7244) (#7249)
* claim: #7244

* feat(sketch): draw curves, points and constraints that conflict in their own colour (#7244)
2026-10-28 22:03:54 +00:00
Logan Night bda5f69c5c Preferences: reverse trackpad orbit direction (#8410) (#8484)
* claim: #8410

* Preferences: reverse trackpad orbit direction (#8410)

Add "Reverse trackpad orbit direction" under the pan settings in
Preferences > Navigation. orbit_reverse defaults off, so older settings
files load unchanged, and turns the Shift + two-finger orbit the other
way on both axes, as natural scrolling flips both. Pan, zoom and mouse
orbiting are untouched. Labels in en, ar, de, he, ja, ko, vi and zh as
a pending locale file; orbit_reverse in the control protocol's sorted
settings list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:25:24 +00:00
froglemonade2 f595f38e1c Define a named parameter inline from any value input (#4071) (#7341)
* claim: #4071

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Define a named parameter inline from any value input (#4071)

Any value input, typed or sent as a command's expression parameter, takes
`name = expression` (or `#name = expression`): the design gets the user
parameter `name` with that expression, and the input stores `name`, in the
command's one undo step.

- doc: the lexer skips a definition's `name =`, so until the design stores
  it the text evaluates as its expression and commands read and check it
  like any value. `Document::define_inline` then turns every stored
  definition (feature inputs and placements, dimension parameters, sketch
  pattern and text values, joint and coupling values, sheet metal and
  plastic rules, canvas planes) into a user parameter, the unit following
  how the input reads a bare number. A taken, reserved or empty name, two
  different values for one name, and a definition in a parameter's own
  expression or a configuration cell are refused; all or nothing.
- engine: `Session::execute` runs it after any command whose parameters
  hold definition-shaped text; the reply has `defined` (the first name,
  as `sketch.dimension` already gives) and `definitions`. A refusal fails
  the command, which leaves the design as it was.
- `parameters.change` with `new = expression` renames the parameter it
  changes (a dimension's or feature input's own, references following)
  and sets it; when the value is just `new`, it sets `new`. `changes`
  refuses definitions. `expr.evaluate` reports `defines`.
- UI: lengths keep the name when the design unit is applied; sketch text
  sends a definition as typed and previews only its value; the box corner
  and offset Distance 2 use the value; fields whose command keeps no
  expression (sketch scale, move, chamfer) refuse a definition with the
  way to name it. The dimension editor says which parameter it named.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:14:36 +00:00
froglemonade2 02ac56d12f Feature windows choose Join, New Body or Cut from what the material touches (#6901) (#6903)
* claim: #6901

* Feature windows choose Join, New Body or Cut from what the material touches (#6901)

Extrude, Revolve, Loft, Sweep, Coil and the Box, Cylinder, Sphere and Torus choose
their operation by running the Join on a copy of the design off the window thread
and counting the pieces: Join when the material makes one body with what it
touches, New Body when it would be a separate piece, Cut when it lies inside a
body (Revolve and the four primitives; Extrude keeps its own Cut). The choice
changes only when a check is in, a pick in the Operation row (the shown option
included) stops it for good, and OK waits for a running check. Hidden bodies take
no part: with some hidden, the shown ones become the feature's targets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation row: a pick in Extrude stops its own choice at once; ja/zh strings, gallery entry

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation check: contact test first, mesh volumes for Cut, OK takes the evaluated Join

Material touching no body is a New Body without running the Join (the contact
test costs 0-240 ms where the Join costs seconds on a large body). Inside is told
from display-mesh volumes instead of exact ones (8 s on a 400-hole plate). The
check evaluates the Join through Session::ahead, and OK of the same commands
takes it (Session::prime) rather than computing it again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preference: Choose the operation automatically (on by default)

Preferences > Design gets "Choose the operation automatically" (auto_operation,
on by default). Off, feature windows don't choose Join, New Body or Cut from
what their material touches: each keeps the operation it opens with (Extrude
its own Join or Cut), no check runs and OK doesn't wait for one, as before

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic, Hebrew, Vietnamese and Turkish strings for the operation choice and its preference

Arabic, Hebrew and Vietnamese are complete catalogs now, and Turkish has a full
catalog, so this change's three strings get them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation check: a closed window's check stops; the icon audit doesn't choose

A window's operation check kept running after the window closed, a Join on
the design for nothing, and the test harness waited for it after every step:
the icon audit, which opens every window, took ~30 min instead of ~1. The
check now runs under a Progress, and closing the window (or one that doesn't
choose) abandons it: its evaluation stops at the next feature and nothing
waits for it. The icon audit turns auto_operation off, as it only looks at
icons (75 s again).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Box placement test: the window keeps its New Body

The test #6248 added places a box that overlaps Base and expects a second body;
with #6901 the window would join or cut it. The test is about where the box
goes, so it turns auto_operation off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Join pieces: read the target lists leniently 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>
2026-10-28 19:57:27 +00:00
Lars Jansen 261d00fbb2 History and browser: a sketch's icon in the colour of its state (#7245) (#7250)
* claim: #7245

* feat(ui): a sketch's icon in History and the browser takes the colour of its solve state (#7245)
2026-10-28 19:40:45 +00:00
raykholo e2935aff95 Stand-up offer: a note only when the part seems to lie on its back (#7717) (#7718)
* claim: #7717

* Stand-up offer: a note only when the part seems to lie on its back (#7717)

* Stand-up note: an unclear shape still gets the note

* Stand-up note: a Don't ask again button, as the dialog has

* Control protocol: the stand-up settings in the sorted ui.prefs list (#7717)

* Stand-up note: the control import test asks as before (#7717)

The test checks the caller's `up`, so it sets the setting to Ask and every
file from another program still gets the offer.
2026-10-28 19:40:25 +00:00
raykholo dd2e44bb12 Raise the largest file SolidCraft opens with a setting or launch flag (#4086) (#7565)
* claim: #4086

* Raise the largest file SolidCraft opens with a setting or launch flag (#4086)

* Translate the file size limit strings

* Size limits: design files are .sc now, .solidcraft still read
2026-10-28 16:52:29 +00:00
Lars Jansen dca332201f Status bar: the sketch's state, what is being edited and the design's units (#7243) (#7248)
* claim: #7243

* feat(ui): status bar with the sketch's state, what is being edited and the design's units (#7243)
2026-10-28 16:25:32 +00:00
cronos b72165fd30 Sketch: show temporary centre and midpoint alignment guides (#7903)
* Sketch: show center and midpoint alignment guides

Add transient per-viewport horizontal and vertical guides with a sketch preference. Related tests, native UI, WASM and supplementary Linux checks pass. Full CI remains blocked by unchanged Windows engine dead-code Clippy errors.

* Sketch: complete alignment-guide translations

* Tests: compile chosen-program mutex only on Unix
2026-10-28 16:07:05 +00:00
Christian Hammacher aae2c5e417 Assemblies: edit a linked component in place, with the assembly around it (#7672) (#7819)
* Links: update linked designs that changed while the assembly's tab was away

A design coming back to its tab compares the modification time and size of its linked
design files with what they were when it went to the background, and runs Update Links
on the worker thread for those that changed: saved in another tab, another window or by
a checkout. Preference update_changed_links (Design, Linked designs) turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: the assembly guide says linked designs update when their tab returns

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Links: Vietnamese strings, now that vi is a complete catalog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Links: remember what each design last read, so an update that fails is tried again

A design's linked files are now recorded as the design last read them: when Update Links reads a
link without an error, or when the link is first seen. Coming back to the tab reads again what
differs, one link per run, so a file that cannot be read holds up no other and is tried again
the next time, and a part changed while the assembly was shown is taken up on its next return.
Closing several tabs together reads nothing on the way, and the web build, which keeps no file
times, looks at nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Links: no read during a save-changes prompt, records for adopted designs and missing files

A tab shown to answer "save changes?" reads no link before its save, and Cancel there or on a
batch lets the tab left in front read what it skipped. A design opened in place of the blank one
records its links at once, a link whose file is missing is recorded as missing so it is read when
the file comes back, and a read queued for a design that is no longer shown by the time it starts
is dropped. More changed links than can wait at once are read on the next return.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assemblies: edit a linked component in place, with the assembly around it

Activating a linked component opens the design it comes from in a tab of its own, with the
rest of the assembly drawn faded around it where the component sits, so the part's own history,
browser and commands are at hand. Finish Editing in the browser saves the part, goes back to the
assembly and closes the part's tab when the edit opened it; coming back to the assembly updates
the changed link (or Finish Editing runs Update Links when that is turned off). Update Links in
the part also reads the assembly's links again, off the window thread, and redraws the assembly
around the part; a result for an assembly changed meanwhile is dropped with a message.

The part is an ordinary tab, so saving, autosave, recovery, closing and quitting treat it as any
other design. The model scene's ghost triangles are now drawn (only the preview's were).
Preference edit_linked_in_place turns it off. Builds on the update of changed links when an
assembly's tab returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: a double-click opens it, Activate only activates

A double-click on a linked component edits it in place, in the browser as on a face in the
view (around the placement clicked), and the component's menu gets Edit in Place. Activate and
the browser's radio button make it the active component as they always did, so a linked
component can still be activated without opening its design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Double-click on a component's face: edit a linked one in place, activate any other

A double-click on a face in the view activates the component the body belongs to, at that
placement, as a double-click on its row does; a linked one is edited in place. Bodies of the
design itself or of the active component are left alone, and so is a double-click with a
modifier. One preference, double_click_components, covers both gestures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from review

An edit whose part never opens is forgotten instead of starting on a later open of the same
file, and the web build starts the edit after its synchronous open. Finish Editing goes on only
for a save into the linked file and in the part's own tab, waits for a "changed on disk"
answer, and says so when the part was saved elsewhere. Showing the assembly no longer drops a
refresh, which now records the links it read so coming back reads nothing twice. The faded
assembly is worked out once per picture, a bad mesh index skips its whole triangle, and the
last two status texts come from the catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: Finish Editing on the MODEL tab and the mouse's back button

Finish Editing is a command now, component.finish_edit, with its schemas: the app window
answers it, anywhere else nothing changes, as with view.fit. While a linked design is edited in
place the MODEL tab ends with a FINISH EDITING panel, pinned at the right as FINISH SKETCH is,
with a new left-arrow icon; the browser keeps only the line naming the assembly. The mouse's
back button, or a keyboard's Back key, finishes too unless a dialog, tool or sketch is open.
The assembly guide describes editing in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from the second review

Saving the assembly waits while it reads its links for the part
Finish Editing waits for dialogs, tools, sketches and prompts open in the part, also when run as a command
The assembly reads the edited part explicitly when it does not check its links on its own
The FINISH EDITING panel cannot be customized
A tab opened by an edit stays that edit's to close when the part is entered again
The mouse's back button finishes editing; the keyboard's only while no text field has focus
Refreshing the assembly keeps its selection and active component

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from the third review

component.finish_edit run as a command opens nothing and answers with an error when it cannot finish; engine.batch and engine.script refuse it
A double-click or Edit in Place while a dialog, tool or sketch is open in the assembly keeps it open
What changes in the assembly while it reads its links without changing its document stays: picks, activation, components dragged but not captured
Showing the assembly while it reads its links starts no second read
A new or opened design in the part's tab ends the edit
Finish Editing keeps the part's tab open while its agent chat runs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: Update Links run as a command in the part refreshes the assembly too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: the ribbon button reads Finish Edit, as Finish Sketch does

A bare "Finish" took the catalogs' surface-finish translation (German "Oberfläche").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from the fourth review

Finish Edit waits while the part's agent is in the middle of its turn, instead of keeping the tab of any chat open
A part saved while its assembly refreshes is read again when the edit finishes: the refresh records the files as it found them
A double-click on a linked component while something is open in the assembly says so instead of activating it
Commands are recognised in any spelling the engine takes, so engine.batch and engine.script cannot slip Finish Edit through
Update Links run as a command refreshes the assembly from the control channel only, not for the app's own reads
Moves of components the refresh removed are not carried over, and a refusal is one message
The command description and the guide say that the command does not save the part

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: the command is Finish Edit, as Finish Sketch is

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: a command to start it, and fixes from the full review

Added component.edit_in_place {component, path?}: the double-click and Edit in Place in the menu run it, and as a command it asks nothing, so a network location not allowed yet or a design open elsewhere makes it fail instead
Finish Edit asked by the part's own agent finishes once that agent's turn ends; the button still waits for the turn
The parameters and design properties panels, with text typed and not applied yet, hold up entering and finishing an edit
A refresh is not taken up under an undo, a queued command or a feature still being computed in the assembly
Refusals say what holds them up (a refresh, a file being read or written) instead of nothing
The browser strip names the assembly that is refreshing, not any assembly
The schema description says the command does not save the part
Korean strings for every new message

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from the second full review

The MCP batch tool refuses component.edit_in_place and component.finish_edit as steps instead of sending them one by one
Edit in Place asked while the assembly's agent is in its turn opens the part once the turn ends; a double-click then is refused rather than stopping the agent
Both commands answer queued: true when they wait for the agent's turn, and stopping the agent forgets what it queued
An undo, a queued command or a delete check running in the design holds up entering and finishing an edit
A refresh redraws every edit of the assembly, the parts in other tabs too
In an assembly never saved, a double-click activates the linked component as before
The control and MCP docs list the new batch and script refusals, and the commands list every way they fail

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: fixes from the third full review

The MCP batch tool refuses the two commands however a step names them, an execute step too
A queued Edit in Place is checked fully when asked for, a second one is refused, and both queued requests wait for what runs in the design instead of being dropped
Disconnecting the agent forgets what it queued, as stopping it does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Edit in place: help text for the Finish Edit button

main now requires help for every toolbar command (#7134), and Finish Edit
is one. Written in every language the branch's catalog carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:57:44 +00:00
dudedagger42 4a34a258e1 Logo: an option to draw it in the theme's accent (#8133)
* Logo: an option to draw it in the theme's accent

Preferences > Interface > Logo: Theme's colours (the default, as before) or
Accent, three shades of the theme's accent. ui.prefs logo_accent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Logo: US spelling for the option's label, as upstream's English catalog uses

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Translations for the new options in the five complete catalogs (ar, he, ja, vi, zh)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 15:04:53 +00:00
Herperlerpicus 3a951bc8c3 Sketch: dimension new shapes as drawn (squashed onto current main) (#5987)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:57:54 +00:00
Lars Jansen 67d5051792 Ribbon: keep the SKETCH tab shown outside a sketch (#7904) (#7906)
* claim: #7904

* feat(ui): keep the Sketch tab shown outside a sketch; its drawing tools start one (#7904)
2026-10-28 14:14:08 +00:00
raykholo 5f90d06452 Preferences: reverse vertical pan direction (#5240) (#5454)
* claim: #5240

* Preferences: reverse vertical pan direction (#5240)

Add "Reverse vertical pan direction" beside the horizontal setting in
Preferences > Navigation. pan_reverse_y defaults off, so older settings
files load unchanged, and flips the vertical part of two-finger pan on
every canvas through navigation::handle, independent of the horizontal
setting. Labels in en, ja, zh, de, and ko.

* Reverse vertical pan: strings as a pending locale file, with Arabic, Hebrew and Vietnamese

* Control protocol: pan_reverse_y in the sorted ui.prefs list (#5240)
2026-10-28 13:59:38 +00:00
Mateusz Sych e181015fd1 MCP save: a folder the agent opened or saved a design in stays in scope (#7181) (#7216)
* claim: #7181

* MCP save: a folder the agent opened or saved a design in stays in scope (#7181)

The agent's default folders held the open design's folder only while that
design stayed open there, so after a new design, an opened STEP file or a
save-as elsewhere a save beside the earlier design was refused, while the
same save through the control port worked.

The MCP server now keeps, for the rest of its run, the folder of every
design file a call opened or saved (open, save, and doc.open, file.save,
file.save_as through execute or batch, path given in full) and, headless,
of every design open in its session. Such a call only succeeded because the
folder was already in scope, so naming a path adds nothing. The folders get
the open design folder's terms (inside home or temp, not hidden, hidden
entries unreachable), at most 16. Bridged, they go to the app as
design_folders, which it judges the same way.

The save tool description and docs/mcp.md say how to add a folder with
--allow-path.

* MCP scope: a design's folder is the folder its file resolves to (#7181)

A link in another folder to a design inside the agent's folders passes the
scope check, which follows it, but its own folder was what got remembered
(and, for the open design, what counted while it was open). Take the folder
of the file as the check resolves it.

* Control test: a hidden file the export format accepts (#7181)

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-28 12:22:20 +00:00
raykholo db999b2a98 Control protocol: the ui.prefs settings as a sorted list, one per line (#7747) (#7988) 2026-10-28 12:07:43 +00:00
CamWight 303fddb20e Browser: Bodies folders only where they help: Always, Several bodies only (the default) or Never (#4217) (#4219)
* claim: #4217

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Browser: Bodies folders only where they help: Always, Several bodies only (the default) or Never (#4217)

A new preference on the Interface page, in the Layout section under Browser, sets when a
component's bodies sit in a Bodies folder of their own. Several bodies only lists a component's
lone body, when it has no groups, straight under its placement. Never lists every component's
bodies and groups there. Always keeps the folder as before. The design's own Bodies folder and a
folder hidden with its eye always stay.

One rule, browser::bodies_folded, decides it for the rows and for the menu. A folded folder
draws no row and stays open; its items move up one level, and their own eyes, hover and drops do
its jobs. While a folder is folded, its placement's menu takes the folder's Create Components from
Bodies and Group Selected; New Group and Show All were already there.

ui.prefs takes browser_bodies_folders (always, several, never) and refuses other values; saved
preferences read an unknown value as the default. The s37 scenario sets Always so that it still
checks the Bodies folder's chevron.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Browser: Bodies folders in Arabic, Hebrew and Vietnamese too (#4217)

Arabic, Hebrew, Japanese, Vietnamese and Chinese are complete catalogues, so
every_complete_catalog_carries_every_english_message fails a new message any of them lacks. The
preference's four messages get their Arabic, Hebrew and Vietnamese text, in the words those
catalogues already use for a body and a folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:24:17 +00:00
Lars Jansen 83ac98ac76 Origin plane names: Top / Front / Right (#6491) (#6496)
* claim: #6491

* feat(ui): origin plane names Top / Front / Right (#6491)
2026-10-27 21:06:14 +00:00
sascha2101 42ec27cfe4 Browser with History under it: drag the split between the two cards (#7371) (#7803)
* claim: #7371

* Browser with History under it: drag the split between the two cards (#7371)

Under the browser, History took exactly half the column. The seam
between the two expanded cards is now a grip with the vertical resize
cursor; dragging it moves the split, as the column's right edge moves
its width. The split is kept as the browser's share of the column in
a new preference, browser_share, whose default is the equal split, so
nothing changes until someone drags.

Either card keeps at least its header and two rows. Folding either card
works as before and gives the other the rest; while one is folded or
folding there is no grip. A non-finite share falls back to one half.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

* Prefs: keep the browser share with the History-under-browser settings

Moves the entry so it no longer sits next to the render and dialog
preferences that main added after browser_width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: sascha2101 <221609842+sascha2101@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:59:38 +00:00
raykholo d2f0627421 Follow a theme file and reload it when it changes (#7573) (#7574)
* claim: #7573

* Follow a theme file and reload it when it changes (#7573)

* Translate the follow-a-theme-file strings
2026-10-27 20:08:12 +00:00
Lars Jansen 5a477b7774 Dialogs: open in the left column in place of the browser and History (#6707) (#6712)
* claim: #6707

* feat(dialogs): open in the left column in place of the browser and History (#6707)

* fix(i18n): Vietnamese messages for the dialog placement option (#6707)
2026-10-27 17:59:00 +00:00
Mateusz Sych 9a7b657fdc Assistant: connect the last-used agent on startup (#7009) (#7124)
* claim: #7009

* Assistant: connect the last-used agent and open the panel at start (#7009)

Two Settings > AI options, off by default: when SolidCraft starts, connect
the agent started last (once the installed agents are known; a missing one
is not swapped for another) and open the Assistant panel. Not for runs
started with --control.

A connection that never gets ready (no agent, start error, the agent ends
while starting) is a new Failed state: the header reads Connection failed
and Connect reads Retry. The control channel reports it as "failed" and
takes connect_at_start / open_at_start.

* Assistant: keep the start-up agent when a design replaces the blank one (#7009)

Opening a design over the blank design SolidCraft starts with reset its
chat and stopped the agent connected at start. A chat not asked anything
yet now starts over in place and keeps its agent. Turning AI features
off also drops a start-up connection still waiting for discovery.

* i18n: Arabic, Hebrew and Vietnamese for the start-up options (#7009)

ar, he and vi are complete catalogs on main now, so every new English
message needs them.

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-27 16:38:26 +00:00
Mateusz Sych 2151bc0497 Drive Joints: say why a rigid joint can't be driven and offer Edit Joint (#6981) (#7051)
* claim: #6981

* Drive Joints: say why a rigid joint can't be driven and offer Edit Joint (#6981)

Drive Joints opened on joint 0 when no joint moved, and its preview ran
joint.drive on that rigid joint, so the dialog showed a red "a rigid joint
does not move" with a Create Issue button.

The dialog now says a rigid joint holds its parts still and how to let them
move (Revolute to rotate, Slider to slide, Cylindrical for both), with an
Edit Joint button that turns it into Edit Joint on that joint. Its commands
refuse a rigid joint, so nothing is previewed and OK stays off. A rigid
joint picked in the browser opens Drive Joints on it to say the same; the
joint box lists only joints that move. joint.drive's own refusal names the
types that move and joint.edit.

* Drive Joints: the rigid joint message in Arabic, Hebrew and Vietnamese (#6981)

Main now delivers ar, he and vi complete, so every new message needs them.

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-27 13:20:35 +00:00
Lars Jansen 5fc23436ca History: show the origin and bodies at the top (#6490) (#6495)
* claim: #6490

* feat(history): show the origin and bodies at the top (#6490)
2026-10-27 07:46:25 +00:00
ABDULLAH af07f4e0e5 Arabic interface language with right-to-left text (#3762) (#3768)
* claim: #3457

* Hebrew interface language with right-to-left text (#3457)

Adds a complete Hebrew catalog (assets/locales/he.json, original
translations) and registers `he`.

egui 0.36 shapes each font run with harfrust, so a run of Hebrew letters
is drawn right to left, but it places the runs of a line left to right in
stored order. The new `bidi` module runs the Unicode Bidirectional
Algorithm (unicode-bidi, MIT OR Apache-2.0) over each message of a
right-to-left catalog once, giving egui the runs in display order with
brackets mirrored and placeholders kept whole, while leaving each Hebrew
run's letters in reading order for the shaper. A test lays messages out
with a real Hebrew font and checks where the glyphs land.

Desktop builds append a system Hebrew font (Arial Hebrew / SF Hebrew,
Segoe UI / Arial, Noto Sans Hebrew / DejaVu Sans). Layout mirroring,
wrapped multi-line RTL paragraphs and a web Hebrew font are follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: translate the new Describe Command label; list he in the control protocol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: catch up with main's catalog and the new ribbon (#3457)

- Translate the 258 messages main added since the branch was cut, drop
  the 38 it removed (10 renamed ones keep their translation) and
  retranslate the two whose English changed (toolbar → application bar).
- The timeline title is ציר הזמן, matching the glossary.
- Ribbon buttons split their labels into two lines from the start of
  the string; Hebrew labels come in display order, so the first line
  showed the end of the phrase ("חדשה / סקיצה"). For right-to-left
  labels the first line now takes the words at the end of the string,
  and a shortened line loses characters, and shows its ellipsis, on the
  left. The word-boundary sweep checks Hebrew from the lines the galley
  is built from, since epaint's right-to-left rows carry zero-width
  glyphs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: after rebasing onto main, load the Hebrew face with the cached system fonts

main now searches the system fallback faces once (SystemFonts, on a thread);
the Hebrew face joins that search with its coverage check. Drop the three
camera-animation messages main removed (#4296) from the Hebrew catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: translate the messages main added after the catch-up (#3457)

Translates the messages main added since the last catch-up: the history
bar's buttons and name toggles, the 3D mouse driver and axis mapping, the
thread size columns, the File view (home page), the redesigned Preferences, the new issue report
dialog, free orbit and the assistant's setup card. Drops the one message
main removed. The catalog has every English message again, so the
complete-catalog checks pass for he.

* Arabic interface language (right-to-left, on the Hebrew bidi path)

Adds an original Arabic translation of the whole English catalog
(assets/locales/ar.json, every message) and registers it. `ar` joins the
complete catalogs, so a message added to en.json later fails the build
until it is translated. It goes through the right-to-left path of #3458
unchanged: crate::bidi puts each message in display order and leaves
every Arabic word's letters in reading order for harfrust, which joins
them with the font's own tables. Ribbon labels use the right-to-left line
split from the same stack.

fonts.rs adds a system Arabic fallback after the Latin interface font,
which keeps spaces, digits and Latin text so each Arabic word stays one
shaped run: Segoe UI/Tahoma/Arial on Windows, SF Arabic/Geeza Pro/
Damascus/Tahoma on macOS, Noto Sans or Naskh Arabic/KACST One/DejaVu Sans
on Linux, or NotoSansArabic-Regular.ttf in CRAFT_FONTS_DIR. It is the first
fallback for an Arabic UI (Arial Unicode, a CJK candidate, has Arabic
letters without joining data) and the last otherwise; like Thai and
Hebrew it is never promoted for a CJK interface.

Tests: the catalog comes back in display order with no directional
controls, and Arabic laid out with a real font lands on screen word by word
in reading order.

* Hebrew: review the catch-up translations; restore the camera-animation messages (#3457)

- Review of the 533 messages translated in the previous commit: 21
  corrected. Keys in the motion dialog are keyframes (נקודות מפתח, as
  in Add Key), the Design workspace is תכן as in its label, a dropped
  "(Direct Driver)" is restored, terms aligned with the rest of the
  catalog (פורמט, סוכן קוד, רצועת הכלים), and a few calques reworded.
- Translate ui.animate_view_changes, ui.animation_speed and
  ui.look_at_anim_desc, which main has again, so he stays complete.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the messages main added since (#3457, #3762)

Both catalogs again carry every English message. The 760 messages main added
since the last rebase (render workspace, material editor, standard views,
sheet metal Path Flange, AI app connections, document-on-disk notices and
more) come from A-AL-ANAZI's translations on #3768; the five Perforate dialog
messages are new here. The earlier Hebrew review is kept on top of them, and
33 of the new Hebrew messages are corrected: "completed" was "perfect"
(מושלם → גמור), Regrade read as ranking (now תיקון צבע מחדש), shaders,
guarantee, the Mirror reflection mode, simulations and displacement.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: attribution rows as a pending file

main now takes new ATTRIBUTION.md rows as one file per change
(attribution/pending/), so the he.json and ar.json rows move there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 23 messages main added since (#3457, #3762)

Both catalogs again carry every English message; the two theme-page messages
main removed are dropped. Twelve of the new messages (link updates while
loading, the agent chat's model choice, plugin search, render quality) come
from A-AL-ANAZI's translations on #3768; the sketch plane descriptions, the
rigid group and empty-boolean messages, free sketch points and the web update
note are new here.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 12 messages main added since (#3457, #3762)

Eleven come from A-AL-ANAZI's #3768; "Turn Up Axis" in Hebrew follows the
catalog's existing up-axis wording, and the agent chat's no-tool-call message
is new in both.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 22 messages main added since (#3457, #3762)

* Arabic and Hebrew: a label found by its English text comes back in display order too (#3457, #3762)

* Arabic and Hebrew: translate the 32 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 34 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 30 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 7 messages main added since (#3457, #3762)

---------

Co-authored-by: rootarchitect <7781866+rootarchitect@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Abdullah alanazi <x1700@MacBook-Air-Abdullah-2.local>
2026-10-27 05:05:53 +00:00
Lars Jansen 2d629069c6 Dialogs: OK and Cancel at the top (#6708) (#6713)
* claim: #6708

* feat(dialogs): OK and Cancel at the top (#6708)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:42:23 +00:00
Lars Jansen f1cc49bcdb History: list a sketch under the feature built from it (#6489) (#6494)
* claim: #6489

* feat(history): list a sketch under the feature built from it (#6489)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 00:59:57 +00:00
MAKAO 30f951ecf9 Navigation bridge: a device's own app moves the view (#6094)
A homemade 3D input device's driver app (MAKMOUSE) listens on a loopback
port; with Preferences > Navigation > "Navigate with a device app on this
computer" on (off by default), the desktop app connects, says hello and
reads JSON lines: axis motion (orbit, pan or zoom by mode), zoom steps and
standard views. The motion goes through navigation::device like a 3D
mouse's, only in the focused window; a HID device the app names is left
to it. Documented in docs/3d-mouse.md.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 22:14:52 +00:00
bherbruck 3de2f96b7f Sketch dimensions: double-click a shown dimension in the model view to edit it (#7079) (#7080)
* Double-click a shown sketch dimension in the model view to edit its value (#7079)

A finished sketch's dimensions shown in the model view (Show Dimension) now take a
double-click: the same inline value box as sketch editing opens at the text, Enter
changes the dimension's own expression through parameters.change (one undo step), Esc
cancels. The sketch is not edited and the view does not move. Driven dimensions stay
read-only with a status hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Control channel: ui.selection lists the shown dimensions of finished sketches

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test: a shown dimension that breaks a later fillet reports it, and Undo restores both

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:47:04 +00:00