Files
Bevy_Forge/docs/m0-spike.md
T
Emil Shanaty 59212c952f feat(runtime): add Bevy 0.20 live editor M0 spike
- new bevy_forge_runtime crate with EditorPlugin, EditorState, Selection
- native Bevy UI shell + official bevy_ui_widgets 0.20 (no egui in runtime)
- live hierarchy, reflection inspector, translate gizmo, editor camera
- deterministic 1440x900/1000x640 screenshot mode
- demo example, docs and screenshots; v1 crates untouched
- interactive computer-use test fixed inspector command-queue panic
2026-10-27 22:14:21 +03:00

164 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.