Static, frequency (per mode), nonlinear and explicit (per frame, with a
.pvd collection) and heat results; fluid steps are refused. Wedges keep
the model's node order: VTK 9's wedge has the same orientation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
A partition intersects the body with a box on each side of the plane as
large as the body itself. SolidCraft's split_by_plane uses boxes several
times larger, and its boolean then put the cut up to 1.8 um off the plane
on the enclosure's air, so the cut faces were not recognized and the cells
did not close. A plane along a face of a body it cuts, or a cell whose
boundary does not tessellate into one a mesher takes (a cut through a
hole's axis), is a warning naming the partition, the body and where.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
Window captures (light theme, 1400 x 860) of every sample solved on the current UI; the
thumbnails that were viewport crops are now clean ui.render images like the others; the drop
test's figure at 0.1 ms reads 129 MPa.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The README video's model as a sample: the corpus cantilever-i-beam design opened as geometry,
swept all-hex, clamped at F2:start, 1 kN on F2:top through a kinematic coupling; static step
Load. It has a Start-card thumbnail and a gallery capture; a test checks its tip deflection
against beam theory with shear.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
All six docs/media/examples images at 1400 x 860 in the light theme, the
solved sample in the home view (the crank mirror from below, as its text
says), with the wireframe symbols, no SETUP card and the crank's planes
hidden; the Start card thumbnails cropped to the model from them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
crash: a panic hook and a locked per-run command journal (adapted from
SolidCraft's crash reports). A panic in a command becomes a report with
the model from before it and the command; one outside commands, or an
unclean exit found at the next start (abort, segfault, a crash in a
graphics driver, a kill: what #248 needs), a report with the model the
journal starts from (autosave, file or a copy) and the commands since,
the last control request and the dead run's log lines. Reports are
bounded, deduplicated by signature and replayable (crash::replay, with
writes confined to a scratch folder). The crash folder follows the
automation temp area in --control and CI runs.
logfile: a small size-rotated file logger behind the log facade.
bug_report: GitHub bug-form drafts. Version, OS and what happened by
default, home folder shown as ~; the command journal only with Share my
session, the model only with Include the model as well; a session too
long for the link becomes a file to attach and the clipboard text.
Commands: diagnostics.crash_reports, diagnostics.crash_report,
diagnostics.bug_report (Tools › Help, with its icon) and
diagnostics.crash_test (FIELDCRAFT_CRASH_TEST=1 only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
view.hide, view.show, view.isolate and view.show_all change which
bodies, surfaces, datums, boundary conditions, loads, reference points
and couplings the viewport draws. The hidden items are view state: the
manifest's `view` keeps them, a change marks the model unsaved, but it
is neither journalled nor undone and leaves results current. Items that
go away are forgotten. Headless pictures leave hidden items out; the
glyph builders take a filter. Tools > View > Show All claims the
commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
A datum point by coordinates, at a mesh vertex, a fraction along a
design edge, at a face's centre, or where a datum axis crosses a datum
plane. Datum planes take three datum points or a normal to a datum axis;
axes take two datum points. geometry.datum.edit, .axis.edit and
.point.edit redefine a datum of their kind (partitions cut again);
geometry.datum.delete with cascade also deletes the partitions that cut
by it. The ribbon shows Datum Plane, Datum Axis, Datum Point and
Partition, each with its own icon; edit and delete leave the ribbon
(still commands, claimed by their entries).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
An orbit turns about the model point under the press (the pick ray's
first hit on the plot, the mesh or the design), or the centre of what is
drawn when it starts on empty space, keeps that point still on screen and
marks it while orbiting. The wheel and a pinch zoom toward the point
under the cursor; the wheel's delta is read as it arrives, so a notch
zooms in full in orthographic and perspective views alike (#273).
Mouse presets and reverse zoom come from SolidCraft (prefs.rs NavPreset,
NAV_PRESETS; MIT OR Apache-2.0): FieldCraft's own (left drag per the
navigation bar) stays the default, Ctrl + left drag from empty space
orbits in every preset. They are chosen in the display menu, settable
with ui.set and kept in prefs.json beside recent.json (the browser build
keeps them for the page's run); an older prefs.json still loads.
Fixes#262, fixes#273.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
A seed draws a tick at each node it puts on its edge, so a bias shows as ticks
crowding toward an end. The browser lists the seeds under Mesh; a click
selects the seeded edge. The Seed Edges form takes the selected edges with
Use selection. The toolbar entry is ready (its icon renamed with it).
Part of #230.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample crank-mirror partitions the crank arm on its symmetry plane, sweeps
one half all-hex (hex20) and mirrors it into one conforming mesh, then defines
the crank-arm model. Samples may now run preparing commands (datums,
partitions) before their script sees the bodies. Its test checks the halves
alike and joined, every element valid and the sets on both halves; the heavy
test solves it: sigma_xx at the root -62.43 / +62.43 MPa against M/Z = 62.5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
cargo-deb and cargo-generate-rpm (pinned) package the same stripped binaries and files as the
tar.gz under /usr. The release job compares the file lists, runs lintian, and installs both
packages in Ubuntu 22.04 and Fedora containers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample crank-arm: a 170 mm 6061-T6 crank built in SolidCraft
(crates/engine/samples/crank-arm.json), swept along z by mesh.hex.generate
as 7274 hex20 elements of 3 mm (scaled Jacobian min 0.17). The hex variant
drops the pocket floor fillet and boss chamfers, and its root arcs meet the
bosses 20 degrees off tangent so the arm's top face has no zero-angle cusp.
The square bore is fixed and 1500 N acts on the pedal hole; the faces are
picked by their surfaces, not their names. Its heavy test matches the root
bending stress to M/Z = 62.6 MPa within 3 % (0.3 % in practice).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample bracket-hex: the corpus bracket split into 30 SolidCraft cells,
meshed by mesh.hex.blocks as one conforming hex20 mesh of 3 mm, clamped at
the upright and loaded at the foot. The sample's script finds the clamp and
load faces in every cell that has them. Its test matches the tip deflection
of a fine tet10 solution within 1 % and checks the clamp carries the load.
Closes#166
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample heated-bracket: the corpus filleted bracket in steel, tet10, its
hole bores clamped, the upright's end held at 120 C and the rest cooled by
still air; one coupled temperature-displacement step. Its test checks the
temperatures against the heater and the air, then warms the bracket evenly,
clamps one hole, and matches the free thermal expansion alpha dT times the
distance from the hole along x.
Closes#165
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample rubber-seal: a gasket ring of hybrid hex8 elements in four
mapped quarter blocks, squeezed 2.5 mm between plates bonded to it
(nonlinear static, Mooney-Rivlin rubber). Its test frees the plates and
matches the closed form for incompressible uniaxial compression within 3 %,
and bounds the bonded ring's extra stiffness. The plates are prescribed
displacements until implicit contact (#161) can press it into a groove.
Closes#163
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
file.sample drop-test: an L-bracket standing on its foot (a SolidCraft script
in sample.rs) swept into hex8, falling 2 m onto a rigid floor tilted 15 deg;
explicit dynamics for 1 ms with gravity and plasticity. Its test checks the
mass against rho V, the impact speed sqrt(2 g h) and kinetic energy, the
energy balance and the momentum the floor takes. docs/examples.md starts
with it, and its picture is docs/media/examples/drop-test.png.
Closes#162
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The context panel's form shows typed fields instead of the JSON text: numbers
with the model's units, drop-downs of choices and of the model's sets,
materials, steps and bodies, checkboxes, vectors, groups and one-of variants
(a load's type switches its fields), lists of rows. Defaults are filled in,
required fields are marked, a value the schema finds wrong is noted under its
field, and OK waits while a field holds text that is not a value. The JSON
text stays as the Advanced view. fields.rs holds the generic widgets (row,
number, drop-down, text), adapted from SolidCraft's dialog rows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
The owner's final choice: the hex-meshed cube with its banded fringe,
drawn a little larger, with no streamlines at any size. The Icon Composer
document is back to the floor and cube groups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The streamlines are now banded in the fringe colours along their length, as
flow speed would be, with a thin dark halo and arrowheads. Two sweep in from
the lower left, climb over the cube and run straight into the top face's
mesh lines, narrowing to them, so the flow becomes the structure; one wraps
around the cube. The small variant keeps the cube with one bold coloured
streamline and one arrow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mark is now a hex-meshed cube in isometric view whose faces carry a
banded colour fringe (blue to red, hottest at the front corner), with three
tapered streamlines wrapping around it. The small variant keeps the fringe
cube and one bolder streamline. Icon Composer gets four groups (floor, flow
behind, cube with mesh, flow in front), its maximum. The title-bar mark is
redrawn as the fringe cube.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pages.yml builds apps/fieldcraft-web (trunk build --release, wasm-opt)
on pushes to main and develop and on manual runs, and deploys the site
to https://jyviko.github.io/fieldcraft/ only from main (releases).
Develop merges that touch code build without deploying, so a broken
web build shows up before a release. Trunk is a pinned release binary
checked against its SHA-256; actions are pinned by commit.
Part of #119
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The desktop's ModelApp in a web page through eframe's web runner
(WebGPU, WebGL2 fallback, `?webgl` to force it), built with Trunk.
The browser services sit behind the UI's host-service seams: File >
Open uses the browser's file picker, dropped files are read
asynchronously, and both go into the page's files; Save, Save As and
Write Deck hand the written file out as a download. Autosaves go to the
recovery folder as on the desktop and are mirrored to local storage, so
File > Recover offers what a closed or crashed page left. `?sample=NAME`
opens a sample. A loading screen with the app icon, and a message
instead of the app when neither WebGPU nor WebGL2 is available.
`cargo xtask wasm` (and so `cargo xtask ci`) now checks fieldcraft-web
for wasm32 with the library crates. docs/web.md: running it locally,
what works in the browser and what does not.
Part of #119
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The browser has no file system a page can call synchronously. On wasm32,
fieldcraft_io::fs now reads and writes files kept in memory (memory.rs,
after SolidCraft's vfs): the web host puts picked and dropped files in
and takes out what commands wrote. The recovery folder works over the
same calls (list, remove, is_file), with in-memory entry locks and a
host-provided clock on wasm, so autosave and File > Recover work in the
browser as on the desktop. Native behaviour is unchanged.
Part of #119
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Nothing checked Linux beyond x86_64. A weekly and on-demand workflow
builds fieldcraft and fieldcraft-cli on a native arm64 runner (release
profile, as shipped), runs both binaries and the CLI and engine tests
there, and cross-builds both for riscv64gc-unknown-linux-gnu with
Ubuntu's GNU toolchain, linked, then runs them under QEMU. The GUI opens
Wayland, X11 and GL at run time, so the cross build needs no target
system libraries beyond libc.
The RISC-V job is adapted from SolidCraft's CI.
Closes#122
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The release pipeline's scripts and metadata were exercised only by a
full release run. A workflow of a few seconds, no Rust build, now checks
them on every push to develop and pull request that touches
.github/workflows or packaging, and on demand: actionlint (pinned,
checksum-verified, with shellcheck on every run: script), shellcheck on
the packaging scripts and AppRun, a parse and PSScriptAnalyzer pass
(errors and warnings) over the Windows scripts, xmllint on the macOS
property lists, desktop-file-validate on the desktop entry, and the
entry's StartupWMClass against the app id the window sets.
Adapted from SolidCraft's packaging-lint.yml (itself from PhotoCraft's).
Closes#121
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
The scripts carry `# shellcheck source=../env.sh`, but shellcheck reads
that path from the working directory, so from the repository root it
could not open env.sh: SC1091 on every script, and SC2153 in
macos/package.sh because APP_ID, set in env.sh, looked unassigned.
packaging/.shellcheckrc resolves source paths from the script's own
directory (SolidCraft's setting); every packaging script now passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
A push to the release branch (or workflow_dispatch) builds the macOS universal dmg and CLI zip,
the Linux tar.gz and AppImage and the Windows zip, with the version from Cargo.toml. The last
job checks the set, writes SHA256SUMS.txt and notes saying how the macOS app was signed, and
creates or updates a draft release; it never publishes. Off the release branch it only uploads
the files as a run artifact (dry run). macOS signing and notarization use the APPLE_* secrets
when they exist and fall back to ad-hoc signing (#72).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
packaging/macos/package.sh builds FieldCraft.app (io.github.jyviko.fieldcraft, with icon.icns
and the layered Assets.car), signs it with a Developer ID and notarizes it when the
credentials are there and ad-hoc otherwise, and puts it on a drag-to-Applications dmg that
is mounted and checked; fieldcraft-cli goes in its own zip. packaging/linux/package.sh makes
an FHS tar.gz (binaries, .desktop entry, hicolor icons, licences) and an AppImage made with
appimagetool and the type 2 runtime at pinned, hash-checked releases.
packaging/windows/package.ps1 zips fieldcraft.exe and fieldcraft-cli.exe (static CRT,
checked PE headers and icon). Every package carries README.md, LICENSE-MIT, LICENSE-APACHE,
NOTICE and THIRD-PARTY-LICENSES.txt (#72).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Meshes the open design's bodies (or the listed ones) as the cells of one
conforming all-hex mesh with one size and tessellation tolerance for all;
elements carry their cell's body, boundary faces its B-rep faces. A cell
that is no block, or cells that touch without sharing whole faces, is an
error naming the bodies. Catalogue entry with its VectorCraft icon, the
MCP mesh tool's hex_blocks method, docs/features.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
Crates fieldcraft-*, binaries fieldcraft and fieldcraft-cli, the .fieldcraft file (format tag
fieldcraft/1, manifest fieldcraft.json), FIELDCRAFT_* environment variables, the MCP server
name, egui widget ids (fc_*), the app icon document FieldCraft.icon and its generated family,
docs and licences. No compatibility shim: no files of the earlier name exist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Structured hex meshing: multi-level extrude and revolve, one-to-one sweep, mapped blocks (M5)
modelcraft_mesh::hex::hex_mesh meshes a face-tagged boundary surface with
hexahedra by the first structured method that fits: a straight or
rotational multi-level sweep (imprinted cross-section arrangement, cuts at
reflex corners, mapped/annulus/free regions), a one-to-one sweep through
rings of linking faces (least-squares affine layers with residual
correction), or a mapped logical cube (trivariate transfinite
interpolation). Interval assignment couples shared curves; boundary quads
carry B-rep face tags; the certified validity gate, a tiling check and a
fidelity check guard the output; hex20 mid-edge nodes go onto the faces.
Shape::face_surfaces exposes the analytic face surfaces; the corpus runner
gets a structured hex column.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* mesh.hex.generate: structured hex meshing as a command
Meshes one body, every body of the open design or an imported surface,
replaces the mesh, tags element faces with the B-rep faces (so sets by
geometry resolve) and reports per body the method, counts and quality.
The quality pass certifies each element once and feeds the validity gate
(quality::validity_gate_checks). Shape::size gives the cached body size
for defaults instead of a full measure.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Hex: disk O-grids, convex interval cost, early size guard, hex20 corpus column
Smooth single-loop sections (cylinders, tori, vases) get a butterfly O-grid
instead of the free mesher; interval assignment raises counts by the
squared relative error so equal sides share increments evenly; a mesh far
beyond the element limit is refused before any work and mapped limits are
no longer swallowed. The corpus reports hex8 and hex20 quality.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Catalogue: structured hex commands ready (mesh.hex.sweep, mesh.hex.mapped, mesh.hex.generate)
mesh.hex.sweep and mesh.hex.mapped run mesh.hex.generate with the sweeping
methods or the mapped one; mesh.hex.generate is the sweep entry's related
command. The planned M6 octree entry moves to mesh.hex.octree (its icon
renamed with it). docs/features.md regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Docs: structured hex literature (B8), architecture, roadmap, parity; corpus hex column
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Hex: simplify review fixes
Prepare each sweep frame's cross-section once (arrangement, cuts, fill)
and reuse it across refinement retries; candidate frames come from one
setup pass. Edge triangles come from the feature edges, layer counts go
through size::edge_divisions, sweep residual weights are computed once
per node, flux shape functions live on the stack, and the arrangement's
exact side test and distances serve the region probe. The engine takes
the boundary options mesh.tet.generate takes and names unnamed faces by
index like it; the corpus hex20 run reuses the winning method; the
mapped entry lists mesh.hex.generate too; the octree icon is redrawn
under its new id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md and docs/meshing/corpus.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Regenerate docs/features.md after rebasing onto main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
---------
Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Native file pickers, background opening, drag and drop and recent files
Open (models, SolidCraft designs and tagged meshes in one picker), Save, Save As, Write
Deck and Recover go through the host's file pickers (rfd in the desktop app, injected as
Services so the UI crate stays portable and tests answer them). Files open on a copy of the
session in a worker thread and replace it only on success; files dropped on the window or
named on the command line open the same way. A recent-files list, an unsaved-changes prompt,
Cmd/Ctrl+O/S/Shift+S. Programmatic calls never open a picker: ui.start opens the form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Samples and one-click Solve: results reachable from the window
file.sample {name} opens a ready-to-run sample (the two parts, the cantilever with static and
frequency steps, the bar impact) in place of the model; solve.run solves every step in order.
Help > Samples, the empty viewport's start screen and the Tools > Samples entry open them
(asking first over unsaved changes); Solve runs in the background like a file opening and the
Results tab comes up. --sample [parts|cantilever|impact] on the command line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* The Craft-family shell: title bar, workspace ribbon, browser, context panel, timeline
The window now follows SolidCraft's and VectorCraft's layout and themes:
- title bar with the mark, quick actions (File menu, save, undo, redo, Solve, search,
theme, help), the model's document tab and the version; integrated under the macOS
traffic lights, own caption buttons and resize zones elsewhere (titlebar.rs);
- workspaces (Prepare, Model, Analysis, Results) with their tabs, and panels of icon
buttons whose labelled drop-downs list the whole catalogue, coming-soon entries greyed
with their milestone; panels collapse, then go into a » menu, when narrow;
- the browser: geometry and mesh with eye toggles, definitions with counts, results;
- no permanent Commands list: command search (S, Cmd/Ctrl+K) and a command line;
- the context panel on the right only with context: the command form, results controls,
the selected definition's properties with Edit and Delete;
- navigation bar and orientation gizmo in the viewport; the journal timeline at the bottom
with undo positions;
- SolidCraft's light and dark tokens; craft-ui (IconButton, Tab, WidgetPalette).
Menus and the search are view state (ui.set {menu, palette}), so captures show them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Shell polish, docs and licences
Menus painted as the family's (flat File menu with recent files, decks and samples), the
legend sized to its text, two-line panel labels inside the ribbon, glyphs the UI font has,
offscreen captures without fade-in, ui.start runs in-window file actions (samples, recover,
solve) but never a native picker, ui.select. Control protocol, architecture, ROADMAP, AGENTS
and ATTRIBUTION updated; THIRD-PARTY-LICENSES.txt with craft-ui and rfd.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Title bar mark from the application icon; fluid steps and domains in the shell
The title bar draws the app icon's bracket (assets/app-icon/icon-small.svg's faces) as
SolidCraft draws its mark; the window keeps its title-bar flags after the rebase.
solve.run solves fluid steps too (solve.fluid); the browser lists fluid domains.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Simplify: cached per-frame data, one command per timeline roll, workspace setters
- Icon textures are kept per pixel size (the shell draws several sizes a frame; the cache
used to clear on every size change and rasterise again).
- Opening a model or recovering one starts from an empty session instead of copying the
current one; the replaced session is freed off the window thread.
- Element counts, timeline items, search results and the selected definition's properties
are cached until what they show changes; timeline tooltips are built on hover; long lists
in properties are summarised.
- edit.undo and edit.redo take a count: a timeline click is one command.
- solve.run dispatches on the step's procedure (no string round trip) and reports its name.
- The workspace and tab change together through UiState::select_tab/select_workspace
(ui.set {workspace} alone now sticks); no per-frame syncing.
- One busy guard, Kind::verbs, a fit flag for background jobs, ModelApp::home_view, the title
bar's actions as an enum, dead code removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Title bar: Solve and tools at the right end; no traffic-light inset in full screen
The owner's feedback on the title bar: Solve, search, theme and help sit at its right end
before the version; on macOS the left group (mark, name, quick actions) moves into the
traffic lights' room in full screen, where there are none, and back when leaving it. The
layout is a pure function (bar_layout) tested for both states, narrow windows and custom
caption buttons. ui.fullscreen {on} for agents.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Caps labels in Inter SemiBold
egui has no bold weight of its default font, so the ribbon's tabs and panel labels, the
workspace switcher and its menu, menu headings, the browser header, the context panel's
headers and the Solve label were thin, especially in the light theme. They now use a label
font family: Inter SemiBold 4.1 (SIL OFL 1.1, unmodified, fonts/OFL.txt, ATTRIBUTION.md),
with egui's fonts as fallback, installed with the theme on the live and offscreen contexts.
theme::label_font falls back to the default font until the family is bound (fonts take
effect from the next pass), so nothing can panic. Panels widen to their label's longest word.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: regenerate features.md after rebase
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
---------
Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Model, fem and decks: point masses, rotary inertia, springs, dashpots and rod3 trusses
Model: PointMass and Spring definitions (spring | dashpot; to ground or
two-point; along a degree of freedom, a vector or the line of the ends) on a
set or reference point, resolved per node; ElementKind::Rod3. fem: rod2/rod3
truss kernel on Basis::Line2/Line3 declaring ElementDofs (translations).
Decks: Abaqus T3D3, MASS, ROTARYI, SPRING1/2/A, DASHPOT1/2/A; Nastran CONM1,
CELAS2, CDAMP2; LS-DYNA ELEMENT_MASS/INERTIA and ELEMENT_DISCRETE; what a
format cannot take is reported. Commands model.mass.* and model.spring.*.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Implicit solver: trusses, point masses, rotary inertia and springs on the DofLayout
Trusses declare their translations like solids; point masses, inertia and
springs ask the layout for the kinds they need at their nodes (translations,
rotations), and reference points they use get six degrees of freedom. The
matrix pattern takes rows for those points; dashpots are ignored with a
warning. Existing results are bit-identical (hash-checked).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* Explicit solver: trusses, point masses, springs and dashpots on the node-major layout
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: fem.md on trusses and discrete elements in the layout; regenerate features.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
* docs: trusses in plane models and corotational explicit trusses
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
---------
Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>