# Bevy Forge v2 — M1 Core Status: **M1 Core complete and independently verified (`pass_with_risks`)**. M0 is committed at `59212c9`; M1 turns the M0 spike into a scene-editing slice that reads and writes the existing `bevy_forge_core` `.forge.ron` format. ![Bevy Forge M1 Core — garden scene](m1-core-1440x900.png) _1000×640 variant: [m1-core-1000x640.png](m1-core-1000x640.png)._ ## What M1 adds - **Real scene load**: `FORGE_PROJECT` + `FORGE_SCENE` load a `.forge.ron` scene through `bevy_forge_core` into the live ECS. The garden demo is the reference scene. - **Save**: Ctrl+S syncs edited transforms/names/visibility back into the scene document and writes a `.forge.ron` file (`FORGE_SAVE_PATH`, default `scenes/edited.forge.ron`). - **Transform undo/redo**: Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y for inspector-slider and gizmo-drag edits. - **Hotkeys**: Ctrl+S save, F focus camera, Delete delete the selected subtree, Ctrl+D duplicate the selected subtree. - Focused tests: **66 runtime tests** (scene 6, shortcuts 6, history 8, inspector 13, gizmo 10, plus the M0 suite), all green. - Independent verification: **V11 pass_with_risks** (`.swarm/m1/reviews/V11.md`), including a post-review delta after the camera guard. Runtime **66 tests**, workspace **412 passed, 2 ignored**. - Interactive checks done: load 9/7, slider edit → Ctrl+Z → Ctrl+Shift+Z, Ctrl+S with a valid saved RON (garden source untouched), Ctrl+D duplicate, Delete, F focus, camera delete/duplicate refusal, no panic. ## 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 ``` | Variable | Default | Meaning | |---|---|---| | `FORGE_PROJECT` | `examples/demo-project` | project root with a `Cargo.toml` containing bevy | | `FORGE_SCENE` | `scenes/garden.forge.ron` | scene to load, relative to the project root | | `FORGE_SAVE_PATH` | `scenes/edited.forge.ron` | Ctrl+S output, relative to the project root | The scene plugin loads when at least one of `FORGE_PROJECT`/`FORGE_SCENE` is set; the command above sets both. The garden scene has 9 entities / 7 roots (Camera, Sun, Ground, Shrub, Flower Stem, Flower Bloom, Orbit Crystal, Lantern Post, Lantern Glow). The custom `forge_demo::Orbit` component is skipped in the live ECS with a warning; all 3D meshes, lights, camera, names, transforms and visibility load. ## Controls | Input | Action | |---|---| | F1 / **Editor (F1)** | Toggle the editor UI | | Click hierarchy row | Select entity | | Drag inspector Translation X/Y/Z | Move selected entity | | Drag gizmo axis | Move selected entity | | Right/middle drag, wheel | Orbit / pan / zoom camera | | **Ctrl+S** | Save `.forge.ron` | | **Ctrl+Z** | Undo transform edit | | **Ctrl+Shift+Z / Ctrl+Y** | Redo transform edit | | **F** | Focus camera on selected entity | | **Delete** | Delete selected subtree | | **Ctrl+D** | Duplicate selected subtree | Delete/duplicate are structural edits and are **not undoable in M1**; undo/redo is Transform-only. ## Architecture ``` crates/bevy_forge_runtime/ ├── src/scene.rs .forge.ron load, ECS spawn, save/sync, delete/duplicate helpers ├── src/shortcuts.rs Ctrl+S / F / Delete / Ctrl+D ├── src/history.rs transform command stack + Ctrl+Z/Y ├── src/inspector.rs M0 reflection inspector + history capture ├── src/gizmo.rs M0 camera/gizmo + history capture ├── src/hierarchy.rs M0 live tree └── examples/editor_live.rs ``` The runtime now depends on `bevy_forge_core` (Bevy-free model/persistence). Core `Transform` uses XYZ Euler degrees; the bridge converts to/from Bevy quaternions with `bevy_forge_core::math::{quat_from_euler_deg, quat_to_euler_deg}`. ## Limits (M1) - 3D only in the live bridge; Sprite/Text2d/Camera2d components are skipped (M2). - Custom components are skipped in ECS but preserved in the document on save. - Delete/duplicate are not undoable; multi-select/docking/terminal/play mode are out of scope. - Deleting or duplicating a `Camera3d` subtree is refused with a warning in M1: the editor camera is adopted from the scene, and a second active camera would break the viewport. - V11 residual: a synthetic portal drag can be shorter than one Bevy frame, so the live gizmo drag → Ctrl+Z path and the inspector click/snap finalizer remain unit/helper-tested rather than scripted end-to-end. Slider-drag undo is interactively verified. - The garden `Camera3d` is adopted by the editor camera; do not add a second active camera. - Saving must be explicit (Ctrl+S); there is no autosave loop yet. - Hover styling and screenshot determinism: park the pointer outside the window for byte-stable screenshots (M0 caveat). - A synthetic portal drag can be shorter than one Bevy frame, so the live gizmo-drag → Ctrl+Z path is covered by transform helper/unit tests and the unchanged M0 drag code, not by a scripted mouse hold; the slider undo path is interactively verified. ## Verification M0 acceptance is in [`m0-spike.md`](m0-spike.md). M1 was independently verified by V11: `.swarm/m1/reviews/V11.md` (initial and post-fix delta). The exact commands are in `.swarm/m1/plan.md`; the final report with actual spend is in the local M1 coordination dir.