ddde08fb4c3c48888bc0170bec4d94cb24a9d41e
16
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ddde08fb4c |
Results view: hover over contours is an outline, not a pink fill (#207)
While result contours are shown, the hovered item's face fill is left out and only its outline, edges and nodes are drawn, so the hover never hides the colours under the pointer. Picker::hover is the hover's own overlay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo |
||
|
|
217628ead4 |
ui: command forms drawn from the parameter schema
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 |
||
|
|
4445be0b48 |
mesh.quality: a one-line summary, shown in the status bar
Quality from the ribbon printed its whole JSON report into the status
bar, cut off after the first metric's histogram, so a user saw braces
and no answer. The report now carries a `summary` line ("30676 elements,
all valid; scaled Jacobian min 0.305, mean 0.963", with the invalid and
undetermined counts when there are any), and the status bar shows a
reply's summary instead of its JSON whenever it has one. The CLI and MCP
get the same line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
|
||
|
|
e4e3c9a699 |
ui: mesh in the background from the mesher forms
OK on a mesher's form ran the command on the window thread: octree hex
on the bolted assembly froze the window for over a minute, with no
progress and no way to stop it. The tet and hex meshers' forms now run
their command as a background job on a copy of the session, as opening
a file and solving do: the window keeps drawing with the job's name and
Cancel, the form closes when the mesh is in and shows the error when it
is not. ui.dialog {run} stays synchronous for programmatic callers.
The new test walks a first-time user's path: Open picks a SolidCraft
design, Tet Mesh opens its form, OK with the defaults meshes the part,
and a mapped hex mesh of a holed plate says why it does not fit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
|
||
|
|
8a4209a20c |
control: ui.drop drops files on the window
The Open dialog is a native picker the control channel cannot click, so
nothing could walk a person's open path end to end: ui.start file.open
opens the command's JSON form instead. ui.drop {paths} hands the paths
to the next frame with the window system's drops, which open them
through the same route a picked file takes (open_path: by type, in the
background, the unsaved-changes prompt, the recent list). At most 16
paths of at most 4096 bytes each.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
|
||
|
|
9e269a9f45 |
ui-egui: select faces, edges, vertices, bodies, nodes and elements by picking
A click in the viewport picks what is under the pointer through the selection filter (the selection bar, top centre): geometry faces, edges, vertices and bodies, or mesh nodes, element faces and elements. Shift adds, Cmd/Ctrl adds or removes, a click on nothing clears, Escape clears; with Box on, a left drag selects the visible nodes, element faces or elements inside the box. What a click would pick is highlighted under the pointer with its name beside it. The selection is kept in the model's persistent terms: geometry by name (GeometryRef, named through the mesh's geometry tags or the drawn bodies' face names), so it survives a remesh, and the mesh by label (labels the model loses drop out). It reads as a set's members. Picking runs on the CPU against the triangles both renderers draw. The selection and the hover are drawn as an overlay in the theme's new pick_selected and pick_hover colours (light and dark), outlined; the GPU draws it as a second small layer, so a hover change uploads only that. Command forms that apply to part of the model (sets, boundary conditions, loads, sections, couplings) get a Target row whose Use selection fills the members, or makes a set of the selection and names it. A right click offers Create set from selection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm |
||
|
|
5665cc3d8c |
ui: the viewport draws the analysis setup's symbols, with toggles
The setup's symbols (fieldcraft_render::glyphs) are built with the display data and drawn over the model in every style, at the drawn nodes (a results plot's deformed shape), muted over results; the clipping radius holds them. Theme tokens give their colours in light and dark. The browser's Loads & BCs and Interactions rows get eye toggles (ui.set show_loads, show_interactions), also in the view menu. The GPU viewport draws reference point names with the interface's font; the bottom left says which definitions are sampled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm |
||
|
|
34200013a4 |
The ribbon follows each command to its stage
A command run by a script, the control channel, MCP, the command search or the browser left the ribbon on whatever tab it showed, so an agent's session never showed the stage it was at. `catalogue::stage_tab` is the rule, from the catalogue: a command's entry tab, none for the Tools tab (files, history, the model summary). The app follows it after a command that changed the model or the results display (queries leave the ribbon alone); a script follows its last command with a stage. A ribbon click runs a command of the tab shown, so it never moves the ribbon: a test checks every entry and drop-down command against its tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm |
||
|
|
d5bd74570f |
Rename the project to FieldCraft
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 |
||
|
|
bf325bb234 |
Craft-family shell, native file dialogs, samples and one-click Solve (#46)
* 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> |
||
|
|
6dda34e837 |
simplify: joining in modelcraft-mesh::join, shared label helper, run_script returns step outputs
Weld and face-to-face check move from the mesh.block command to modelcraft_mesh::join (bounding-box-limited weld, grid-binned hanging-node test), for node merging and imports to reuse. mesh.block and mesh.tet.generate share fresh_labels. The block map evaluates each edge curve once per lattice parameter; vector helpers come from vec3; tet10 and hex20 mid-side nodes follow ElementKind::edges. Session::run_script returns each step's output, which the oracle reads instead of its own loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm |
||
|
|
0e97f8dd1d |
Results display (M4) and offscreen full-UI capture (#28)
* ui.capture: the whole window drawn offscreen and rasterised on the CPU ui.screenshot falls back to it when no frame is presented (hidden window, locked screen), so agents can look at panels and the toolbar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Draw the open design and imported surfaces in the viewport DisplayMesh keeps node labels on every element primitive (for results), gains add_surface (geometry faces and their boundaries, coincident points welded) and displaced (elements moved by nodal offsets). Bodies are tessellated at a thousandth of their size; meshed models show the geometry as boundaries only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * results.* commands: deformed shape, contours, mode shapes, animation, reaction sums The results display is session state (ResultsView), set by commands that are not edits. Nodal fields (displacement, von Mises, principal and component stresses; principal stresses in closed form after Smith 1961) and reaction force and moment sums per set. Results kept from an earlier revision stay viewable, marked stale; solve.probe says when a result is stale. The Results tab's display and reaction entries are ready. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Results display: deformed shape, contours with legend, mode shapes and animation, probe, reaction sums The viewport draws the session's results view: elements moved by their nodes' displacements or a mode shape (automatic or given scale), faces split exactly along contour band boundaries into flat-coloured pieces (same on GPU and CPU), a legend with levels and extremes, a results panel whose controls run the results.* commands, a click probing the nearest node (solve.probe), and stale results marked. Solving from the form shows the result on the Results tab. sample::cantilever is a solvable model for tests and demos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Simplify the results display (review) One Contour in the plot; the results scene reuses scene::build; a solve shows its result through the engine (ResultsView::for_result) and the UI raises the Results tab when a view appears; the plot's scale and contour values are kept across animation frames; design bodies are tessellated once per design; the first content is framed where the display is rebuilt; field_values in one match; probe reuses results::displacements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Results display for explicit steps: field frames, energy histories The results view works on the engine's step results (static, frequency, explicit): ResultsView.frame and results.frame {frame | time} pick an explicit field frame; the deformed shape (true scale) and contours (element stresses averaged to the nodes, velocity) follow it; animation runs through the frames. The Results panel has a frame slider and plots the kinetic, internal, hourglass and external energies with their values at the frame. sample::impact is a steel bar flying onto a rigid wall. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs/features.md after the 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> |
||
|
|
aa68bbbcdf |
Constrained Delaunay tetrahedralization (boundary recovery) and mesh.tet.generate (M2) (#29)
* predicates: LNC points, generic insphere and its perturbed form (Diazzi et al. 2023 §4.3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * mesh: constrained Delaunay tetrahedralization (segment recovery with LNC Steiner points, gift-wrapping facet recovery, labelling) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * cdt: rounding repair, mesh.tet.generate, corpus CDT column; review cleanups (shared perturbation rule, one facet scan, cached coordinates, worklist segment recovery) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * mesh.tet.generate is ready in the catalogue; corpus table with the CDT column 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> |
||
|
|
a292212b67 |
Toolbars for every capability, VectorCraft icons, coming soon for planned ones (#20)
* feat(engine): capability catalogue — every toolbar entry, ready or coming soon, and docs/features.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * feat: 98 toolbar icons drawn with VectorCraft from recipes (cargo xtask icons), attributed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * feat(ui): toolbar of tabs and panels from the catalogue, VectorCraft icons recoloured per theme, coming-soon entries greyed with their milestone; ui.toolbar Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * refactor: ready entries are their command; one tooltip; tabs and panels as catalogue runs; icon cache per theme and size; ui.toolbar read-only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: roadmap notes the toolbar and icons Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * feat(ui): deck entries run deck.write with their format, ready when the writer is in FORMATS; file and edit entries; compact and collapsed panels instead of scrolling Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: features page after the Nastran writer (#24) made its deck entry ready Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: features page after the LS-DYNA writer (#25) made its deck entry ready Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * feat: solve.static, solve.frequency and solve.probe on the toolbar (Solve and Results tabs) 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> |
||
|
|
2d99a8571c |
The .modelcraft file, undo/redo on the journal, atomic saves and autosave recovery (M3) (#21)
* modelcraft-io: the .modelcraft file (modelcraft/1), atomic writes, autosave storage A stored ZIP of a manifest (format tag, geometry sources with SHA-256, part sizes and hashes), the model definition as stable pretty JSON, the mesh and geometry tags in a compact binary part, and the journal one command per line. Reading caps every size, checks every checksum and replays the model through its checked methods. Model::without_mesh and empty mesh fields left out of the model's JSON; geometry::read_file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * engine: undo/redo on the journal, file.open/save/save_as, autosave and recovery CommandSpec gains a kind: Model commands are journalled and become undo steps; Session commands (file.*, edit.*) manage the session. Undo history is bounded by steps and estimated memory. Geometry sources are recorded with content hashes and reopened on file.open (missing or changed files are warnings). Desktop app autosaves every 30 s and reports recoverable models; Ctrl/Cmd+Z and Shift+Z/Y undo and redo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: the .modelcraft format, undo history, roadmap and parity status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * simplify: shared path parameter, one load path for open/recover, history accounting in History Session commands skip the per-command model copy; saved revision is an Option; journal written from borrowed entries and read without an intermediate tree; backups copied by the file system; recovery lock and error helpers; geometry file wrappers use read_file. 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> |
||
|
|
3c1485d83a |
Desktop app: egui/wgpu viewport, model tree, commands and control channel (#9)
* render: display data from the FE model, orbit camera and CPU rasterizer modelcraft-render (L1, no GPU): DisplayMesh (the unshared faces of solid elements, shells, element edges, line elements, nodes), the orbit camera and a CPU rasterizer with PNG output for headless snapshots, adapted from SolidCraft's render crate. Workspace: egui/eframe/egui-wgpu 0.36 and SolidCraft's patched egui-wgpu from the pinned rev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * engine: sample model script (a hex8 block and a tet4 cube) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * Desktop app: egui/wgpu viewport, model tree, commands, status bar, control channel modelcraft-ui-egui (L5): ModelApp over the engine Session; GPU viewport (lit faces, element edges, nodes) with a CPU fallback; orbit/pan/zoom, standard views and fit; model tree; commands panel generated from the registry with a JSON parameter form; status bar; control request handling (engine.*, ui.*, ui.screenshot, ui.render). apps/modelcraft: eframe window, --sample, --control PORT loopback JSON-lines server. Adapted from SolidCraft's ui-egui and app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * THIRD-PARTY-LICENSES: the desktop app's dependencies Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: control protocol, desktop app in architecture, roadmap and attribution Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * render: simplify the display mesh (sorted face keys over maps, no unused fields) Interior faces are found by sorting fixed-size face keys instead of a BTreeMap of Vecs, edges are deduplicated by sort, and each element's corners are looked up once. Drops the unused `element` fields on DisplayTri/DisplayLine, the unused Mat4::IDENTITY and corner_count, and hoists the line colour out of the raster loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * viewport: split GPU geometry into batches within the buffer limit; refuse oversized CPU renders A mesh with a few million boundary triangles made one vertex buffer larger than the device's max_buffer_size (256 MiB under the limits eframe requests), and wgpu's default error handler panicked. Geometry is now uploaded in batches of whole primitives, each at most 128 MiB and the device limit, and all are drawn. A device error handler logs errors and shows them in the status bar instead of panicking. The CPU renderer refuses sizes over 8192 per side or 16 MP, and scenes over 20 million primitives, with an error, and allocates its buffers fallibly. ui.render reports a size out of range instead of clamping it; the CPU viewport fits a large window into the limit. 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> |