From c45f3173fab8603d0cb43a510a7818d20edcc5ab Mon Sep 17 00:00:00 2001 From: bherbruck Date: Thu, 8 Oct 2026 15:48:03 +0000 Subject: [PATCH] QA targets for the newest UX reports (pending until their owners land): s37 browser chevrons on every node kind (all toggle; no Joints folder yet), s38 view animations to Top/Bottom end without a jump (the last frame turns 22.5 degrees today), s39 view cube edge/corner hover lights 2/3 patches, s40 toolbar Pin/Remove/reorder survive a restart and the workspace switcher spans the toolbar; ui_layout tests: every command dialog docked right at 260-380 px (or 480-560 for tables; the exploded view is 635), other windows fit on screen. Harness: published rects and counts, browser rows/fold arrows as handles, camera and view_anim steps, ui.at cube points, settings carried over a close restart, an adhoc scenario runner Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL --- crates/ui-egui/src/browser.rs | 2 + crates/ui-egui/src/control.rs | 6 + crates/ui-egui/src/scenario.rs | 155 +++++- crates/ui-egui/src/toolbar.rs | 2 + crates/ui-egui/src/viewport.rs | 14 +- crates/ui-egui/tests/scenarios.rs | 18 + .../tests/scenarios/s37_browser_chevrons.json | 523 ++++++++++++++++++ .../scenarios/s38_view_anim_no_jump.json | 20 + .../tests/scenarios/s39_view_cube_hover.json | 16 + .../s40_toolbar_customize_persists.json | 17 + crates/ui-egui/tests/ui_layout.rs | 67 +++ 11 files changed, 831 insertions(+), 9 deletions(-) create mode 100644 crates/ui-egui/tests/scenarios/s37_browser_chevrons.json create mode 100644 crates/ui-egui/tests/scenarios/s38_view_anim_no_jump.json create mode 100644 crates/ui-egui/tests/scenarios/s39_view_cube_hover.json create mode 100644 crates/ui-egui/tests/scenarios/s40_toolbar_customize_persists.json create mode 100644 crates/ui-egui/tests/ui_layout.rs diff --git a/crates/ui-egui/src/browser.rs b/crates/ui-egui/src/browser.rs index 45e14b11..93107c07 100644 --- a/crates/ui-egui/src/browser.rs +++ b/crates/ui-egui/src/browser.rs @@ -281,6 +281,7 @@ fn draw_row(ui: &mut egui::Ui, id: egui::Id, row: &Row) -> RowResp { }; ui.painter().add(egui::Shape::convex_polygon(pts, t.text_dim, Stroke::NONE)); out.fold = ui.interact(ar.expand(3.0), id.with("fold"), Sense::click()).clicked(); + crate::scenario::publish_handle(&format!("fold:{}", row.label), ar.center()); } x += 14.0; // Eye. @@ -322,6 +323,7 @@ fn draw_row(ui: &mut egui::Ui, id: egui::Id, row: &Row) -> RowResp { badge(ui.painter(), br, b, t.text_dim); bx += 15.0; } + crate::scenario::publish_handle(&format!("row:{}", row.label), r.center()); out.resp = Some(resp.clone()); out.clicked = resp.clicked(); out.double = resp.double_clicked(); diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs index 8613bfff..d5233296 100644 --- a/crates/ui-egui/src/control.rs +++ b/crates/ui-egui/src/control.rs @@ -264,6 +264,12 @@ pub fn handle(app: &mut SolveApp, ctx: &egui::Context, req: &ControlRequest) -> }; } let Some(rect) = app.viewport.rect else { return err("no viewport") }; + if let Some(c) = p.get("cube") { + // A point on the view cube, in cube units (faces at ±1). + let n = |i: usize| c.get(i).and_then(Value::as_f64).unwrap_or(0.0); + let q = crate::viewport::cube_point(app, rect, solvecraft_engine::geom::Vec3::new(n(0), n(1), n(2))); + return ok(json!([q.x, q.y])); + } let proj = crate::viewport::projection(app, rect); let num = |v: &Value, i: usize| v.get(i).and_then(Value::as_f64).unwrap_or(0.0); let world = if let Some(w) = p.get("world") { diff --git a/crates/ui-egui/src/scenario.rs b/crates/ui-egui/src/scenario.rs index 0b3c6851..f1128b1c 100644 --- a/crates/ui-egui/src/scenario.rs +++ b/crates/ui-egui/src/scenario.rs @@ -16,7 +16,10 @@ //! folder (Save pickers save there) //! - `{"shot": "name"}`: a screenshot when run in a window; headless, a render of the model //! into `$SOLVECRAFT_SCENARIO_SHOTS` when that is set; `{"debug": 1}` -//! prints the UI state +//! prints the UI state (`"widgets"`: also every widget's text; `"handles"`: every published +//! handle, browser rows as `row: