Commit Graph
15 Commits
Author SHA1 Message Date
selune a261aaa841 Render: integrated workspace, preview image jobs and opaque PBR (#1046)
Lands the Render workspace (R3), bounded preview-image jobs with cancellation and atomic PNG export (R4a), and opaque PBR looks as one change.

- Render workspace: an overlay-free product preview on the installed GPU device. Returning to Design restores its camera. render.scene and render.settings.apply are added.
- Image jobs: render.preflight/start/status/cancel/export run bounded CPU preview jobs. Export captures the job, overwrite choice and document, and checks the caller's file scope before writing.
- Opaque PBR: looks can carry metal fraction, roughness and dielectric IOR. The product viewport and preview PNG use them; geometry and mass are unchanged. The v1 catalog export refuses PBR rather than dropping it.
- Render setups and PBR looks are saved under design format 21. Labels are in en/de/ja/ko/zh/ru.

Supersedes #706 and #800. Refs #620, #673, #756, #1004.

Contributed by @0xlillith.

Co-authored-by: lillith <35337584+0xlillith@users.noreply.github.com>
2026-10-14 19:24:36 -04:00
bherbruckandClaude Opus 5.5 6de8f6db95 Agent-built designs: stop redoing whole-design work on every command (#1148)
A design built over MCP is many small commands, and each one did work over the
whole design, so building or showing a 1,300-body design took minutes:

- moved components were transformed and meshed again after every change; world_state
  now reuses each placed body whose definition and placement are unchanged
- next_d_name searched the design once per candidate number
- Document::eval evaluated every parameter for every expression; now only when the
  expression names one
- param_rows' used_by was quadratic; the desktop no longer gathers completions on every
  change while no text box has focus

solidcraft-cli bench-agent builds a generated ~1,300-body bicycle command by command
and times it (241 s -> 16 s here). Eval output is unchanged apart from timings.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:48:39 -04:00
bherbruckandClaude Opus 5.5 1ff16cc72b A hole on a face drills into the material, also in older designs (#950) (#952)
* Hole matrix: placement, types, extents, edits and 0.9.0 designs, with today's failures listed

Each case checks the drill goes into the material, the bore sits on its axis, a blind hole stops
where it should, the removed volume against its analytic value, the face count and that every
body is still one closed valid solid. Failing cases are listed in tests/hole_matrix/known_failures.txt
as a ratchet.

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

* A hole on a face drills into the material, also in older designs (#950)

Without a direction, solid.hole took the direction from any face whose infinite plane passed
within ten tolerances of the point, the last one found winning: the far side of a thin plate or a
face of another body at the same height could set it, and the wrong direction was saved. It now
uses the face nearest the point, against its outward normal (exact for planes, cylinders and
spheres, so holes on curved faces work without a direction). When a design is evaluated, a face
hole whose saved direction leaves the face it starts on is mirrored into it, so designs saved
with the wrong direction drill into the part.

Fixes #950.

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

* Hole at a point on no face (a planar face's centroid outside it) keeps the plane it lies in

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

* Record the hole direction fix in the goldens and the action matrix baseline (#950)

Seeds 7, 21, 81 and 85 drill their holes straight into their faces now. In the action matrix,
holes on four faces that used to go the wrong way now build, and two whose correct direction
meets a cut the kernel refuses are marked failing.

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

* Goldens: seeds 7, 21 and 85 drill their holes straight in (#950)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:45:11 -04:00
Nathan Dane 9f76cca8b4 Collect application resources for #433 (#833) 2026-10-14 00:49:32 -04:00
Jonas Wrede 14635e5d3a feat: user-defined physical materials stored in the design (#532) (#606)
A design can define its own physical materials (material.create, material.edit, material.delete): name, density and an optional look. They work everywhere built-in materials do: assignment, mass properties, colours and configuration cells. Stored in user_materials, an additive field under format 16. Un-ignores the #554 regression test. Fixes #532.

Co-authored-by: jonaswre <jonas.wrede@beyondit.gmbh>
2026-10-13 04:47:23 -04:00
MqriusandClaude Opus 5.5 1d7450b04c fix(doc): To Object takes the face at the pick, not the first body near it (#429)
object_height, curved_target and curved_target_any took the first solid body with any face
within its pick tolerance of the To Object point. That tolerance is 5 % of the body's size,
so a large body beside a small target took picks made on the target: a ridge extruded up
to a post 2 mm above a plate treated the plate as the target, nothing trimmed the tool, and
it ran past the post (to x 9.08 instead of -2.31).

They now share face_at: the nearest face over every solid body, still within that body's
tolerance. appearance gains nearest_face (the face and its distance) and pick_tolerance,
which face_index_at now uses as well.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:55:47 -04:00
bherbruckandClaude Opus 5.5 296683229d Rename SolveCraft to SolidCraft everywhere, with compatibility shims (#389)
* WIP deep rename (not for push)

* WIP2

* WIP3

* WIP4 wxs fix

* rustfmt

* Rename the remaining identifiers in merged crash-report code

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:17:01 -04:00
Iraklis KourtisandClaude Opus 5.5 08cf526fe2 feat(doc): persistent names follow the kernel's exact face history (#136)
Why: every reference a user makes to a face or edge (fillet and chamfer
edges, sketches on faces, shell/draft/offset faces, joints, appearances)
is stored as a name and found again after any upstream edit. Those names
were re-derived by sampling points of each face and voting, and pieces
of a split face were numbered by where their centres lay. After an
upstream edit that splits, merges, mirrors or shrinks a face, a fillet
or sketch could silently re-attach to the wrong face, and nothing told
the user. The kernel now reports exact history for its operations, so
names follow it and fail loudly instead of guessing.

- crates/doc/src/lineage.rs: a feature's kernel histories composed into
  one lineage over nameable operands (bodies before the feature, moved
  copies, shell cavities, tools named by role: sketch curve, cap, box
  side, imported face). Instrumented: extrude/revolve/sweep/loft tools,
  join/cut/intersect, lumps after a cut, fillet/chamfer, shell, draft,
  split face/body, pattern/mirror (bodies and features), combine,
  boundary fill, move/scale, offset/delete face, thread, import.
- crates/doc/src/history_names.rs: names from lineage; split pieces told
  apart by the faces only they touch (F2:top#[F2:side:l4,F4:side:l4]),
  merged faces answer to every name (aliases), lump bodies ordered by
  their faces' names instead of shell order.
- crates/doc/src/name_lookup.rs, piece_names.rs: references resolve by
  exact name, alias or bounding faces, else nearest piece with a
  warning; names worked out from geometry (operations without history)
  are reported when only geometry decided.
- Format 14: names stored by older formats get a legacy mark and are
  found as the build that saved them found them (some geometric names
  name a face history names differently: a tube's outer wall was named
  after its inner circle). New corpus file saved by 9a979cf.
- kernel: Body::lumps carries each piece's history over the whole.
- Adversarial tests: split, merge, mirrored twins, shrink to a sliver,
  moving cut with body pieces, history-less bodies, certified sketch.
- docs/book/src/dev/naming.md describes the real mechanism and why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
bherbruck c1d819f235 feat: preserve body history and placed modelling workflows
Record ownership transfers in the timeline so earlier Join/Cut membership,
world placement, machining data and styles survive component moves, edits,
independent copying, undo and reopening. Preserve pending positions in history
snapshots and keep constructor transfers ordered during feature redefinition.

Retain shallow sheet pockets and exact planar intersection islands through
unfold/refold, with depth-aware flat previews and DXF export. Store explicit
3D wire coordinate spaces and migrate known legacy provenance without moving
saved points or analytic fits.

Infer unique eligible cylindrical Emboss targets, align Revolve manipulators
with actual extent geometry, and discard obsolete preview errors after input
correction. Certify constructed and immutable imported face styles using exact
source metadata while preserving legacy face names. Upgrade designs to format10
with bounded validation and geometry-preserving legacy migration.
2026-10-11 03:59:12 -04:00
bherbruck 0398a813c8 feat: strengthen sketches, feature editing, and independent assemblies 2026-10-11 02:44:31 -04:00
bherbruck 07932d0f42 feat: preserve modeling intent across sketches, assemblies, and fabrication
Persist typed sketch dimensions and bounded ordered configuration rules in format 8. Use exact occurrence paths and source identity for editing, movement, appearance, and mass. Preserve sheet material regions through cutting, folding, and exact DXF export; retain nested cavities and material islands.

Validation: cargo xtask ci passed, including 368 engine tests, 178 UI tests, 68 UI scenarios, 136 kernel tests, and the 10-crate wasm check. Actual preview workflows and legacy format-7 origin-corner reopening were inspected.
2026-10-11 01:28:01 -04:00
bherbruckandClaude Opus 5.5 9ee8ba5dd7 Imported looks outlive later features: a body's imported colour, opacity and face colours (kernel paint, dropped by operations) are carried to the next version of the body, its faces by persistent name (split faces keep the colour, new faces take the body's); assigned face appearances already follow their faces by name
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-09 12:47:56 +00:00
bherbruckandClaude Opus 5.5 294597cc96 Face colours and opacity in STEP and 3MF export (and STEP import)
- Bodies carry a Paint for export (opacity, per-face colours), set by
  Document::painted from the appearance model. The paint comes from a
  face appearance, a body/component appearance's opacity or a material
  look (Glass), and falls back to the paint the body was imported with.
- STEP: faces with colours of their own get a STYLED_ITEM on their
  ADVANCED_FACE. See-through looks add SURFACE_STYLE_TRANSPARENT.
  Differently coloured pieces are not merged into one face.
- STEP import reads face styles and transparency. The reader tracks the
  file face of each kernel face (bands split in two keep it), so imported
  face colours land on the right faces; the design shows them through
  face_colors.
- 3MF: per-triangle colours (pid/p1 into the base materials, carried
  through welding) and the object's alpha (#RRGGBBAA).
- Tests: a blue half-transparent cube with a red top exports, re-imports
  with its opacity and the red top face, and keeps it when opened and
  exported again. 3MF writes the alpha and the face entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 14:02:10 +00:00
bherbruckandClaude Opus 5.5 e7a85b30f7 Persistent naming: joint origins on faces and circular ends, and face appearances, store the face's name and find it by name first (a joint whose face is gone reports it instead of attaching elsewhere)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 11:37:33 +00:00
bherbruckandClaude Opus 5.5 a283e424d9 Appearances on faces, bodies and components (face > body > component > material > imported colour), with names and opacity and a built-in library of 20 (metals, ABS colours, glass, rubber, wood, paint); AppearanceCommand takes bodies, faces (points) or components, a library name or a colour with opacity, or nothing to clear; appearance.library, appearance.list (a body's resolved look and per-face colours); file format 3 turns the old body colour map into body appearances
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 11:37:33 +00:00