Files
Emil Shanaty 72960eb2d0 feat(runtime): add M2 live play mode, assets, export and hot reload
- play/pause/stop with a tracked-transform snapshot and validation summary
- asset browser with kind filters and image preview from project assets
- BSN and imperative Rust export through bevy_forge_core codegen
- .forge.ron watcher applying transform/name/visibility edits
- 95 runtime tests; workspace 441 passed; M2 demo docs/screenshots
2026-10-27 23:51:41 +03:00

73 lines
3.4 KiB
Markdown
Raw Permalink 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 — M2 Live
Status: **M2 Live complete and independently verified (`pass_with_risks`)**. M1 Core is committed at
`3eea9c0`; M2 adds live-mode controls and project workflow around the M1 scene editor.
![Bevy Forge M2 Live — play mode and asset browser](m2-live-1440x900.png)
_1000×640 variant (play overlay, panel closed): [m2-live-1000x640.png](m2-live-1000x640.png)._
## What M2 adds
- **Play / Pause / Stop**: a viewport overlay and keyboard controls. Play animates the scene, Pause
freezes it, Stop restores every tracked transform exactly (the snapshot includes the camera pose
captured on Play). A small validation summary (errors/warnings/info) is shown for the loaded
scene.
- **Asset browser**: toggle with `B`; lists the project `assets/` folder with kind filters and an
image preview.
- **Export**: `Ctrl+E` writes BSN, `Ctrl+Shift+E` writes imperative Rust to `exports/` using the
existing `bevy_forge_core` codegen. The garden has seven roots, so its BSN uses core's
`bsn_list!`; single-root scenes use `bsn!`.
- **Hot reload watcher**: when the loaded `.forge.ron` changes on disk, transform/name/visibility
changes are applied to existing entities. Add/remove is logged and ignored in M2; the camera is
never duplicated.
## Run
```bash
cd bevy-forge
FORGE_PROJECT=examples/demo-project \
FORGE_SCENE=scenes/garden.forge.ron \
cargo run -p bevy_forge_runtime --example editor_live
```
## Controls
| Input | Action |
|---|---|
| F1 / toolbar **Editor (F1)** | Toggle the editor UI |
| Click hierarchy row | Select entity |
| Drag inspector slider / gizmo axis | Move selected entity |
| Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y | Undo / redo transform |
| Ctrl+S | Save `.forge.ron` |
| F | Focus camera |
| Delete / Ctrl+D | Delete / duplicate subtree |
| **P** | Play / pause |
| **Shift+P / Esc** | Stop and restore |
| **B** | Toggle asset browser |
| **Ctrl+E / Ctrl+Shift+E** | Export BSN / Rust |
## Limits (M2)
- Asset **drag-into-scene is deferred to M3**: `bevy_forge_core::MaterialData` has no texture field
yet, so the browser is list/filter/preview only.
- Watcher hot reload applies transform/name/visibility to existing mapped IDs; adding or removing
entities/components requires a restart in M2. The watcher has no spawn/despawn path, so the editor
camera cannot be duplicated.
- Play mode is a snapshot/restore demonstration (rotating meshes), not a full game play mode.
- 3D only; custom components are preserved in the document but skipped in the live ECS.
- Delete/duplicate are not undoable; multi-select/docking/terminal are out of scope.
- The asset browser uses the project's `assets/` via `BEVY_ASSET_ROOT` (set by `editor_live`);
files outside the asset root fall back to a local decode for preview only.
- Tests: **95 runtime tests**, workspace **441 passed / 2 ignored**. M2 validation was run with the
garden demo (9 entities / 7 roots) and computer-use for Play/Pause/Stop, the asset panel and
exports.
## Verification
M0: [`m0-spike.md`](m0-spike.md). M1: [`m1-core.md`](m1-core.md). M2: **V21 pass_with_risks**
(`.swarm/m2/reviews/V21.md`); runtime **95 tests**, workspace **441 passed / 2 ignored**. V21's
low-severity residuals are the live 3-key `Ctrl+Shift+E` portal injection (handler unit-tested), play
shortcuts remaining active while the editor is hidden, the camera pose restored on Stop by design,
and the watcher not retrying a failed parse until the next mtime change.