stack/render-11087
187
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8829c1c3c5 | Render: restore saved shots, progressive images and exports | ||
|
|
6578d591ac |
control::execute: check the undo depth before placing the world for the first-body fit (#5940)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1d387d3f21 |
Measure: the area of a curved face on the exact surface, not the display mesh (#9086) (#11486)
* Measure: the area of a curved face on the exact surface, not the display mesh (#9086) * Measure: a non-straight border edge leaves the band to the mesh; fix the Vec3 imports (#9086) 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> |
||
|
|
fabeaa329a |
Desktop app: closing a design stops its kernel work, and designs build the same on any kernel (#11771)
* Desktop: closing a design stops its kernel work; same result on any kernel A design's jobs now run under a stop token that closing or replacing the design fires: an operation under it refuses to start, and one running ends at solidcore's next check. The kernel it ran on is not used again. Calls that answer from a body itself always finish, since a stopped call can leave what it borrows half-changed, and what fills a body's shared cells is not stopped. Every kernel call starts clean (the same random rays, no stations from earlier calls), so a design builds the same on any kernel of the pool, down to its B-rep records. The pool is bounded: at most 8 kernels wait between calls, and at 256 running calls a new call fails rather than grow or wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Stop tokens: a copy never stops its design; a stopped job can't decide a refusal A copy replacing its own design stopped the token it shares with the design it came from, so that design's later work would be refused. Only the design itself stops it now. Which face a refusal names no longer depends on whether the job that found it had been stopped: the refusal is kept with the body, and a stopped job's probes were all refused, which named the wrong face. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9d1ad9f0b9 |
Feature editor: OK accepts the joint placements a roll back re-solves (#11094) (#11095)
* Feature editor: a roll back's re-solved placements are not a changed design Rolling the marker solves the joints again and stores where that puts each occurrence, so the editor's pinned original differed from its source there and OK was refused with "the original editor model does not match its source design". The check now takes the placements as the roll leaves them. * Feature editor: also accept the ratio and lift of coupled joints that rolling the marker works out 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> |
||
|
|
fbd30b0bd0 |
Panels: inspect and change layouts through commands (#11304) (#11454)
* claim: #11218 * Panels: add shared layout rules and retained content runtime * claim: #11304 * Panels: inspect and change layouts through shared commands (#11304) * Panels: account for layout commands in geometry coverage |
||
|
|
dc38349cbf |
Layer split stage 1: the B-rep record, native body file and Vec/Plane come from solidcore-record (#11496)
* Kernel: the B-rep record and the native body file come from solidcore-record SolidCraft's portable B-rep record (`solidcraft_geom::brep`: brep.rs, topology, history, envelope, part, curve2) and the native body file (`solidcraft_kernel::native`: the tagged binary codec and the container) move to solidcore's `solidcore-record` crate: geometry as data, with structural validation and no maths (solidcore's docs/layers.md, stage 1). Every caller uses `solidcore_record::brep` and `solidcore_record::native`; the old copies are deleted. What computes from coordinates stays with the kernel, in geom's `brep`: - `brep::check`: the record's geometric checks (orthonormal frames, non-degenerate planes, unit revolution axes, non-singular placements). `check::validate` and `check::validate_built` are the record's validation and these together, and every caller of `Brep::validate` uses them, so what is accepted is unchanged; - `brep::label`: a surface's natural ranges (a cone's apex), `curve_interval`, `edge_curve_interval` and `form_turns`; - `brep::pcurve::eval`: a pcurve's point; - `geometry::check`, `placement::moved` and `split_edges` become functions on the record. The kernel's native module keeps the conversion between a body and its saved record (metadata.rs) and checks the decoded record's geometry. `native/analytic.rs`, which no module declared, is deleted. solidcore-record is pinned to its rev on solidcore's `layer-record` branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Geometry: Vec2, Vec3, Plane and the profile types come from solidcore-record The plain data of vectors and points, sketch planes and planar profiles (`Seg2`, `Loop2`, `Region2`) moves to `solidcore-record`, with its constants and component-wise operators only (owner decision, solidcore layer split). Their geometry stays in geom as traits: `Vec2Geom`, `Vec3Geom`, `PlaneGeom`, `Seg2Geom`, `Loop2Geom`, `Region2Geom`, `Seg2ArcFit`, `Loop2ArcFit` and `Region2ArcFit`, in scope with `use solidcraft_geom::prelude::*`. Every caller names the types from `solidcore_record`; geom no longer defines or re-exports them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Kernel: pin solidcore-record to solidcore main f5e8e9a29 solidcore-record is merged on solidcore main (tangency-labs/solidcore#2519); its crate there is identical to the rev pinned before but for its clippy configuration. The lock is regenerated against the merged rev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ac3e6e0105 |
A panic solidcore's guard catches reaches the engine as EngineError::Internal
smlib's run() catches a solidcore panic and replaces the kernel (kept: the app does not die natively), returning Error::Internal; the kernel turned it into KernelError::Failed and the engine into Other, so hostile_params_never_panic and the fuzzer no longer saw kernel panics. Now the kernel's wrapper errors go through KernelError::smlib, which keeps Internal; a body the wrapper could not take because of a panic is Internal too. A feature whose evaluation hit it records the result as internal (not cached: the kernel was replaced), and the command that made it, or any command whose kernel call returns it, fails with EngineError::Internal under its own id. Crash reports mark a panic inside a solidcore call recovered (kernel::guarded), and the crash test's kernel mode panics inside a solidcore call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DtL5M41G8Nua7HvuFPZkmJ |
||
|
|
ea772a0438 |
Merge develop into main: SolidCraft on the SMLib kernel (v1.1.0-alpha) (#11351)
* UI: rim and wall picking tests for a circle of arcs that is one wall A circle drawn as two half arcs now extrudes to one full-turn wall with its seam edge, and each rim is one closed edge (tangency-labs/smlib#67). The tests keep their intent on that body: a rim clicked once is one item, measured and highlighted whole and picked from either side; a wall picked either side of its seam is the same surface, lit whole, and toggles off from the other side; every face is its own patch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fillets: a later round at a corner where earlier rounds meet blends them again with it The owner's ruling of 2026-10-30: a later fillet on an edge at a vertex where earlier rounds already meet in a mitre makes the corner rounding all of them at once makes, one smooth patch, the mitre gone. A body made by constant-radius rounds keeps what they were made on and which edges they rounded at which radius; a later round reaching such a corner blends the earlier rounds' edges (from the earliest of those meeting there on) with the new edges in one SMLib blend of the body before them. The result's history is put over the body the later round was given: an earlier round's face is that face trimmed anew (its name kept), the corner patch and the new rounds are the later fillet's. A picked mitre seam has no round of its own: it is refused unless a new edge of its radius meets it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: a later r3 round at an r2 mitre, through the Fillet feature, makes the all-at-once corner Two box edges rounded r2 in one fillet, then the upright edge at their mitre r3 in a second fillet (tangent chain on, so the seam comes with it): 10 faces, 7928.743041 mm³ as fillet_radii of the box gives, the r2 rounds' names kept, the r3 round and the corner patch the second fillet's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Kernel: a body's record of rounds goes with its history, and can be read back The rounds that made a body are over the body its history is over: a new history (an operation carrying a step's result back to its own operands) leaves the record out, so a later round never reads one history against another body. Body::rounds gives the record and Body::with_rounds_of takes one back, checked (edges of the body before them, a fillet's radii, the body's history over that body), for a saved model to keep it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Model cache: a body made by rounds keeps them, so a later round blends them the same after opening A design gave another body when opened from its model cache: the rounds a body was made of lived only in memory, so a later round at their mitre was built sequentially (or refused, as too large) after opening and blended with them when evaluated anew. The saved model now records, per kernel body made by rounds, the body they were made on (a place in the bodies, stored once though no state holds it) and the edges with their radii; reading it attaches them back down each chain, and a thinned model keeps those bodies with the bodies made from them. Model cache format 7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: a corner patch of rounds 2/3/4 takes no more than the strips leave in its block three_rounds_at_a_corner bounded the patch's extra cut at 3 mm³ beyond the strips, a figure with no derivation; SMLib's all-at-once body at radii 2, 3, 4 takes 3.099 (V 7878.579574 against strips 7881.678). That body is the strips' outside the block its patch lies in: its rounds are the strips' cylinders ending at a's section y = rc, b's x = 20 − rc and c's rails where they meet a's and b's (the patch's four corners, now asserted), so the patch takes at most what the strips leave in that block (11.86 at 2/2/3, 32.69 at 2/3/4). The lower bound is that block; the upper one, at most the strips' volume, stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: the io crate's hand-built saved models list their rounds, as format 7 records do Model cache format 7 ( |
||
|
|
3c806394b0 |
Edit Sketch: restore timeline and undo state when finishing (#10691) (#10791)
* claim: #10691 * Fix sketch edit completion history (#10691) |
||
|
|
a22ea76ab6 |
Feature editor: a section, an analysis or the selection changed while it is open leaves OK and Cancel working (#10687) (#10822)
The editor accepts revision changes that only changed what is shown,
counted by the display revision, but only hiding and showing counted
there. Section Analysis, the surface analyses, continuity, the
selection, the status pill catching up and view.render_select bumped
the revision alone, so turning a section off with an editor open made
OK refuse ("the design changed while the feature editor was open") and
Cancel leave the timeline rolled back. They now go through
refresh_display, as visibility changes do.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
36bdf4ea3c |
Sketch drag: drop the second document copy per frame (#10507)
* claim: Sketch drag: drop the second document copy per frame * Sketch drag: drop the second document copy per frame edit_solved copied the document to edit it, then stored it with `*s.doc_mut() = doc`. The command's undo snapshot still holds the old document, so doc_mut copied the whole design a second time only to overwrite it. Store the edited document with Session::set_doc instead, which forgets the same caches and puts it in a new Arc. The design lands at a new address as before and the command's end records it for the crash journal (#7502). A live drag frame on a design of 200 sketches (20k curves) drops from 19.2 ms to 9.4 ms; 50 sketches: 2.3 ms to 1.7 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Markus Kaltenbrunner <kaltenbrunnermarkus@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ab6e6941c7 |
View: look hidden bodies up in a set (#10496)
* claim: View: work out consumed sketches and hidden bodies once per revision * View: work out the sketches features use once per design Each sketch_shown call walked every feature of the design to tell whether the sketch is used, and the viewport asks about every sketch several times a frame. The used sketches are now gathered into a set once per design (keyed on the design itself, so any edit reads them again). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * View: look hidden bodies up in a set body_visible walked the hidden-bodies list for every body asked about, and the viewport asks about every body several times a frame. The hidden bodies now join the hidden joints and folders in the view's visibility index, built when the list changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Markus Kaltenbrunner <kaltenbrunnermarkus@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2b65164159 |
View: work out the sketches features use once per design (#10545)
* claim: View: work out consumed sketches and hidden bodies once per revision * View: work out the sketches features use once per design Each sketch_shown call walked every feature of the design to tell whether the sketch is used, and the viewport asks about every sketch several times a frame. The used sketches are now gathered into a set once per design (keyed on the design itself, so any edit reads them again). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Markus Kaltenbrunner <kaltenbrunnermarkus@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b7a6967ef2 |
Web app: open a design a few features a frame, with progress and Cancel (#10275)
* Engine: open a design a feature at a time (#10198) OpenSteps splits doc.open of a design into steps for a caller that must keep working meanwhile (the web app, which has one thread): start reads the file, each step evaluates the next feature by moving a copy's history marker one feature on (so every result before it is reused), and finish puts the design in the session's place with doc.open's reply. The next feature's imported STEP text is offered first, so a caller can read it in parts. Session::opened and opened_at are split into small helpers so both paths build the session the same way; doc.open is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Web app: open a design a few features a frame, with progress and Cancel (#10198) On the web, a design to open is now a staged file load like a STEP file (#1376): its features are evaluated for about 30 ms a frame through OpenSteps, a feature's imported STEP file is read a solid per frame first and held so the feature finds it read, the progress card counts the design's features, Cancel works between steps, and the meshes are made a few per frame afterwards. The desktop app keeps its worker thread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ed66adac5c |
Keep renamed bodies visible when reusing hidden names (#10163) (#10175)
* claim: #10163 * fix(engine): preserve visibility when renaming into hidden names |
||
|
|
34c378c063 |
Save As: rename the design to the new file's name (#4907) (#10036)
* claim: #4907 * Save As: rename the design to the new file's name when its name was borrowed (#4907) --------- Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com> |
||
|
|
5b6e5815a3 |
Engine: lower the per-command cost of evaluating large designs (#9615)
* claim: Engine: lower the per-command cost of evaluating large designs * Engine: lower the per-command cost of evaluating large designs - The fingerprint texts of features are kept in one store shared by every worker, not per worker: a command evaluated ahead runs on a new worker each time, where the per-worker store was always empty and every feature was written out again. Same texts, same hashes. - Pinning body names after a command keeps, per feature, the names of the bodies it made with the state they were read from, so it no longer searches every result's bodies (features x bodies per command), and finds results by their index before searching. - Pinning fingerprints the timeline again only from the first renamed feature (or a pattern or mirror of features replaying one) when the model proves its fingerprints are the design's; the fingerprints are those of the full pass. - The evaluation cache's byte count looks bodies and sketches up instead of searching them per body (bodies squared per feature). Same counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
fa21db7df8 |
Save: hard-link the backup copy and check for unsaved changes once per revision (#9617)
* claim: Save: hard-link the backup copy and check for unsaved changes once per revision * Save: keep the backup as a hard link and check for unsaved changes once per revision The backup of a save is the old file under a second name (a hard link renamed over the old .bak) instead of a copy written out again; where links are refused (FAT, shares, cloud folders) or the old file cannot be flushed, it is copied as before. Every point a save can stop at leaves the design file whole and the backup the version before it. Session::is_dirty compared the whole document with the saved one each time it was asked, which the window does every frame for every tab. The answer is kept per revision and pair of documents; the cache holds both, so neither can change in place while it stands, and doc_mut lets it go first so edits stay in place. On the rover in two unsaved tabs an idle frame takes 15.0 ms instead of 19.3 ms; a save with its backup of the 11.8 MB file writes in 9.6 ms instead of 18.9 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
affe37bcc3 |
Body names: inspect.interference refuses an unknown body; appearance.chain and appearance.list take a placed copy's name (#9740) (#9856)
* claim: #9740 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ * Body names: inspect.interference refuses an unknown body; appearance reads take a placed copy's name (#9740) inspect.interference dropped a name that is no body, so a misspelled or wrongly cased name left that body unchecked and two overlapping cubes answered count 0. It now refuses the name, as inspect.clearance does, naming the closest body when one is near enough to be a typo or another case (cmd::no_body, on the existing edit_distance). appearance.chain, appearance.list and appearance.replace's scope take a placed copy's name (KB (K:2)) and a placement's (K:2) for the body and component they show, as appearance.assign already does, through two Session helpers: own_body_name (on body_frames) and component_or_placement, which appearance.assign now uses too. A name that is neither is still refused. select.set already refuses an unknown body on main (#9737). 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> |
||
|
|
91aefd5abc |
Refuse sketch values that collapse a curve in settle_value_edit (#9729) (#9837)
* claim: #9729 * Refuse value edits that collapse a sketch curve: settle_value_edit runs settle's shrunk/flung checks (#9729) * rustfmt --------- Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com> |
||
|
|
3b77567932 |
Docs: joint flip needs x for point origins; checkpoints are single use, 16 kept (#9746) (#9844)
joint.create's flip text and the assemblies guide said two origins at one point with the same z stay as they are; a point origin without x takes its x from z, so a part turned about z turns back. Say so, and point to giving x on both origins or joint.as_built. edit.checkpoint and edit.restore_checkpoint now say that restoring or forgetting uses the checkpoint (and later ones) up and that only the last 16 are kept, and the "no checkpoint N" error says why. The editing and mechanisms skills no longer read as if a checkpoint can be restored twice. Co-authored-by: thocsmith <193096300+thocsmith@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
810a9558bd |
perf(#3892): index the hidden joints and folders of the view (#9823)
The browser asks about every joint of the design on every frame, and the answer walked the list of hidden joints: a nested STEP assembly hides thousands of them, so a frame cost grew with the size of the design. Session keeps the hidden joints and folders as sets and answers from them. The sets are built when the view changes and kept until it changes again: the revision says the design changed, and the lists say the view changed under it (the view is replaced outside the engine too, without a revision of its own). The behaviour is unchanged: the hidden joint stays hidden, the shown one stays shown, and undo and redo keep the hiding right. |
||
|
|
5bd5be9543 |
Viewport status item: standard details card (#8613) (#8614)
* Keep viewport summary menus below modal owners * Build viewport status details from shared blocks * Keep details focus checks outside context data locks * Preserve native editor Escape ownership in details cards * Initialize strict contract test sessions directly * Translate viewport status detail cards * Use inferred slider options and test legacy Section editing |
||
|
|
4973638b56 |
Selection follows body rename so Delete targets the right body (#9737) (#9789)
* claim: #9737 * Selection follows body renames; stale body selections are dropped (#9737) --------- Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com> |
||
|
|
4ba6a9744b |
Browser: allow nesting groups and re-ordering groups & components (#9109) (#9116)
* Browser: nest groups and reorder components Groups can hold other groups (up to 8 levels) and be reordered with the items around them. Sub-components can be reordered too, through a new `components` list in `browser_order` that is not drawn as a folder. Document: `BrowserGroup` gains `parent`; group items and `browser_order` lists hold `BrowserEntry` values (a number is a group, a string an item). One pending format file; older designs read unchanged. Loading and refreshing drop what the lists name that is gone, and cut cycles and over-deep nesting to the top level. Engine: `browser.group` takes `parent`; `browser.move`, `browser.order` and `browser.ungroup` handle groups. A change to only the browser's groups and order no longer re-evaluates the model. UI: nested rows, dragging a group row (top of a row: before it, the rest: into it), New Group inside a group, and dropping a placement on the top of a sibling to reorder it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Fixed formatting Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Fixed unintended side effect in render scene browser test Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Preserve group order in render workspace Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Increased test coverage Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Updated clipboard test from upstream main for group item type Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
085853315d |
Sketch: copy completed sketches between designs (#5427) (#8962)
* claim: #5427 * Sketch: paste completed sketches across design tabs |
||
|
|
3c40edd12a |
Print face: Send to Slicer lays a body on its marked face (#8429) (#8433)
* claim: #8429 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Print face: Send to Slicer lays a body on its marked face (#8429) A body can have one flat print face (Document::print_faces, held by the certified target a sketch on a face holds). body.print_face {body, point?} marks or clears it. Send to Slicer, Save Mesh with a slicer and EasyPrint turn and move the exported copy so the face lies on the bed at Z = 0 with the centre of mass over the origin; a face that can't be found is a warning and that body is exported as it lies. Move/Copy and Mirror give a copy its source's print face. One pending format file; the command has its own icon (print_face). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Print face: Ctrl+B, the face menu and the Send to Slicer row (#8429) Ctrl+B and the face context menu mark the selected flat face as its body's print face, or clear it. Send to Slicer shows the print face of the one body being sent in a Print face input, takes a flat face picked in the viewport and clears it when emptied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Print face: a light tint in the viewport and its strength in Preferences (#8429) Each visible body's print face is tinted towards the theme's section colour and outlined, at the strength set under Preferences > General > Slicer (print_face_highlight, 0 to 1, 20 % by default; 0 hides it). The user guide describes the print face, and the known limitation after a shell of a shelled body is listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3b8cbc4e22 | Viewport: surface analysis status items and legend keys (#8547) (#8556) | ||
|
|
2356a63aea |
CLI: run takes --param-check (#6921) (#6924)
* claim: #6921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CLI: run refuses unknown options and takes --param-check (#6921) `solidcraft-cli run` now checks its options through `known_args`, so a mistyped option fails instead of being ignored, and takes `--param-check off|warn|strict` with the MCP server's words and default `off`. `warn` prints each unknown key with a suggestion on stderr and runs the step; `strict` stops at that step and writes nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CLI: run's option check takes --param-check; warn on timed runs as steps complete `run` keeps #6919's (#6918) unknown-option check, with `--param-check` among the options that take a value. `Session::run_script_timed` now takes the same per-step callback as `run_script_each`, so `run --timings` or `--profile` at the warn level reports a step's warnings even when a later step fails, instead of after the script (and not at all on a failure). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cb34eef6aa |
Settings profiles: save, switch, export and import input and interface settings (#6237) (#6254)
* claim: #6237 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Settings profiles: save, switch, export and import input and interface settings (#6237) A profile keeps the Interface, Navigation and Sketch preferences (mouse mode, radial menu and gestures with every studio's lists, theme, scale, font, ...), the language, the keyboard shortcuts, the toolbar, the S box favourites and the imported theme it uses under a name. Machine-specific settings stay out (3D mouse, graphics, units, AI, recent files). - Preferences > General > Settings profiles: choose the active profile to apply it, Save, Rename, Delete, Export... and Import...; a note shows when the settings differ from the saved profile; Cancel takes a switch back. - settings.profile.{list,save,apply,rename,delete,export,import} commands for the control channel, palette and scripts; the engine checks the parameters, the app does the rest. - One `solidcraft-profile/1` file; import checks the format and name, drops unknown keys and unreadable values, caps sizes, never switches, and never panics. Each preference is applied through prefs::set, so a value this computer refuses keeps its current one and is reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Glossary: settings profile, and "profile" among the words with more than one meaning (#6237) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Settings profiles: new strings in a pending locale file, not the catalogs (#6237) New UI strings now go to assets/locales/pending/ (CONTRIBUTING.md), so this pull request no longer edits the shared catalogs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Preferences snapshot: compare the toolbar, favourites and profile too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Settings profiles: keep a command's several keys (#6237) Since a command can have several keys (#6288), the keymap saves a list where it has more than one. A profile's checks only took a single key, so saving or importing a profile dropped such a command's shortcuts. They now read the keys as the keymap does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Settings profiles: Arabic, Hebrew and Vietnamese strings (complete catalogs) (#6237) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Tripper <tripper@localhost> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
5f11d92458 |
Opening a design pins its body names, so the first undo evaluates nothing (#8939)
Problem: a design saved before body names were pinned (#6403) is pinned by its first command that changes it, as part of that command. Undoing that command went back to the unpinned design, whose fingerprints no evaluated result matched any more, so the first undo after opening evaluated the whole timeline again: 63-72 s in the SELENE rover (5,484 features) when opened from the command line or headless (`Session::opened_at`), 0.08 s with this change. `doc.open` pinned at the end of the command instead, which kept undo fast but left the design with unsaved changes on opening. Solution: `Session::opened_at` pins the names as it opens the design, with the names the file's bodies have (no result changes, so nothing is evaluated), and takes the pinned design as the saved one: opening is no change. Claude-Session: https://claude.ai/code/session_013WUFq6QFBqmZjxwaKy2J1M Co-authored-by: Markus Kaltenbrunner <kaltenbrunnermarkus@users.noreply.github.com> |
||
|
|
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) |
||
|
|
d6d6c7d9ee |
Copy and paste bodies and components between designs (#3511) (#3512)
* Components: copy and paste bodies and components between designs and components (#3390) Squashed for the rebase onto main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * claim: #3511 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Paste New: copy from a design other than the one pasted into `component_clone::paste` read the design it copies from through the session it pastes into. `build` now takes the source (document, evaluated model, unapplied moves) apart from the target session; Paste New within one design passes the session as both, as before. Names are numbered against the target's names. From another design (`Source::copied`, a `ForeignCopy` snapshot taken at copy time): - names are kept where the target doesn't have them, else numbered; - the user parameters the copy uses come along, `w_2` where the target has a `w`, with the copied expressions following; - a copy whose features use what isn't in it (bodies, sketches, faces, parameters outside it) is refused with a list of what; `FeatureKind::input_bodies` lists the bodies a feature uses; - configurations stay with their design, and the target's timeline marker must be at the end; - a body moved in from outside comes as an imported base named `BodyImport1`. Body transfers are pointed at the copy's components before they are added: `add_feature` checks that the components they name exist, which another design's don't. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: paste bodies and components copied in another design `component.paste_from_design` pastes what `Session::foreign_copy` holds, at the same world coordinates as in its design, into the active component or `component` (placed by `component_path`; a component placed more than once gets it in every instance), as one step to undo: - bodies as imported bodies, without their history, in one Import feature (named as any import is, "Import1"); a body seen in another placement ("Cube (B:2)") pastes as "Cube"; names the target has are numbered; - components as independent copies (Paste New from the snapshot): with their history, appearances, materials, joints and motion inside them; joints to the outside stay behind. Tests: bodies (position, naming, target component, undo; a body of another placement) and components (history, appearances, a part placed twice, editing independently, save and reopen, undo; user parameters renamed; refused when using a body outside it; bodies moved in). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Clipboard: copy in one design, paste in another Copying or cutting bodies or components also keeps a snapshot of them (`ForeignCopy`); another tab pastes it with `component.paste_from_design`: bodies as imported bodies, components as independent copies (Paste and Paste New alike), folded and selected. Cut pastes as a copy there, the original staying; Esc on the cut leaves nothing to paste anywhere. The last copy in any design is what pastes: each copy or cut is numbered, and a tab whose own copy is older empties its clipboard when it is switched to (`drop_stale`). A failed copy anywhere leaves nothing to paste in any tab. Tests: bodies and components pasted in another tab, the last copy winning across tabs, cut as a copy. `copied_bodies_stay_with_their_design` gave way to the cross-design test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Clipboard: what is selected wins over a design row picked earlier Copy copied the whole design as a linked component whenever the design's browser row was still picked, even after a component, body or feature had been selected in the view or another tab, and failed in an unsaved design. The design row now gives way to anything selected, and switching tabs drops the picked components of the design left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Put the Paste from Another Design label in the pending locale file Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: unground the placement before moving it (a design's first part is grounded) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop locale keys main already folded into en.json Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pending locale: Paste from Another Design in the complete catalogs 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> |
||
|
|
443e5cd59d |
Feature editor: allow visibility changes while editing (#8810) (#8827)
* claim: #8810 * fix(engine): preserve feature editors across visibility changes (#8810) |
||
|
|
3cc10acafa |
Render lights: uniform light list, solo and mute, and the Light editor (#6281) (#7265)
* Render lights: uniform light list, solo and mute, and the Light editor * Render lights: Lighting and Light editors to the approved design * Render lights: the scale-test frame carries the product light list * Restore the stable Render light mute target on the shared eye control * fix: validate the viewport BRDF probe with current shader dependencies * fix: compile legacy lighting controls only for tests * fix: scope the legacy lighting preset import to tests * fix: reuse the merged Add Light label and translations * test: enable the implemented Add Light radial action * fix: restrict the legacy CPU vector editor to tests * test: reveal Output before checking Lights browser focus * test: use the published Browser card rectangle for Output scrolling * test: reveal Output children before exercising editor navigation |
||
|
|
c1925bb219 |
Render appearance: click, drag and paint to assign, Pick Up, copy and paste (#6281) (#6431)
* Render appearance: click, drag and paint to assign, Pick Up, copy and paste, and Remove * Exclude the workspace Shots strip from dialog width checks * Exclude the collapsed Shots control from dialog width checks * Retain assembly cache listings and measure actual dialog bounds * fix: handle toast button rectangles in assignment status * fix: restrict gallery note measurement helper to tests * test: measure assignment help at the catalogue footer * fix: share the command revision snapshot after restacking |
||
|
|
e6dc105134 |
Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151) (#5381)
* Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151) A point cloud is kept in the design as a reference, drawn as depth-tested dots and never a body. - io: a PLY reader (ASCII, binary little/big endian; x, y, z of any numeric type, optional colours, other elements skipped; counts checked against the file) and XYZ/PTS text, thinned evenly past max_points. PLY meshes with faces can also come in through file.insert_mesh. - doc: Document.point_clouds (shared f32 points relative to an f64 origin, colours, units, rigid placement, size and colour), stored as a binary container part; format change in pending/point-clouds.rs. - engine: pointcloud.insert / edit / delete / list; doc.open opens a cloud as a new design; selection.delete takes point_clouds; view bounds include them. - gpu: an instanced point-sprite pipeline (16 bytes a point). - ui: Browser Point Clouds folder with eyes, menu and an Edit Point Cloud card; drop, Open, Insert and file dialogs take .ply/.xyz/.pts; a CPU viewport fallback; messages in en, en-GB, ja, zh, de and ko. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: colour by the file, one colour or height, from the UI (#5151) The Edit Point Cloud card gets Color By (File Colors, Single Color, Height). Height is a blue-to-red ramp over design Z, between the cloud's own two heights or, by default, a range worked out from the points (all but the lowest and highest 2 %, from an even sample). pointcloud.insert and pointcloud.edit take color_by and height_range; pointcloud.list reports them. The colour of each point is worked out in one place (PointCloud::shade) for the GPU and CPU viewports. Also: the card's dropdowns compare the picked index (a dropdown's response doesn't report the pick, so File Units did not change either). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: integrate format registration and viewport caches (#5151) * Point clouds: satisfy current UI audits and document comparisons (#5151) Route model RGB data through the theme conversion boundary, provide a compact ribbon label, and include point clouds in the new document comparison. Gate the Unix-only CLI-link helper and test so Windows all-target checks remain buildable after the rebase. * Point clouds: isolate translations for current main (#5151) Move the existing 74 messages unchanged into one pending locale file and attribute it through a pending row, following the current repository workflow. Repository checks, 50 tooling tests, final workspace Clippy, wasm and generated-catalog equality checks passed after the rebase. * Point clouds: fit the rebased code to main's GpuTarget and Frame Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Compare point clouds when reusing placement-independent results Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point clouds: complete command help and required translations (#5151) * Point clouds: size the save cap from the raised limit 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> |
||
|
|
866029aaa2 |
Engine: one sketch store for the sketch commands (W38.0, #5425) (#6336)
* Engine: one sketch store for the sketch commands (W38.0, #5425, no behaviour change) The sketch commands found and kept the sketch they work on in about forty places, each its own way. They now go through one module, cmd::sketch_store, so a drawing session (W38a/b) can put sheet and view sketches behind the same calls without the commands changing again. - target: the command's `sketch` param or the sketch being edited (target_sketch, moved). - active: the sketch being edited, if any. The thirteen commands that need one keep their own refusal text; unifying the three texts is a separate, visible change. - read and write: the only calls from the sketch commands to Document::sketch and sketch_mut. - update: change a sketch on a copy of the document and keep both, the edit the text and link commands made by hand (sketch.text, sketch.edit_text, the projection, intersection and include links, sketch.fit_curves_to_section, sketch.break_link). As before, those paths neither solve the sketch nor run its checks. - checked: the checks an edited sketch passes (the periodic splines), shared by edit_solved and sketch.offset.break. edit and edit_solved stay in sketch.rs and load and keep their sketch through read and write. Imported text, snap points and the face projections keep their own shape (a text that can't be linked is skipped, snap points copy the document only when one is needed) through read and write. The reads and writes that are about the design's own sketches stay as they are, each on a line marked `// design-only:` (Redefine Sketch Plane, a joint's curve, a motion trace's wire, and the session's live drag, parameter edits and `created` diff). A source scan, each_sketch_command_goes_through_the_store, fails when a command reads or writes a sketch, or asks for the active one, anywhere but the store or a marked design-only line in the files that work on the design's sketches. Every existing sketch test is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: the sketch store's scan also catches the active sketch taken as a value (#5425, review of #6336) The scan only caught `active_sketch.ok_or`, so main's `let Some(id) = s.active_sketch else …` could have come back unseen (0xlillith's review). It now also flags the value-read forms: `) = s.active_sketch` (let-else and if let), `=> s.active_sketch` (a match arm), `s.active_sketch.and_then(` and `s.active_sketch.map(`. State checks (`is_some`, `is_none`, `== Some(`), assignments and snapshot copies stay allowed. The wider scan found five commands that hand-rolled the store's `target` rule (a `sketch` param or the sketch being edited). They now call `sketch_store::target`: sketch.inspect, sketch.glyphs, sketch.export_dxf, inspect.curvature_comb and inspect.minimum_radius (their `curves` form). Their refusals become target's: - no `sketch` and none being edited: "no sketch is being edited" (was "no such sketch (and none is active)", or "no such sketch" for sketch.glyphs); - an unknown name or id: "no sketch `X`" (an unknown id used to reach "that sketch is not evaluated"); - a feature that is not a sketch: "`X` is not a sketch"; - a `sketch` that is neither an id nor a name (true, a list, an object): refused, where it used to fall back to the sketch being edited. A null `sketch` still means none given (the scenario harness sends one): target now reads it that way for every sketch command (target_reads_a_null_sketch_as_none_given). No test, doc or schema text named the old wording; the params docs ("sketch?: id|name (default active)") still hold. The two remaining value reads, the default sketch for a feature (features.rs) and the sketch a measurement prefers (measure_sel.rs), go through `sketch_store::active`, with no change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: a number in `sketch` is an exact sketch id, never a name (#5425, review of #6336) `sketch_store::target` turned a JSON number into text and looked it up with `Document::find_feature`, which falls back to a name when no feature has that id. So `{"sketch": 999999}` could pick a sketch named "999999" whose id is something else, and export or inspect it. sketch.export_dxf, sketch.glyphs and the two curvature inspects read an exact id before they moved onto the store; the other sketch commands (the old `target_sketch`) and sketch.inspect read a number as text. One rule now, for every command that takes `sketch`: a number is an exact id (`as_u64`, then the feature with that id); text is an id written out or a name, as before. A number that isn't a whole number of 0 or more (negative, fractional) is refused with "`sketch` must be an id or a name"; an id no feature has gives "no sketch `N`", as before. Nothing in the tests, docs, scenarios or examples names a sketch with digits, so nothing relied on the old fallback. Test (sketch_store): a sketch named "999999" with another id. sketch.export_dxf, sketch.glyphs (with another sketch being edited, for its enabled check), inspect.curvature_comb and inspect.minimum_radius (with a real curve id) refuse `{"sketch": 999999}`, find the sketch as `"999999"` and by its own id, and refuse -1 and 1.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: MidPoint finds its sketch through the store too (#5425, after #5011) #5011 added a caller of the old `target_sketch` (MidPoint's `line_stays`, which swaps a point picked after its line) after this branch's base. It now reads the sketch through `sketch_store::target` and `sketch_store::read`, as the other sketch commands do, so a number there is an exact id too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: standard parts fix their sketch's entities through the store (#5425, after #6376) #6376 (a standard part's sketches are fully defined) reads the sketch being drawn straight from the document's features, after this branch's base. `fix_all` now takes it from `sketch_store::active` and `sketch_store::read`, as the store's scan requires, with the same result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Engine: Toggle Diameter and Delete on a profile find their sketch through the store (#5425) Two sketch commands landed on main after the store: sketch.toggle_diameter (#7729) still called the removed sketch::target_sketch, and Delete on a picked profile (#7107) read the sketch straight from the document. Both now go through sketch_store (target and read), and the store's source scan passes again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sketch dimensioned: use the sketch store's target after the rebase Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sketch dimensioned: read the sketch through the store 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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
65784cae2f |
Save As offers the open file's own name, not the name stored in the design (#8329) (#8354)
* claim: #8329 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ * Save As offers the open file's own name (#8329) Save As, Save As JSON and Save a Copy proposed the design's name, the one stored inside the file. Copies of a file under other names keep the stored name, so "Sample Plate-bug.solidcraft" was offered "Sample Plate.sc", the same as its sibling, and one replaced the other. Session::save_as_name() offers the stem of the open file unless the design was renamed since it was opened or last saved, and the design's name otherwise (a new design, or one renamed in the Browser). 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> |
||
|
|
f103468dba |
Params: a list parameter refuses a wrong type instead of losing entries (#6651) (#6683)
* claim: #6651 * test(#6651): a list parameter of the wrong type is refused A list parameter such as a cut's `targets` or an export's `bodies` loses entries without an error: a value of the wrong type reads as an empty list, which most commands take to mean "every body". The regression test drives the engine the way a user does: two bodies, a box cut that crosses both and is meant for one of them, and a `targets` of the wrong type. The command must refuse it and leave the design as it was. * fix(#6651): a list parameter refuses a wrong type instead of losing entries A list parameter of the wrong type was read as an empty list, and an empty list means "every body" to most commands: a cut meant for one body cut every body it touched and the command reported success. A wrong type is now an error that names the parameter, the offending entry index and the value it got. A list longer than 10000 entries is an error instead of being cut short. `null` stays absent, as the schema contract says, and a plain string is still a list of one. The 80 call sites now propagate the error instead of losing entries; the commands that take feature keys, which may be named or numbered, read them with their own reader. |
||
|
|
3a951bc8c3 |
Sketch: dimension new shapes as drawn (squashed onto current main) (#5987)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7e8f87dc57 |
Extrude: a face shared by two bodies is resolved in the active occurrence (#419) (#6469)
* claim: #419 * fix(#419): a face shared by two bodies is resolved in the active occurrence |
||
|
|
ebdc0bc07e |
Assembly: deeply nested body selection no longer stalls the window (#7502) (#7694)
* claim: #7502 * Assembly: name placed bodies from a per-design index, reveal the Browser from the body's path, evict cache entries singly (#7502) * Release the placement index before in-place document edits so pinning body names stays in place --------- Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com> |
||
|
|
d245541075 |
Reuse placement-independent model results (#6525) (#6527)
* claim: #6525 * perf(eval): reuse local geometry across placement changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(engine): preserve recovery journal through shared refresh The shared evaluator retains the document Arc, so refresh and body-name pinning can copy it after command_done recorded its address. The next read then mistakes that copy for an outside edit and discards the replay. Record completion after refresh, name pinning or failed-command restoration. Add a minimal journaled box/inspect regression in the existing crash suite. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ad749d3399 |
Joints: the model is evaluated for the placements a solve leaves (#7084) (#7085)
Session::refresh evaluated the model and then solved the joints, which writes the solved placements into the design. A feature that reads where a part is placed kept the result made for the placement before the solve: a mirror of a jointed part's body, made from the root, ended up 4 mm below the part after a move the slider took back. When the solve moves parts, the model is now evaluated again for the placements the design holds, and the joints solved for that model, at most three rounds. Features that don't read placements come from the cache. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3ad5a360f2 |
Engine: keep the model and placed world across appearance-only edits (#7396)
Evaluation and placement never read appearances, yet an appearance edit re-evaluated the model and placed every occurrence again. A whole-document proof that only appearances changed now takes the existing render-only refresh, which keeps the model and retargets the world-placement cache. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
614e006eac |
Engine: keep every placed body's frame with the world state (#7411)
Each command that names a body (appearance, material, move, ...) mapped it to its component's own name by working out every placed body's world name and frame, so a command on a large assembly cost a walk of the whole design. The list is now kept with the world-placement cache while it is current. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |