forked from 1b-agent/fieldcraft-upstream
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>
This commit is contained in:
320 files changed
+2990
-88
No files matched your search
@@ -114,6 +114,7 @@ pub fn handle(app: &mut ModelApp, ctx: &egui::Context, req: &ControlRequest) ->
|
||||
"model": {"nodes": app.session.model.nodes().len(), "elements": app.session.model.elements().len()},
|
||||
"version": crate::VERSION,
|
||||
})),
|
||||
"ui.toolbar" => ok(crate::toolbar::describe(app)),
|
||||
"ui.set" => {
|
||||
let mut cur = serde_json::to_value(&app.ui).unwrap_or(json!({}));
|
||||
if let (Some(o), Some(src)) = (cur.as_object_mut(), p.as_object()) {
|
||||
@@ -367,6 +368,8 @@ mod tests {
|
||||
json!({"width": 1e12, "height": -5, "path": ""}),
|
||||
json!({"command": 5, "params": "x", "commands": {"a": 1}}),
|
||||
json!({"key": "NoSuchKey", "text": 7, "view": null, "points": [[1], "x", null]}),
|
||||
json!({"tab": "nope", "command": "mesh.tet.generate"}),
|
||||
json!({"tab": 3}),
|
||||
];
|
||||
for method in [
|
||||
"engine.execute",
|
||||
@@ -384,6 +387,7 @@ mod tests {
|
||||
"ui.worldToScreen",
|
||||
"ui.resize",
|
||||
"ui.render",
|
||||
"ui.toolbar",
|
||||
] {
|
||||
for p in &hostile {
|
||||
let _ = call(&mut app, method, p.clone());
|
||||
@@ -392,6 +396,21 @@ mod tests {
|
||||
assert!(app.synthetic.len() < 1000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_toolbar_lists_every_entry_and_switches_tabs() {
|
||||
let mut app = ModelApp::new(Session::default());
|
||||
assert_eq!(call(&mut app, "ui.set", json!({"tab": "mesh"}))["ok"], true);
|
||||
let r = call(&mut app, "ui.toolbar", json!({}));
|
||||
assert_eq!(r["result"]["tab"], "mesh", "{r}");
|
||||
let entries = r["result"]["entries"].as_array().unwrap();
|
||||
assert_eq!(entries.len(), modelcraft_engine::catalogue::CATALOGUE.len());
|
||||
let tet = entries.iter().find(|e| e["id"] == "mesh.tet.generate").unwrap();
|
||||
assert_eq!((tet["coming_soon"].as_str(), tet["command"].is_null()), (Some("M2"), true));
|
||||
assert_eq!(call(&mut app, "ui.set", json!({"tab": "nope"}))["ok"], false);
|
||||
let r = call(&mut app, "ui.start", json!({"command": "mesh.tet.generate"}));
|
||||
assert_eq!((r["ok"].as_bool(), r["error"].as_str()), (Some(false), Some("Tet Mesh is coming soon (M2)")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn screenshots_are_saved_as_png() {
|
||||
let image = egui::ColorImage::filled([4, 3], egui::Color32::RED);
|
||||
|
||||
Reference in new issue
Block a user