* claim: new designs save as .sc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* New designs save as .sc; .solidcraft files still open and keep their name on Save
DESIGN_EXT is now "sc"; DESIGN_EXTS lists sc, solidcraft and solvecraft and
every open path (dialogs, drag-drop, recent files, CLI, MCP, links, the web
picker) accepts all three. Save of an opened .solidcraft file writes that
file; Save As, autosave, recovery and crash reports use .sc. Windows, macOS
and Linux register .sc alongside the older extensions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Update UI tests for the .sc default extension
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The app id moves from ai.storyteller.solidcraft to io.tangencylabs.solidcraft: macOS bundle id
(the CLI signs as io.tangencylabs.solidcraft.cli), Linux desktop/metainfo/MIME file names, icon
name, Wayland app_id / X11 class, Flatpak, Snap common-id, nfpm/FreeBSD/Nix/AppImage staging,
the web app's icon paths and the docs.
Existing installs keep working: the Flatpak repository marks both old ids
(ai.storyteller.solidcraft and ai.storyteller.solvecraft) end-of-life with a rebase straight to
the new id, re-marking the solvecraft ref that pointed at the 0.8 id; the manifest grants
read-only access to both old ~/.var/app folders and the first launch copies settings and
autosaves from the newest one; AppStream <replaces>/<provides> and X-Flatpak-RenamedFrom list
both; the AppImage removes menu entries it wrote under either old id. The data and settings
folders (solidcraft / SolidCraft) are unchanged. The MSI UpgradeCode and ProgIDs are unchanged.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: on Windows, give claude mcp add the CLI's full path (#5895)
The Windows installer puts solidcraft-cli.exe in C:\Program Files\SolidCraft but not on PATH,
so the README's and docs/mcp.md's `claude mcp add solidcraft -- solidcraft-cli mcp` registers a
server that can't start there. Say so next to the command and give the full-path form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: word the Windows full-path note so it holds once the installer sets PATH (#5895)
#5898 makes the MSI add its folder to PATH. Say "if a terminal doesn't find solidcraft-cli
(older Windows installers don't put it on PATH)" instead of stating that the installer never
does, so the note stays true whichever change lands first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: the Windows CLI path is the default, not the only place (#5895)
The MSI installs to ProgramFiles6432Folder and lets people choose the folder
(WixUI_InstallDir), so C:\Program Files\SolidCraft\ is only the x64 installer's default; the
x86 MSI on 64-bit Windows lands in C:\Program Files (x86)\SolidCraft\. Say "by default" in
the README and docs/mcp.md (review on #5896).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* claim: #5734
* Docs: don't offer winget install before the package is in winget-pkgs (#5734)
The README and docs/downloads.md said Windows users could run
`winget install bherbruck.SolidCraft`, but winget-pkgs has no manifests for
bherbruck.SolidCraft (manifests/b/bherbruck doesn't exist), so winget finds
no package. winget.yml only updates a package that is already listed, and
does nothing until then. Drop the command from both pages, and say in
docs/releasing.md that the first version has to be submitted once by hand
and the command added back when it's listed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Releasing: a first WinGet submission is already open; take it up (#5734)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: refresh every UI screenshot, GIF and video from the current UI
Re-record the README demo, the rover build, the sample plate and the class-A surface pictures
with 0.22.1 in the default dark theme. The demo script is fixed for the current sketch dimension
boxes and MCP file limits, and the rover replay and class-A pictures now have scripts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Docs: cut the idle time out of the demo and rover recordings
The README demo plays at 6x and the rover replay at 15x with a constant-rate camera orbit, with the stretches where nothing on screen changes cut out by the new trim_idle.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Snapshot: draw a see-through appearance see-through, and give the CLI --body, --tool and --section
A headless picture dropped a body's opacity: the scene carried only a colour, so a design with
a translucent appearance was drawn opaque by `solidcraft-cli snapshot`, by MCP screenshots and
in a design's thumbnail, although the window has always drawn it as glass. There was then no
way to look at the body a cut would remove inside the material it meets: only a volume to
measure and reason about, which hides exactly the errors a picture makes obvious (a tool that
stops short, or lands in the wrong place).
- `SceneMesh` carries the body's opacity; `view::build_scene` takes it from the design
(`model_body_opacity`), and a selected body stays solid so the selection colour reads.
- The GPU capture routes a see-through body into the scene's glass at its own alpha, as the
viewport does; the CPU rasterizer draws the solid bodies first (they own the depth buffer),
then the see-through ones blended over them, far sides before near sides and without writing
depth, so what lies inside shows and a line between the two is not hidden.
- `snapshot --body NAME:opacity=0.3,color=#rrggbb`, `--tool NAME` (that body solid in the tool
colour, the rest see-through) and `--section z=27` run the commands the app itself runs
(`appearance.assign`, `inspect.section`): the options are shortcuts, not a second renderer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Tests: measure the tool colour as it is drawn through a see-through target
The tool-colour filter was derived on paper and demanded a red more than twice either other
channel, which the target in front of it tints away (measured: (200, 108, 85) through opacity
0.3); and the colour check painted the tool, which a solid target hides.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fmt
* Snapshot options: strip the colour's # rather than slicing it; README
Slicing `value[1..]` on an input-derived string is what the house rules ask us not to write,
even where a length check has already made it safe. The error a failed assignment reports now
names the body rather than claiming it came from --body, since --tool reaches it too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* --tool: assign the bodies around the tool in groups, not one command at a time
Each appearance.assign is an undo step with a document snapshot behind it, so one per body
made --tool cost grow with the size of the design for no reason: the bodies around the tool
all get the same opacity, and the ones that share a colour can be named in one call. A design
whose bodies all wear the default grey now costs two commands whatever its size.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Rasterizer: say where its glass and the GPU's differ
Splitting each see-through body by facing orders its own two layers; it does not sort across
bodies, which the GPU does. Worth stating rather than leaving a reader to find it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Reword comments, docs and package descriptions so they describe SolidCraft's own behaviour instead of comparing it to another product. The trademark notice, the commercial-CAD rule and the navigation preset name stay as they were.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
SolidCraft read the HID device directly, which bypasses spacenavd and
everything set in spnavcfg (swapped and inverted axes, sensitivity, dead
zones). When the daemon's socket is there it is read instead, with a fixed
32-byte record decoder and no library; without it the hidraw path is
unchanged. The daemon sends a record only when values change, so its
readings are held until the next one rather than going stale.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds File > Export > Current View as DXF: the visible bodies projected from the current camera onto 2D LINE/LWPOLYLINE entities, with hidden edges omitted or dashed.
Co-authored-by: cronos <19868002+crono2250@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
FreeCAD .FCStd and Rhino .3dm files open, insert and drop like STEP and IGES:
cadmpeg (Apache-2.0, pinned =0.6.1, native builds only) detects the format,
decodes it under its service resource caps, validates the model and writes it
as STEP AP214, which becomes an Import feature in a new component named after
the file, with the up and names options.
Only the fcstd, rhino and step codecs are compiled in (no default features).
ACIS is left out: cadmpeg's sat codec is a ShapeManager stream decoder.
native_cad.rs is the single importer seam. Self-made FreeCAD and Rhino box
fixtures, hostile-input, ZIP-bomb and cap tests, engine tests for the
component path; the browser build reports these formats as not supported.
A note under design format 23 says an Import's file can name these formats.
Co-authored-by: Jacob Oursland <jacob.oursland@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The web app reads a 3D mouse through the Gamepad API and drives the camera through navigation::device, so it follows each page's navigation capabilities (#1336).
Co-authored-by: CamWight <CamWight@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
glTF files open, insert and drop like 3MF/STL/OBJ: a component named after the file, the node tree as nested rigid components, repeated meshes as occurrences, metres to mm, Y up turned to Z up by default (up: z keeps axes), materials as PBR appearances. Bounded, hostile-input tested reader; no new persisted data. Closes#1505.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One docked Save as mesh dialog replaces Export STL / 3MF / 3MF with face tags, with an optional Send to slicer that lists the slicers installed on this machine. Engine: file.save_mesh and file.slicers; the Convert Mesh dialog goes (mesh.convert and the MeshConvert feature stay, so existing designs open). Strings in all catalogs; screenshots in the PR. Checked on main + this branch: cargo check --workspace, the engine slicer/mesh/file tests, the UI catalog and menu tests and scenario s14 (the one local colour-token failure is epaint's TexturesDelta panic, which main shows on this machine too).
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>
Publishing a non-prerelease release runs winget.yml, which opens the
winget-pkgs pull request for bherbruck.SolidCraft with Komac (pinned
2.16.0 binary, SHA-256 checked) from the three versioned MSIs. It skips
cleanly without the WINGET_TOKEN secret or before the package's first
version is in winget-pkgs. docs/releasing.md has the one-time token
setup; the README's Download section gains the winget install line.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Trimmed faces are cut into four-sided patches (squares around holes, butterflies for round faces, motorcycle traces from concave corners) and each is meshed as a Coons grid, with a cut grid as the fallback; cells are at most 2:1 along straight directions. Folded blends are refused rather than overlapped. The README lists display meshes and the gpu crate.
A design with components and joints exports as a URDF robot description (file.export to .urdf, the MCP export tool, solidcraft-cli run --out, File > Export URDF...). It writes one binary STL per component in metres, links with mass, centre of mass and inertia from material density, and maps rigid, revolute, slider, cylindrical, pin-slot, planar and ball joints to URDF joints or short chains. Loops, broken joints and loose parts are reported as warnings. Options: mesh_prefix, effort, velocity. Docs in docs/urdf.md.
Agent tool calls (MCP, and bridged control requests carrying allow_paths) reach files only in the open design's folder (strictly inside home or the temporary folder, not in a hidden folder, and never its hidden files), the app's recovery folder, the server's private scratch folder and each --allow-path; --allow-any-path lifts the limit. Paths are resolved first, so .. and symlinks that lead out (including a save through a link, #845) are refused. On Windows, UNC, device, NT, verbatim non-drive, drive-relative, alternate-stream, reserved-device and 8.3 short-name paths are refused before any file system call, and the resolved path must be on a local drive. doc.recovery_discard and doc.recover {discard} delete only real recovery entries. Docs: mcp.md, control-protocol.md, README.
As soon as a pick settles the dimension (one line, circle or arc, or the second point or line of a distance or angle), its value box takes the keyboard with the measured value selected. The text follows the cursor while typing and Enter places it there (or in its default place), as one undo step. A click before typing pins the text and keeps the box focused, a click on another entity makes a distance or angle, Tab hands back to placing first, Esc cancels. Letters go into the box, not to tool shortcuts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `pi` story of examples/demo/enclosure_ui_mcp.py keeps the 0.6 flow and adds the rim
rounded in one pick (a tangent chain), "Pi 4" engraved in the floor in DejaVu Sans Bold, and a
PETG material defined in the design, with its mass in Properties, before the height change.
The 0.6 story stays as `pi-0.6` (it built demo/pi-case). The center rectangle now comes from
the Rectangle drop-down. The finished case is in the action matrix corpus as
demo/pi-case-0.8.
docs/screenshots/demo-0.8.gif (9.3 MB) and demo-0.8.mp4 (9.9 MB) replace the 0.6 files: 41 s
at 9x playback.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Refs #303. file.save / file.save_as can store a warm native geometry cache (cache: true, off by default) keyed to the document hash, app version and adapter revision. Opening shows a bounded preview from it until the rebuilt session replaces it. Any cache failure counts as a miss.