Files
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

8.2 KiB
Raw Permalink Blame History

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

1000×640 variant: 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

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:

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.