* feat(engine): capability catalogue — every toolbar entry, ready or coming soon, and docs/features.md Co-Authored-By: Claude Opus 5.5 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: roadmap notes the toolbar and icons Co-Authored-By: Claude Opus 5.5 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm --------- Co-authored-by: jyviko <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
4.8 KiB
Control protocol
modelcraft --control PORT (or MODELCRAFT_CONTROL_PORT=PORT) listens on 127.0.0.1:PORT for
JSON lines. Each request is one line {"id": …, "method": "…", "params": {…}}; each reply is one
line {"id": …, "ok": true, "result": …} or {"id": …, "ok": false, "error": "…"}. Requests are
handled on the UI thread between frames; pointer and keyboard input is injected as real egui
events, one pointer event per frame. The protocol has the same shape as SolidCraft's.
modelcraft --sample --control 7070
{"id":1,"method":"engine.execute","params":{"command":"model.info","params":{}}}
→ {"id":1,"ok":true,"result":{"elements":{"hex8":64,"tet4":162},"nodes":199}}
{"id":2,"method":"ui.render","params":{"path":"/tmp/model.png","width":900,"height":600}}
The channel is untrusted input. A request line may be at most 16 MiB; a longer one is answered
with {"ok": false, "error": "request too large"} and the connection is closed, as are
connections that send eight lines that are not JSON. At most 16 connections are served at once,
at most 64 queued requests run per frame so a flood cannot starve drawing, and a request the UI
thread has not answered within 60 seconds gets {"ok": false, "error": "timeout"}. Numbers are
checked and clamped (drag steps, wheel lines, window size); ui.render refuses an image size out of range.
Engine
| Method | Params | Result |
|---|---|---|
engine.execute |
command: command id, params: JSON object |
the command's result |
engine.script |
commands: [{command, params}, …] |
stops at the first error; journal: commands that changed the model so far |
engine.commands |
— | every command: id, label, params (the parameter documentation) |
Commands never open forms when run this way. modelcraft-cli commands prints the same registry.
UI
| Method | Params | Notes |
|---|---|---|
ui.inspect |
— | view settings (ui), camera, viewport rect (points), renderer (gpu/cpu) and adapter, open command form, status bar, node and element counts, version |
ui.set |
any view setting: style (shaded_edges, shaded, wireframe), show_nodes, perspective, dark, show_tree, show_commands, tab (the toolbar tab: geometry, mesh, properties, assembly, steps, loads, interactions, solve, results, tools) |
an unknown setting or value is an error; returns the settings |
ui.view |
view: front, back, left, right, top, bottom, iso, home (iso and fit), fit |
returns the camera |
ui.toolbar |
— | the toolbar (ui.set {tab} switches tabs): tab, tabs, and every catalogue entry (docs/features.md) with id, label, tab, panel, command (null while coming soon), more (its drop-down's commands), coming_soon (the milestone, or null), rect (its button in screen points last frame, on the shown tab; a collapsed panel's entries share its drop-down button) and fit (full, compact icon-only, or collapsed into the panel's drop-down, by window width) |
ui.start |
command: a command or toolbar entry id |
like clicking it on the toolbar or in the Commands panel: a command without parameters runs, one with parameters opens its form; an entry that is coming soon is an error naming its milestone |
ui.dialog |
params? (JSON object, fills the form), run?, cancel? |
drives the open command form; run returns the command's result and closes the form on success |
ui.click |
x, y (screen points), button?: left/right/middle, shift?, ctrl?, alt?, double? |
real pointer input |
ui.move |
x, y |
|
ui.drag |
x0, y0, x1, y1, button?, shift?, ctrl?, steps? (1–200) |
press, move, release: in the viewport a left drag orbits, a right or middle drag (or Shift + left) pans |
ui.scroll |
x, y, delta? (wheel lines, −100–100; positive zooms in) |
zooms at the point |
ui.key |
key (egui key name, Enter, Escape…), cmd?, shift? |
F over the viewport frames the model |
ui.text |
text |
typed text (into the focused field) |
ui.worldToScreen |
points: [[x, y, z]…] (at most 1000) |
screen points in the viewport drawn last frame (null when not on screen) |
ui.resize |
width, height |
window inner size in points |
ui.screenshot |
path? |
PNG of the window, taken a few frames later; needs a presented frame (a hidden window or a locked screen answers with an error: use ui.render). Without path: modelcraft-shot.png in the temporary folder |
ui.render |
path, width? (default 1280), height? (default 800): whole pixels, each 1–8192 and at most 16 megapixels in all |
CPU render of the model with the current camera and view settings (no window or GPU needed). A size out of range, or a scene over 20 million primitives, is an error |
app.quit |
— | closes the window |