- 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
363 lines
17 KiB
Markdown
363 lines
17 KiB
Markdown
# ◆ Bevy Forge
|
||
|
||
**A native visual scene editor for the Bevy engine, built around Bevy 0.20's BSN scene notation.**
|
||
|
||
Bevy Forge opens a Bevy project, lets you lay out a 2D or 3D scene with a hierarchy, inspector,
|
||
viewports and asset browser, then exports the result as paste-ready **BSN Rust code** (primary)
|
||
or imperative `Commands::spawn` code. Everything is editable by hand: scenes are plain RON files
|
||
and generated code is ordinary Rust.
|
||
|
||

|
||
|
||
> **Status: early alpha (0.1.0).** The 0.1 feature set is implemented: the workspace tests,
|
||
> formatting check, CLI and generated-BSN compile gate are green on this checkout. This is not a
|
||
> tagged release, so expect rough edges and API churn before 0.1.0 is published.
|
||
|
||
## Why a standalone editor?
|
||
|
||
Bevy Forge does **not** link Bevy. The editor and core crates build without pulling Bevy into the
|
||
dependency graph and are not affected by Bevy's release cadence; they target Bevy 0.20 through
|
||
generated code. The scene format is an editor-owned RON file, and export produces source code that
|
||
your game compiles. That keeps the tool independent of Bevy's runtime scene serialization and makes
|
||
the output easy to review, diff and check in.
|
||
|
||
Live in-game editing (a Bevy plugin with a remote protocol) is a roadmap item, not part of this
|
||
editor.
|
||
|
||
## v2 live editor (M0 spike)
|
||
|
||
The `v2-live-editor` branch moves editing into the game as a **Bevy 0.20 plugin** with native Bevy
|
||
UI and official `bevy_ui_widgets` — no egui in the runtime crate. M0 ships the `EditorPlugin`, a
|
||
fixed editor shell, live hierarchy, reflection inspector, translate gizmo, editor camera and
|
||
deterministic screenshots at 1440×900 / 1000×640.
|
||
|
||
```bash
|
||
cargo run -p bevy_forge_runtime --example editor_spike
|
||
```
|
||
|
||
See [docs/m0-spike.md](docs/m0-spike.md) for controls, architecture and M0 limits. The v1 standalone
|
||
editor below remains the current released workflow.
|
||
|
||
### M1 Core — real scene load/save + undo
|
||
|
||
M1 loads a real `.forge.ron` scene through `bevy_forge_core`, saves edits with Ctrl+S, adds
|
||
Transform undo/redo (Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y) and the F focus, Delete and Ctrl+D duplicate
|
||
hotkeys.
|
||
|
||
```bash
|
||
FORGE_PROJECT=examples/demo-project \
|
||
FORGE_SCENE=scenes/garden.forge.ron \
|
||
cargo run -p bevy_forge_runtime --example editor_live
|
||
```
|
||
|
||
See [docs/m1-core.md](docs/m1-core.md) for the garden demo, hotkeys and M1 limits.
|
||
|
||
### M2 Live — play mode, assets, export, hot reload
|
||
|
||
M2 adds Play/Pause/Stop with transform snapshot/restore, a project asset browser, BSN/Rust export
|
||
and a `.forge.ron` transform watcher.
|
||
|
||
```bash
|
||
FORGE_PROJECT=examples/demo-project \
|
||
FORGE_SCENE=scenes/garden.forge.ron \
|
||
cargo run -p bevy_forge_runtime --example editor_live
|
||
```
|
||
|
||
See [docs/m2-live.md](docs/m2-live.md) for controls and M2 limits.
|
||
|
||
## Two viewports
|
||
|
||
| 2D scene editing | 3D wireframe preview |
|
||
|---|---|
|
||
|  |  |
|
||
|
||
## Features
|
||
|
||
- **Project-aware editor.** Opens a directory containing a `Cargo.toml` with a `bevy` dependency,
|
||
indexes its `assets/` folder and lists its `scenes/*.forge.ron` files.
|
||
- **Hierarchy panel.** Create empty entities, sprites, text, cameras, lights and primitive meshes;
|
||
rename inline; duplicate; delete; reparent and reorder by dragging (cycles rejected); lock and
|
||
hide entities; search the tree.
|
||
- **Inspector.** Name and Transform editing (translation, Euler rotation, scale, reset); add/remove
|
||
components; asset pickers for images and meshes; colour and numeric editors; mesh primitive
|
||
parameters and material presets; validation issues for the selected entity.
|
||
- **2D viewport.** Textured sprites, text and camera/light glyphs, grid and axes, pan and
|
||
cursor-anchored zoom, click selection, grid-snapped dragging, X/Y translate gizmo, drag-and-drop
|
||
of images from the asset browser, fit view.
|
||
- **3D viewport.** egui-painted wireframe preview (no GPU renderer): orbit/pan/zoom camera, grid,
|
||
primitive and sprite proxies, camera/light glyphs, click selection, ground-plane dragging, fit.
|
||
- **Asset browser.** Recursive index of the Bevy `assets/` directory with kind filters, search,
|
||
lazy thumbnails, double-click assignment and drag payloads for viewports.
|
||
- **Undo/redo.** Snapshot-based history (100 steps by default) for every structural and property
|
||
edit, including a single undo entry per gizmo drag.
|
||
- **Validation.** Structural, asset-reference and numeric range checks surfaced in the UI and by
|
||
the CLI, with `error` / `warning` / `info` severities.
|
||
- **Persistence.** Human-readable `.forge.ron` scenes, atomic writes, optional autosave.
|
||
- **Two export formats.** Bevy 0.20 BSN (`bsn!` / `bsn_list!`) and imperative Rust with
|
||
`Commands::spawn` + `.with_children`.
|
||
- **Command line.** `forge new`, `forge validate`, `forge export`, `forge info`, `forge scenes`.
|
||
- **Editor chrome.** Dark theme, menu bar, status bar, command palette, toasts, welcome screen,
|
||
keyboard-shortcut reference and unsaved-changes protection.
|
||
|
||
## Requirements
|
||
|
||
- **Rust stable, 1.85 or newer** (the workspace sets `rust-version = "1.85"`) and Cargo.
|
||
- A desktop session with a working GPU/windowing stack for `eframe`/`egui`:
|
||
Linux (X11 or Wayland), macOS, or Windows. Linux/Wayland is the primary development platform;
|
||
macOS and Windows go through the same `eframe` backend but are less exercised.
|
||
- **No Bevy installation is needed to build the editor or the CLI.** Bevy 0.20 is only needed when
|
||
you compile exported code inside a game, or when you check the excluded `compat/bsn-smoke` crate.
|
||
- A network connection the first time Cargo fetches dependencies, unless they are already cached.
|
||
In the prepared development environment, prefix routine builds with `CARGO_NET_OFFLINE=true`.
|
||
|
||
## Quick start
|
||
|
||
```bash
|
||
# 1. From this repository checkout.
|
||
cd bevy-forge
|
||
|
||
# 2. Run the editor on the bundled demo project.
|
||
cargo run -p bevy_forge_editor -- examples/demo-project
|
||
|
||
# 3. Or open a single scene directly (the project is discovered by walking up
|
||
# to the nearest Cargo.toml).
|
||
cargo run -p bevy_forge_editor -- examples/demo-project/scenes/garden.forge.ron
|
||
```
|
||
|
||
The editor binary is named `bevy-forge`. Launched without an argument it shows the welcome screen;
|
||
open a project by path (for example `examples/demo-project`), then pick a scene. Passing a project
|
||
or scene path on the command line opens it directly. From there:
|
||
|
||
1. Select an entity in the hierarchy and edit it in the inspector.
|
||
2. Switch the viewport between 2D and 3D with `2` / `3`.
|
||
3. Press `Ctrl+E` (Cmd+E on macOS) to open the export dialog and copy the generated BSN.
|
||
4. Press `Ctrl+S` to save the scene to `scenes/<name>.forge.ron`.
|
||
|
||
A new scene can be started from **File > New scene** (empty, 2D starter or 3D starter) or scaffolded
|
||
together with a Bevy project from the CLI.
|
||
|
||
## CLI
|
||
|
||
`forge` is the command-line companion. Run it through Cargo, or install the binary from this
|
||
repository:
|
||
|
||
```bash
|
||
# Run from the workspace root without installing:
|
||
cargo run -p bevy_forge_cli -- --help
|
||
|
||
# Optional: install the `forge` binary into ~/.cargo/bin.
|
||
cargo install --path crates/bevy_forge_cli
|
||
```
|
||
|
||
Common commands (all paths are examples):
|
||
|
||
```bash
|
||
# Scaffold a new Bevy 0.20 project. The target must not exist or must be empty.
|
||
forge new my-game --name my_game --template 3d
|
||
|
||
# Validate a scene; --project is discovered from the scene path when omitted.
|
||
forge validate examples/demo-project/scenes/garden.forge.ron
|
||
forge validate examples/demo-project/scenes/garden.forge.ron --json
|
||
|
||
# Export BSN (default) or imperative Rust.
|
||
forge export examples/demo-project/scenes/garden.forge.ron --format bsn -o /tmp/garden.rs
|
||
forge export examples/demo-project/scenes/platformer.forge.ron --format rust --function platformer
|
||
|
||
# Summarise a scene and list a project's scenes.
|
||
forge info examples/demo-project/scenes/garden.forge.ron
|
||
forge scenes examples/demo-project
|
||
```
|
||
|
||
`forge new --template` accepts `empty`, `2d` (default) or `3d`. It writes a complete Bevy 0.20
|
||
project: `Cargo.toml`, `src/main.rs`, `assets/` (generated textures where the template needs them),
|
||
`scenes/demo.forge.ron`, `.gitignore` and a `README.md`.
|
||
|
||
Exit codes follow the CLI contract:
|
||
|
||
| Command | `0` | `1` | `2` |
|
||
|---|---|---|---|
|
||
| `forge new` | project created | - | target exists and is not empty, I/O error |
|
||
| `forge validate` | no validation errors | validation errors found | I/O, RON parse or usage error |
|
||
| `forge export` | code generated | codegen error (empty scene, invalid function name, non-finite value, bad custom component) | I/O, RON parse or usage error |
|
||
| `forge info` | printed | - | I/O, RON parse or usage error |
|
||
| `forge scenes` | listed | - | not a project or I/O error |
|
||
|
||
`--help` and `--version` are available on every command level. Human-readable output goes to
|
||
stdout; user errors go to stderr with a non-zero exit.
|
||
|
||
## Getting BSN into a Bevy app
|
||
|
||
Export BSN from the editor (**File > Export > BSN scene**) or the CLI. The result is a Rust module,
|
||
not a runtime asset: put it next to your game code and call the generated function from a startup
|
||
system.
|
||
|
||
```bash
|
||
# From the game project's root: write the generated module into src/.
|
||
forge export scenes/garden.forge.ron --format bsn -o src/garden.rs
|
||
```
|
||
|
||
```rust
|
||
// src/main.rs of a Bevy 0.20 game
|
||
use bevy::prelude::*;
|
||
|
||
mod garden; // the exported file; its function is `garden::scene(..)`
|
||
|
||
fn main() {
|
||
App::new()
|
||
.add_plugins(DefaultPlugins)
|
||
.add_systems(Startup, spawn_garden)
|
||
.run();
|
||
}
|
||
|
||
fn spawn_garden(
|
||
mut commands: Commands,
|
||
mut meshes: ResMut<Assets<Mesh>>,
|
||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||
) {
|
||
// The generated signature includes only the asset parameters the scene needs.
|
||
commands.spawn_scene(garden::scene(&mut meshes, &mut materials));
|
||
}
|
||
```
|
||
|
||
- A scene without meshes generates `pub fn scene() -> impl Scene` - call it with no arguments.
|
||
- A scene with meshes generates `meshes` / `materials` parameters (only the ones it uses). Pass
|
||
`&mut Assets<Mesh>` / `&mut Assets<StandardMaterial>` from your systems.
|
||
- A scene with several roots generates `pub fn scene() -> impl SceneList`; spawn it with
|
||
`commands.spawn_scene_list(...)`.
|
||
- Custom components are emitted as `<type_path> { field: <raw expression> }`. The component type
|
||
must derive `Component` plus either `Default + Clone` or `FromTemplate`, and must be in scope
|
||
where the generated code is compiled.
|
||
|
||
The full template reference, derive requirements, material caveats and a troubleshooting table are
|
||
in the [BSN export guide](docs/bsn-export.md).
|
||
|
||
## Scene format
|
||
|
||
Scenes are human-readable RON files named `*.forge.ron`, stored in the project's `scenes/`
|
||
directory. They are Bevy Forge's own format - not Bevy's `.scn.ron` dynamic-scene serialization -
|
||
and contain no generated code.
|
||
|
||
- [Scene format reference](docs/format.md) - every field and component variant, versioning,
|
||
identity and forest invariants, asset paths, save/autosave and validation.
|
||
- [Architecture](docs/architecture.md) - crates, data flow, key types and the panel/action model.
|
||
|
||
## Project layout
|
||
|
||
```text
|
||
bevy-forge/
|
||
Cargo.toml workspace (core, editor, CLI)
|
||
crates/
|
||
bevy_forge_core/ scene model, project, undo, assets, validation, codegen
|
||
bevy_forge_editor/ eframe/egui desktop app; binary `bevy-forge`
|
||
bevy_forge_cli/ `forge` command line
|
||
examples/demo-project/ Bevy 0.20 demo project with garden (3D) and platformer (2D) scenes
|
||
compat/bsn-smoke/ excluded crate that compiles generated BSN against Bevy 0.20
|
||
docs/ architecture, scene format, BSN export
|
||
scripts/ generated-code verification helpers
|
||
```
|
||
|
||
## Keyboard shortcuts
|
||
|
||
`Ctrl` means `Cmd` on macOS. Shortcuts that mutate the scene are ignored while a text field has
|
||
keyboard focus.
|
||
|
||
| Shortcut | Action |
|
||
|---|---|
|
||
| `Ctrl+S` | Save the current scene |
|
||
| `Ctrl+Shift+S` | Save the scene as... |
|
||
| `Ctrl+O` | Open a project... |
|
||
| `Ctrl+K` | Command palette |
|
||
| `F1` | Keyboard-shortcut reference |
|
||
| `Ctrl+Z` | Undo |
|
||
| `Ctrl+Shift+Z`, `Ctrl+Y` | Redo |
|
||
| `Ctrl+D` | Duplicate selection |
|
||
| `Delete` | Delete selection |
|
||
| `Ctrl+E` | Export BSN scene |
|
||
| `Ctrl+Shift+E` | Export imperative Rust |
|
||
| `F` | Fit the active viewport to the scene |
|
||
| `G` | Toggle the grid |
|
||
| `2` / `3` | Switch to the 2D / 3D viewport |
|
||
| `Ctrl+B` | Toggle the asset browser |
|
||
| `Ctrl+Shift+L` | Toggle the hierarchy panel |
|
||
| `Esc` | Clear the selection (while not typing) |
|
||
|
||
Command palette: type to filter, `Up`/`Down` to move, `Enter` to run, `Esc` to close.
|
||
|
||
Mouse and pointer interactions:
|
||
|
||
| Context | Input | Action |
|
||
|---|---|---|
|
||
| Hierarchy | click / `Ctrl`+click / `Shift`+click | Select / toggle / extend selection |
|
||
| Hierarchy | double-click, right-click | Rename inline, context menu (rename, duplicate, delete, focus, lock) |
|
||
| Hierarchy | drag | Reparent or reorder (cycle-creating drops are rejected) |
|
||
| 2D viewport | middle mouse, or `Space`+left mouse | Pan |
|
||
| 2D viewport | mouse wheel | Zoom around the cursor |
|
||
| 2D viewport | click / `Shift`+click | Select topmost / toggle |
|
||
| 2D viewport | drag selection, X/Y gizmo handles | Move (grid-snapped when enabled) |
|
||
| 3D viewport | middle mouse, or `Alt`+left mouse | Orbit |
|
||
| 3D viewport | `Shift`+middle mouse | Pan |
|
||
| 3D viewport | mouse wheel | Zoom |
|
||
| 3D viewport | click, drag | Select, move on the ground plane |
|
||
|
||
Locked entities ignore viewport transforms; hidden entities are skipped by picking. Pan, zoom,
|
||
orbit and fit never modify the document.
|
||
|
||
## Limitations and roadmap
|
||
|
||
Bevy Forge is deliberately focused. Current limitations:
|
||
|
||
- **No live editing.** The editor is standalone; there is no in-game plugin, remote protocol or
|
||
hot reload of a running Bevy app.
|
||
- **BSN is source code, not an asset.** Export writes Rust that your game compiles. Runtime `.bsn`
|
||
asset loading/caching is not implemented.
|
||
- **Custom components are raw expressions.** The editor does not parse your Rust types, so custom
|
||
component fields are stored as raw Rust/BSN expressions with only basic identifier and
|
||
non-empty-expression checks.
|
||
- **Validation is static.** It checks structure, asset references and value ranges; it does not run
|
||
`rustc` on exported code.
|
||
- **Material asset caveat.** There is no `StandardMaterial` asset loader by default. Generated BSN
|
||
uses inline `materials.add(StandardMaterial { ... })`, so it does not need a registered material
|
||
loader; hand-referenced material assets such as `materials/cube.toml` do need one in your game.
|
||
- **3D preview, not a renderer.** The 3D viewport paints wireframes and proxies with egui. There is
|
||
no PBR preview, shadow preview or GPU scene rendering.
|
||
- **Editor features out of scope for 0.1:** animation editor, `bevy_ui` editor, material graph,
|
||
terrain tools, collaboration, asset import pipeline.
|
||
- **Bevy 0.20 only.** Generated code targets Bevy 0.20.0 BSN. Legacy dynamic-scene (`.scn.ron`)
|
||
syntax and broad multi-version support are out of scope.
|
||
- **No native file dialogs.** Paths are typed into in-app dialogs.
|
||
- **Undo history is in-memory** (100 steps by default) and is cleared when a scene is opened.
|
||
|
||
Roadmap direction: in-game live editing over a plugin/remote protocol, runtime scene assets,
|
||
richer asset previews and a plugin-facing API. Roadmap items are not implemented yet.
|
||
|
||
## Contributing
|
||
|
||
1. Read [the architecture notes](docs/architecture.md) and [the scene format](docs/format.md).
|
||
Public model APIs are small and should stay stable.
|
||
2. Keep the dependency rule: `bevy_forge_core` and `bevy_forge_editor` never depend on Bevy; the
|
||
excluded `compat/bsn-smoke` crate is the only Bevy-dependent crate.
|
||
3. Format with `cargo fmt` and keep `cargo check --workspace` warning-free for the crates you
|
||
touch. Do not add dependencies without agreement.
|
||
4. Tests live next to the code (`#[cfg(test)]` modules) and under `crates/*/tests/`; CLI tests run
|
||
the real binary with `CARGO_BIN_EXE_forge`. The generated-code gate compiles exported BSN in
|
||
`compat/bsn-smoke`.
|
||
5. Update the relevant page in `docs/` when behaviour or a template changes.
|
||
|
||
Useful verification commands (run them in your checkout; no claim is made that they are green at
|
||
every commit):
|
||
|
||
```bash
|
||
cargo check --workspace
|
||
cargo test --workspace
|
||
cargo fmt --all --check
|
||
cargo run -p bevy_forge_cli -- validate examples/demo-project/scenes/garden.forge.ron
|
||
cd compat/bsn-smoke && cargo check
|
||
```
|
||
|
||
## License
|
||
|
||
Bevy Forge is dual-licensed under the **MIT OR Apache-2.0** license, at your option. See
|
||
[LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE). Unless you explicitly state
|
||
otherwise, any contribution intentionally submitted for inclusion in this project shall be
|
||
dual-licensed as above, without any additional terms or conditions.
|