# Bevy Forge v2 — M0 Spike Status: **M0 spike**, not a release. It proves the v2 architecture: a real in-game Bevy 0.20 editor plugin with native Bevy UI, a live hierarchy, a reflection inspector, one translate gizmo and deterministic screenshots. No egui is involved in the runtime crate. ![Bevy Forge M0 spike](m0-spike-1440x900.png) _1000×640 variant: [m0-spike-1000x640.png](m0-spike-1000x640.png)._ ## What M0 delivers - `bevy_forge_runtime` — a new crate in the workspace, added to a game with `.add_plugins(EditorPlugin)` after `DefaultPlugins`. - Fixed editor shell: toolbar, hierarchy (left), inspector (right), status bar; F1 or the toolbar button toggles the whole editor. - Live hierarchy: `Children`/`ChildOf` tree, indentation, scrolling, click selection, selected-row highlight. - Reflection inspector for `Name`, `Transform` and `Visibility`; translation X/Y/Z are editable via `bevy_ui_widgets` sliders and update the ECS entity. Rotation/scale/visibility are read-only in M0. - Editor camera (right-drag orbit, middle-drag pan, wheel zoom) and a translate gizmo with screen-space axis picking and ray/plane dragging. - Deterministic screenshot mode at fixed sizes with a scale factor override. - A small hardcoded 3D demo scene (nine named scene entities plus the editor camera) in `crates/bevy_forge_runtime/examples/editor_spike.rs`. ## Requirements - Rust 1.85+ (the workspace pins `rust-version = "1.85"`; this environment used 1.99). - Linux with Vulkan/GL and a windowing session (Wayland or X11). The reference run is Wayland with an NVIDIA RTX 3050; the UI and screenshots also work through the probe on this machine. - No Bevy installation is required; Bevy 0.20.0 is a normal Cargo dependency. ## Run ```bash cd bevy-forge cargo run -p bevy_forge_runtime --example editor_spike ``` The first run compiles the Bevy UI/PBR pipeline and is slow. The window opens at 1440×900. ## Controls | Input | Action | |---|---| | F1 / toolbar **Editor (F1)** | Show or hide the editor UI | | Left click a hierarchy row | Select that entity | | Left drag a gizmo axis | Translate the selected entity along X/Y/Z | | Right drag in the viewport | Orbit the editor camera | | Middle drag in the viewport | Pan the editor camera | | Mouse wheel | Zoom the editor camera | The inspector sliders edit `Transform.translation.x/y/z` in the range -20..=20 with 0.1 steps. A gizmo drag updates the ECS `Transform`, and the inspector sliders follow. ## Deterministic screenshots The screenshot mode is opt-in and exits after saving: ```bash FORGE_SCREENSHOT=$PWD/.swarm/m0/evidence/m0-1440x900.png \ FORGE_SCREENSHOT_SIZE=1440x900 \ cargo run -p bevy_forge_runtime --example editor_spike FORGE_SCREENSHOT=$PWD/.swarm/m0/evidence/m0-1000x640.png \ FORGE_SCREENSHOT_SIZE=1000x640 \ cargo run -p bevy_forge_runtime --example editor_spike ``` | Variable | Default | Meaning | |---|---|---| | `FORGE_SCREENSHOT` | unset | output PNG; unset disables the mode | | `FORGE_SCREENSHOT_SIZE` | `1440x900` | `WIDTHxHEIGHT`, 320..=7680 | | `FORGE_SCREENSHOT_FRAMES` | `300` | minimum frames before capture | | `FORGE_SCREENSHOT_WARMUP_SECS` | `10` | minimum wall-clock seconds before capture | The warmup is deliberate: UI/gizmo shaders are ready quickly, but the 3D mesh/PBR pipeline can take ~10 s to compile on a cold run. A 30-frame screenshot is blank; the mode waits for both thresholds. The window is forced to `WindowResolution::new(w, h).with_scale_factor_override(1.0)`, so the PNG is exactly the requested size on HiDPI displays. **Determinism caveat:** the hierarchy hover highlight follows the pointer. Park the cursor outside the editor window before capturing if you need byte-identical pixels; the committed evidence was captured that way. The screenshot mode fixes size, scene and frame timing, but does not currently neutralise pointer hover. ## Architecture ``` crates/bevy_forge_runtime/ ├── src/lib.rs public prelude: EditorPlugin, EditorState, Selection, InspectorSource ├── src/plugin.rs resources, plugin registration, selection cleanup ├── src/ui/ fixed shell, theme, markers, EditorLayout ├── src/hierarchy.rs live ListBox/ScrollArea tree + selection observer ├── src/inspector.rs reflection summary/apply, transform sliders, live sync ├── src/gizmo.rs editor camera, axes drawing, picking/drag ├── src/screenshot.rs deterministic PNG mode └── examples/editor_spike.rs ``` The editor UI is an overlay: the 3D camera renders full-window and the panels cover the left/right edges. `EditorLayout::viewport_rect` defines the center rectangle used by gizmo input. ## M0 acceptance The full evidence is in `.swarm/m0/reviews/V01.md` and `.swarm/m0/final-report.md`; the commands are listed in `.swarm/m0/plan.md`. In short: - `cargo check -p bevy_forge_runtime` passes; `cargo test -p bevy_forge_runtime` is **38 passed, 0 failed, 0 ignored** plus one ignored doctest; the full workspace is **384 passed, 0 failed, 2 ignored** (v1 + M0). - `cargo tree -p bevy_forge_runtime -i egui` finds no egui; a plain tree grep for `egui` is empty. The v1 editor still uses egui; the runtime crate does not. `bevy_ui_widgets` resolves to 0.20.0. - The example launches, logs `editor shell ready`, `hierarchy: 10 rows, 7 roots`, `inspector: selected ... (Hero Cube)` and `gizmo: camera ready`, with no warnings/panics. - The gizmo is visible on the selected entity; its drag math is unit-tested (including a rotated parent). Computer-use on 2026-10-27 clicked hierarchy rows, dragged the inspector X slider and the X gizmo axis, toggled the UI and zoomed the camera; selection, inspector, ECS and gizmo followed, with no panic. - Screenshots are exactly 1440×900 and 1000×640; both show the shell, hierarchy, inspector and gizmo. - No v1/core/CLI source changes; only the workspace member/lock, the new crate, docs and README. - Independent review: **pass_with_risks** (`.swarm/m0/reviews/V01.md`, local coordination artifact). All acceptance gates pass; the residual risks are right/middle orbit-pan (not scripted) and the disclosed hierarchy root filter. ## Interactive verification (computer-use, 2026-10-27) The editor was driven through the KDE Wayland remote-desktop portal with the computer-use tool: - clicked `Red Cube`, `Blue Cube`, `Ground` and `Hero Cube` in the hierarchy — selection, inspector fields and gizmo moved to the clicked entity every time; - dragged the Red Cube Translation X slider from −2.6 to 3.2 — the cube and gizmo moved and the inspector value updated; - dragged the Hero Cube X gizmo axis from 0.0 to 1.0 — the cube moved and the inspector slider followed; - the toolbar button hid the UI; F1 restored it; wheel zoom changed the camera distance. This found a real bug that unit tests missed: on a selection change, the inspector's transform-sync system ran after the panel rebuild and queued a `SliderValue` insert for a slider that had just been despawned, panicking in Bevy's command queue. The systems are now chained **sync-first, then rebuild**; repeated selection/slider/gizmo runs are clean. Orbit and pan (right/middle drag) are not scripted by the portal drag helper and remain a manual check; wheel zoom is covered. ## Limits (M0, by design) - No save/load of `.forge.ron`, no BSN export from the UI, no undo/redo, no play/pause, no asset browser, no docking, no multi-select, no rotate/scale gizmo. - The demo scene is hardcoded; `bevy_forge_core` is not a runtime dependency yet. - The live hierarchy panel lists named, transformed scene roots and their descendants; unnamed root entities are omitted in M0 (a full-world mode is M1 work). `collect_rows` remains the literal tree model for tests. - The inspector covers `Name`/`Transform`/`Visibility`; generic `TypeRegistry` component discovery is M1 work. - Parent scale is ignored during gizmo drags (M0); rotations are honored. - 3D only in the demo; the v2 plan adds 2D and scene loading in M1/M2. ## Next M1 Core: `.forge.ron` save/load via `bevy_forge_core`, selection API/multi-select, undo/redo command stack, editor camera polish, and the first integration tests against the real scene format. Do not start M1 until M0 is accepted by the verifier and the actual request/token spend is recorded.