Bevy Forge 0.1.0: visual scene editor for Bevy 0.20 BSN

This commit is contained in:
Emil Shanaty
2026-10-27 18:52:10 +03:00
commit 13bf16d510
79 changed files with 44353 additions and 0 deletions
+321
View File
@@ -0,0 +1,321 @@
# ◆ 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.
![Bevy Forge editor](docs/screenshot.png)
> **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.
## Two viewports
| 2D scene editing | 3D wireframe preview |
|---|---|
| ![2D viewport with the platformer demo](docs/screenshot.png) | ![3D viewport with the garden demo](docs/screenshot-3d.png) |
## 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.