From 440b391dda92d9be571c01bb632665fc04fc5374 Mon Sep 17 00:00:00 2001 From: Jaco du Preez Date: Sun, 9 Aug 2026 20:16:52 +0200 Subject: [PATCH 01/10] feat: add engine-bevy module manifests --- .agents/modules/engine-bevy/modulefile.yaml | 11 +++++++++++ .opencode/modules/engine-bevy/modulefile.yaml | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 .agents/modules/engine-bevy/modulefile.yaml create mode 100644 .opencode/modules/engine-bevy/modulefile.yaml diff --git a/.agents/modules/engine-bevy/modulefile.yaml b/.agents/modules/engine-bevy/modulefile.yaml new file mode 100644 index 0000000..3244bb7 --- /dev/null +++ b/.agents/modules/engine-bevy/modulefile.yaml @@ -0,0 +1,11 @@ +name: engine-bevy +version: "0.6.0" +description: "Bevy engine specialist — Rust ECS game engine for 2D and 3D." +depends: [core] +provides: + agents: [bevy-specialist] + skills: [] + commands: [] + rules: [] +plugged-into: + engines: [bevy] diff --git a/.opencode/modules/engine-bevy/modulefile.yaml b/.opencode/modules/engine-bevy/modulefile.yaml new file mode 100644 index 0000000..3244bb7 --- /dev/null +++ b/.opencode/modules/engine-bevy/modulefile.yaml @@ -0,0 +1,11 @@ +name: engine-bevy +version: "0.6.0" +description: "Bevy engine specialist — Rust ECS game engine for 2D and 3D." +depends: [core] +provides: + agents: [bevy-specialist] + skills: [] + commands: [] + rules: [] +plugged-into: + engines: [bevy] From 3aa11879a4bfd1f95cbc59b9235ae82602e48adf Mon Sep 17 00:00:00 2001 From: Jaco du Preez Date: Sun, 9 Aug 2026 20:22:43 +0200 Subject: [PATCH 02/10] docs(engine-reference): add Bevy 0.19 core reference docs (VERSION, breaking-changes, deprecated-apis, current-best-practices) Task 2 of Bevy engine support: source-verified reference set for Bevy 0.19.0 (2026-06-18), covering 0.16->0.17, 0.17->0.18, 0.18->0.19 transitions. Every entry cites the official migration guide or release page. --- docs/engine-reference/bevy/VERSION.md | 65 ++++ .../engine-reference/bevy/breaking-changes.md | 325 ++++++++++++++++++ .../bevy/current-best-practices.md | 269 +++++++++++++++ docs/engine-reference/bevy/deprecated-apis.md | 62 ++++ 4 files changed, 721 insertions(+) create mode 100644 docs/engine-reference/bevy/VERSION.md create mode 100644 docs/engine-reference/bevy/breaking-changes.md create mode 100644 docs/engine-reference/bevy/current-best-practices.md create mode 100644 docs/engine-reference/bevy/deprecated-apis.md diff --git a/docs/engine-reference/bevy/VERSION.md b/docs/engine-reference/bevy/VERSION.md new file mode 100644 index 0000000..ec85ce0 --- /dev/null +++ b/docs/engine-reference/bevy/VERSION.md @@ -0,0 +1,65 @@ +# Bevy Engine — Version Reference + +| Field | Value | +|-------|-------| +| **Engine Version** | Bevy 0.19.0 (latest 0.19.x as of 2026-08-09; no 0.19.1 patch released yet) | +| **Release Date** | 2026-06-18 | +| **Project Pinned** | 2026-08-09 | +| **Last Docs Verified** | 2026-08-09 | +| **LLM Knowledge Cutoff** | May 2025 | + +## Knowledge Gap Warning + +Bevy 0.19 is BEYOND the LLM's training data cutoff (May 2025; training data +covers roughly 0.16–0.17). Risk level is HIGH. Agents MUST verify every API +against this reference set or the official docs before use. + +## Risk Level: HIGH + +Bevy ships a new minor version roughly every 3 months with breaking changes. +The Migration Guides are the authoritative source for version transitions. + +## Version History + +| Version | Release | Risk Level | Key Theme | +|---------|---------|------------|-----------| +| 0.16 | 2025-04-24 | HIGH | `Event` trait split into `Message` (buffered) and `Event` (observers); `bevy_render` reorganized into `bevy_camera` / `bevy_shader` / `bevy_light` / `bevy_mesh` / `bevy_image`; system sets standardized on `*Systems` naming | +| 0.17 | 2025-09-30 | HIGH | Entities rework (`EntityRow` index, flush removed, `EntitiesAllocator`); `RenderTarget` moved from a `Camera` field to a component; Cargo feature collections; `Internal` component removed | +| 0.18 | 2026-01-13 | HIGH | Resources are now stored as components on dedicated entities; `RenderGraph` replaced by systems; text moved from `cosmic-text` to `parley`; `bevy_scene` renamed to `bevy_world_serialization` (BSN arrives) | +| 0.19 | 2026-06-18 | HIGH | Resources-as-components; render graph as systems; Parley text overhaul; `audio`/`ui` Cargo features no longer implied by `3d`/`2d`; bloom luma now computed in linear space | + +## Bevy Characteristics + +- **Rust game engine**, ECS-first (data-oriented design) +- **Code-only** — no visual editor; all content is code, assets, and .ron data +- **Renderer**: wgpu (WebGPU/WebGL abstraction), 2D and 3D +- **UI**: bevy_ui (retained node tree, flexbox) +- **Assets**: AssetServer / bevy_asset with hot reload +- **Licensing**: MIT OR Apache-2.0 — free forever, no restrictions +- **Platform support**: Windows, macOS, Linux, Web (WASM), Android/iOS (via mobile examples) + +## Key Crates + +| Crate | Purpose | +|-------|---------| +| bevy | Main engine crate (re-exports everything through `bevy::prelude`) | +| bevy_ecs | Entity-Component-System core: World, queries, systems, schedules, observers | +| bevy_render | Core rendering infrastructure, render world and render resources | +| bevy_ui | Retained UI node tree (flexbox layout) | +| bevy_asset | Asset loading, `AssetServer`, hot reload | +| bevy_audio | Audio playback (rodio backend; format support behind `vorbis`/`wav`/`mp3`/`flac` features) | +| bevy_camera | Camera types (`Camera`, `Camera3d`, `Camera2d`, projections) — split out of `bevy_render` in 0.17 | +| bevy_shader | Shader types (`Shader`, `ShaderRef`, `ShaderCache`) — split out in 0.17 | +| bevy_light | Light types (`PointLight`, `SpotLight`, `DirectionalLight`, `AmbientLight`, `Skybox`, `Atmosphere`) — split out in 0.17 | +| bevy_mesh | Mesh types (`Mesh`, `Mesh3d`, `Mesh2d`, `Indices`, `Meshable`) — split out in 0.17 | +| bevy_image | Image types (`Image`, `ImagePlugin`, `ImageFormat`) — split out in 0.17 | +| bevy_material | Material machinery extracted from `bevy_pbr`/`bevy_render` in 0.19 (`AlphaMode`, `MaterialProperties`) | +| bevy_world_serialization | Legacy scene system (renamed from `bevy_scene` in 0.19; `Scene` → `WorldAsset`, `SceneRoot` → `WorldAssetRoot`); still needed for round-trip world serialization and GLTF scene spawning | + +## Verified Sources + +- Official website: https://bevyengine.org/ (redirects to https://bevy.org/) +- GitHub repository: https://github.com/bevyengine/bevy +- Migration guides: https://bevyengine.org/learn/migration-guides/ (canonical: https://bevy.org/learn/migration-guides/) +- API docs: https://docs.rs/bevy +- Release feed (dates/tags): https://github.com/bevyengine/bevy/releases diff --git a/docs/engine-reference/bevy/breaking-changes.md b/docs/engine-reference/bevy/breaking-changes.md new file mode 100644 index 0000000..dc28a7f --- /dev/null +++ b/docs/engine-reference/bevy/breaking-changes.md @@ -0,0 +1,325 @@ +# Bevy Breaking Changes (0.16 → 0.19) + +**Last verified:** 2026-08-09 + +Changes are organized by risk level. Source for each entry: the official +Migration Guides (https://bevyengine.org/learn/migration-guides/). + +## High Risk (compile-breaking, widespread) + +### 0.19 — Resources are now components +- **Old**: + ```rust + #[derive(Component, Resource)] + struct MyData(f32); + ``` +- **New**: + ```rust + #[derive(Component)] + struct MyDataComp(f32); + + #[derive(Resource)] + struct MyDataRes(f32); + ``` +- **Migration**: `Resource` is a subtrait of `Component` in 0.19 and `#[derive(Resource)]` implements both, so it is no longer possible to derive both traits on one type. Types can no longer meaningfully be used as both resources and components; split them into distinct types. Broad queries (`Query`, `Query<()>`, etc.) now include resource entities and can conflict with `Res`/`NonSend` params — filter them out with `Without` / `Without`. `ResMut` and the `*_mut` resource accessors now require `Resource` in generic code. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#resources-as-components + +### 0.19 — Render graph replaced by systems +- **Old**: + ```rust + impl ViewNode for MyNode { /* ... */ } + render_app + .add_render_graph_node::>(Core3d, MyLabel) + .add_render_graph_edges(Core3d, (Node3d::Foo, MyLabel, Node3d::Bar)); + ``` +- **New**: + ```rust + pub fn my_render_pass( + world: &World, + view: ViewQuery<(&ExtractedCamera, &ViewTarget)>, + mut ctx: RenderContext, + ) { + let (camera, target) = view.into_inner(); + // ... + } + + render_app.add_systems( + Core3d, + my_render_pass + .after(foo_pass) + .before(bar_pass) + .in_set(Core3dSystems::MainPass), + ); + ``` +- **Migration**: The `RenderGraph` API has been removed. Render passes are now systems that run in the `Core3d`/`Core2d` schedules; `ViewNode` is replaced by a regular system using the `ViewQuery` parameter and `RenderContext` is now a system parameter. Order passes with `.before()`/`.after()` on the actual system functions. Coarse ordering sets: `Core3dSystems::Prepass`, `MainPass`, `PostProcess` (and `EarlyPostProcess` in 2D/3D). +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#render-graph-as-systems + +### 0.19 — `bevy_scene` renamed to `bevy_world_serialization` +- **Old**: + ```rust + commands.spawn(SceneRoot(asset_server.load("scene.gltf#Scene0"))); + ``` +- **New**: + ```rust + commands.spawn(WorldAssetRoot(asset_server.load("scene.gltf#Scene0"))); + ``` +- **Migration**: The old scene system is renamed: `bevy_scene::*` → `bevy_world_serialization::*` (and `bevy::scene::*` → `bevy::world_serialization::*`). Key renames: `Scene` → `WorldAsset`, `SceneRoot` → `WorldAssetRoot`, `DynamicScene` → `DynamicWorld`, `SceneSpawner` → `WorldInstanceSpawner`, `SceneLoader` → `WorldAssetLoader`, `ScenePlugin` → `WorldSerializationPlugin`. The new next-gen scene system (BSN) lives in `bevy_scene`; GLTF scene spawning is the most likely source of breakage. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#the-old-bevy-scene-is-now-bevy-world-serialization + +### 0.19 — Text moved from `cosmic-text` to `parley`; `TextFont` fields changed +- **Old**: + ```rust + TextFont { + font: asset_server.load("FiraMono-medium.ttf"), + font_size: 35., + ..default() + } + ``` +- **New**: + ```rust + TextFont { + font: asset_server.load("FiraMono-medium.ttf").into(), + font_size: FontSize::Px(35.), + ..default() + } + ``` +- **Migration**: `bevy_text` now uses `parley` for layout. `TextFont::font` changed from `Handle` to `FontSource` (variants `Handle` and `Family`; `From>` is implemented so `.into()` suffices) and `font_size` from `f32` to `FontSize::Px(...)`. `TextRoot`/`TextSpanAccess`/`TextSpanComponent` are consolidated into `TextSection`. `Font::try_from_bytes` is now `Font::from_bytes` (no longer returns `Result`). System font discovery requires the `bevy/system_font_discovery` feature. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#bevy-text-migration-from-cosmic-text-to-parley + +### 0.19 — Cargo feature collection changes: `audio` and `ui` no longer implied +- **Old** (0.18): + ```toml + bevy = { version = "0.18", default-features = false, features = ["3d"] } + ``` +- **New** (0.19): + ```toml + bevy = { version = "0.19", default-features = false, features = ["3d", "audio"] } + ``` +- **Migration**: In 0.19 `audio` is no longer implied by the `3d`/`2d`/`ui` features (it is in `default` features instead), and `ui` is no longer implied by `3d`/`2d`. If you disable default features, opt into `audio` and/or `ui` explicitly when you need them. If you used all default features, nothing changes. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#audio-feature-is-now-no-longer-implied-by-the-3d-2d-or-ui-features and https://bevy.org/learn/migration-guides/0-18-to-0-19/#ui-feature-is-now-no-longer-implied-by-the-3d-or-2d-features + +### 0.18 — `RenderTarget` is now a component +- **Old**: + ```rust + commands.spawn(( + Camera3d::default(), + Camera { + target: RenderTarget::Image(image_handle.into()), + ..default() + }, + )); + ``` +- **New**: + ```rust + commands.spawn(( + Camera3d::default(), + RenderTarget::Image(image_handle.into()), + )); + ``` +- **Migration**: `RenderTarget` has been moved from a field on `Camera` to a separate required component. Spawn it as a component instead of setting `camera.target`. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#rendertarget-is-now-a-component + +### 0.18 — Entities rework (flush removed, new allocator/index types) +- **Old**: `Entities::flush`, `reserve_entity`, `total_count`, `EntityDoesNotExistError`, `Entity::row` / `Entity::from_raw`... +- **New**: `EntitiesAllocator` (via `World::entities_allocator`), `Entities::len`/`count_spawned`, `EntityNotSpawnedError`, `Entity::index` / `Entity::from_index`. +- **Migration**: Reservation and flushing were removed: use `EntitiesAllocator::alloc` + `World::spawn_at` instead of reserve+flush. Error types were reworked (`EntityDoesNotExistError` → `InvalidEntityError`/`EntityNotSpawnedError`), `EntityRow` terminology became `EntityIndex`, and several `Entities` methods (`alloc`, `free`, `get`, `contains`) changed shape. This is a large migration — see the full guide section and the new `entity` module docs. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#entities-apis + +### 0.18 — Cargo feature cleanup and feature collections +- **Old**: `bevy = { version = "0.17", features = ["animation", "bevy_mesh_picking_backend"] }` +- **New**: features renamed (`animation` → `gltf_animation`, `bevy_mesh_picking_backend` → `mesh_picking`, `bevy_ui_picking_backend` → `ui_picking`, `bevy_sprite_picking_backend` → `sprite_picking`) and high-level feature collections (`2d`, `3d`, `ui`, plus `*_api` / `default_app` / `default_platform`) introduced. +- **Migration**: Rename the four features above, and prefer high-level feature collections over hand-picking individual cargo features. `bevy_input` input sources (mouse/keyboard/gamepad/touch/gestures) are now gated behind features — enable the ones you use when `default-features = false`. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#feature-cleanup and https://bevy.org/learn/migration-guides/0-17-to-0-18/#cargo-feature-collections + +### 0.17 — `Event` trait split into `Message` and `Event` +- **Old**: + ```rust + #[derive(Event)] + struct MyEvent; + + fn system(mut events: EventReader) { /* ... */ } + ``` +- **New**: + ```rust + #[derive(Message)] + struct MyMessage; + + fn system(mut messages: MessageReader) { /* ... */ } + ``` +- **Migration**: "Buffered events" are now "messages": derive `Message` instead of `Event` for anything sent/read with writers/readers, and use `MessageWriter`/`MessageReader`/`Messages` (renamed from `EventWriter`/`EventReader`/`Events`). The `Event` trait is now exclusively for observer events. A type can derive both `Message` and `Event` if used in both contexts, but most types use one. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#event-trait-split-rename + +### 0.17 — `bevy_render` reorganization into new crates +- **Old**: `use bevy::render::mesh::Mesh;` / `use bevy::core_pipeline::core_3d::Camera3d;` (0.16 paths) +- **New**: `use bevy::mesh::Mesh;` / `use bevy::camera::Camera3d;` +- **Migration**: Many rendering types moved to new crates: camera types → `bevy_camera` (`bevy::camera`), shader types → `bevy_shader` (`bevy::shader`), light types → `bevy_light` (`bevy::light`), mesh types → `bevy_mesh` (`bevy::mesh`), image types → `bevy_image` (`bevy::image`); post-process effects → `bevy_post_process` (`bevy::post_process`), AA → `bevy_anti_alias` (`bevy::anti_alias`); sprite/UI render types → `bevy_sprite_render` / `bevy_ui_render`. In 0.18 the remaining `bevy_render` re-exports for mesh/image were removed — import from the new crates. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#bevy-render-reorganization and https://bevy.org/learn/migration-guides/0-17-to-0-18/#bevy-render-reorganization + +### 0.17 — System sets standardized on `*Systems` naming +- **Old**: `RenderSet`, `TransformSystem`, `UiSystem`, `InputSystem`, `PickSet` +- **New**: `RenderSystems`, `TransformSystems`, `UiSystems`, `InputSystems`, `PickingSystems` +- **Migration**: System sets now consistently use a `Systems` suffix (e.g. `AccessibilitySystem` → `AccessibilitySystems`, `Animation` → `AnimationSystems`, `TimeSystem` → `TimeSystems`). Rename all references; ecosystem crates are encouraged to adopt the convention. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#consistent-systems-naming-convention-for-system-sets + +### 0.17 — Reflection auto-registration +- **Old**: `app.register_type::();` required for every reflected type. +- **New**: types implementing `Reflect` are automatically registered when the `reflect_auto_register` feature (a Bevy default) is enabled; `register_type` calls can be removed for non-generic types. +- **Migration**: Enable `reflect_auto_register` in application code (it is part of Bevy's default features; libraries should not enable it). Generic types must still be registered manually. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#changes-to-type-registration-for-reflection + +## Medium Risk (compile-breaking, narrow) + +### 0.19 — `System::type_id` renamed to `System::system_type` +- **Old**: `let id = my_system.type_id();` +- **New**: `let id = my_system.system_type();` +- **Migration**: Renamed to avoid shadowing `Any::type_id`. The old method is deprecated and will be removed in a future release; custom `System` impls should override `system_type`. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#rename-system-type-id-to-system-system-type + +### 0.19 — `ExecutorKind` removed; `Schedule::set_executor` +- **Old**: + ```rust + schedule.set_executor_kind(ExecutorKind::SingleThreaded); + ``` +- **New**: + ```rust + schedule.set_executor(SingleThreadedExecutor::new()); + ``` +- **Migration**: `ExecutorKind` is gone; pass an executor instance (`SingleThreadedExecutor::new()`, `MultiThreadedExecutor::new()`, or `default_executor()`). `SystemExecutor` is now a public trait that can be implemented for fully custom executors. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#set-executor-replaced-executorkind + +### 0.19 — Non-send resources renamed to non-send data +- **Old**: `world.insert_non_send_resource(my_data);` +- **New**: `world.insert_non_send(my_data);` +- **Migration**: `App::init_non_send_resource`/`insert_non_send_resource`, `World::*_non_send_resource*`, `UnsafeWorldCell::get_non_send_resource*`, and `DeferredWorld::non_send_resource_mut` are deprecated in favor of the `*_non_send*` names. `Resources`/`ResourceData` were removed; `NonSends`/`NonSendData` replace them. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data + +### 0.19 — `Skybox` image is now optional +- **Old**: + ```rust + Skybox { image: my_skybox, brightness: 1000.0, ..default() } + ``` +- **New**: + ```rust + Skybox { image: Some(my_skybox), brightness: 1000.0, ..default() } + ``` +- **Migration**: `Skybox.image` is now `Option>`; a skybox without an image draws nothing. Wrap the handle in `Some(...)` (or drop the placeholder image entirely). +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#skybox-image-is-now-optional + +### 0.19 — `Image::pixel_bytes` family returns `Result` +- **Old**: + ```rust + if let Some(bytes) = image.pixel_bytes(coords) { /* use bytes */ } + ``` +- **New**: + ```rust + match image.pixel_bytes(coords) { + Ok(bytes) => { /* use bytes */ } + Err(TextureAccessError::OutOfBounds { .. }) => { /* ... */ } + Err(TextureAccessError::UnsupportedTextureFormat(format)) => { /* ... */ } + Err(TextureAccessError::Uninitialized) => { /* ... */ } + } + ``` +- **Migration**: `Image::pixel_bytes`, `pixel_bytes_mut`, and `pixel_data_offset` now return `Result<..., TextureAccessError>` instead of `Option`; distinguish out-of-bounds, unsupported (compressed) formats, and uninitialized data. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#image-pixel-bytes-and-image-pixel-data-offset-now-return-result + +### 0.18 — `Internal` component removed +- **Old**: observers and one-shot systems were tagged `Internal` and hidden by default query filters. +- **New**: no `Internal` component; observer/one-shot entities are no longer hidden by default query filters. +- **Migration**: Remove all references to `Internal`. Tests relying on exact entity counts should query for a component they care about instead. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#internal-has-been-removed + +### 0.18 — Same-state transitions now trigger `OnEnter`/`OnExit` +- **Old**: `next_state.set(State::Menu);` (no transition when already `Menu`) +- **New**: `next_state.set_if_neq(State::Menu);` to preserve the old behavior +- **Migration**: `NextState::set` now always runs state transition schedules (including `DespawnOnEnter`/`DespawnOnExit`) even when the target state equals the current one. Use `set_if_neq` if you do not want same-state transitions. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#same-state-transitions + +### 0.18 — `AmbientLight` split into component + resource +- **Old**: + ```rust + app.insert_resource(AmbientLight { color: Color::WHITE, brightness: 2000., ..default() }); + ``` +- **New**: + ```rust + app.insert_resource(GlobalAmbientLight { color: Color::WHITE, brightness: 2000., ..default() }); + ``` +- **Migration**: The resource form is now `GlobalAmbientLight` (added by `LightPlugin`); `AmbientLight` is a component that can be added to a `Camera` to override it. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#ambientlight-split-into-a-component-and-a-resource + +### 0.17 — `Handle::Weak` replaced by `Handle::Uuid` +- **Old**: + ```rust + const IMAGE: Handle = weak_handle!("b20988e9-b1b9-4176-b5f3-a6fa73aa617f"); + commands.spawn(Sprite::from_image(my_sprite_image.clone_weak())); + ``` +- **New**: + ```rust + const IMAGE: Handle = uuid_handle!("b20988e9-b1b9-4176-b5f3-a6fa73aa617f"); + commands.spawn(Sprite::from_image(my_sprite_image.clone())); + ``` +- **Migration**: `Handle::Weak` is now `Handle::Uuid`; `weak_handle!` → `uuid_handle!` and `Handle::clone_weak` → `Handle::clone`. Users of the `Handle::Weak` variant directly should consider `AssetId` (via `Handle::id`). For shaders, prefer `load_shader_library`/`load_embedded_asset` (enables hot reloading). +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#handle-weak-has-been-replaced-by-handle-uuid + +### 0.17 — `Timer::paused`/`Timer::finished` renamed +- **Old**: `timer.paused()`, `timer.finished()` +- **New**: `timer.is_paused()`, `timer.is_finished()` +- **Migration**: Renamed to align with `Time` and `Stopwatch`. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-timer-paused-to-timer-is-paused-and-timer-finished-to-timer-is-finished + +### 0.17 — `Anchor` variants are now associated constants +- **Old**: `Anchor::Center`, `Anchor::BottomLeft`, `Anchor::Custom(value)` +- **New**: `Anchor::CENTER`, `Anchor::BOTTOM_LEFT`, `Anchor(value)` +- **Migration**: The `anchor` field was removed from `Sprite`; `Anchor` is now a required component. Variants became SCREAMING_SNAKE associated constants; `Anchor::Custom(v)` is now the tuple constructor `Anchor(v)`. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#anchor-is-now-a-required-component-on-sprite + +## Low Risk (deprecations, behavioral) + +### 0.19 — Bloom luma calculation now in linear space +- **Old**: bloom Karis-average downsampling computed luma in non-linear sRGB space (subtly brighter, especially for saturated colors). +- **New**: luma is computed in linear space; bloom may appear dimmer. +- **Migration**: If bloom is now too dim, increase `Bloom::intensity`, increase material `emissive`, or adjust the `prefilter` settings. Visual change only — no code API break. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#bloom-luma-calculation-now-in-linear-space + +### 0.19 — `Assets::get_mut` returns `AssetMut` (change lists) +- **Old**: `assets.get_mut(handle)` returned `&mut A` and always triggered an `AssetEvent::Modified`. +- **New**: `Assets::get_mut` returns `AssetMut`; a `Modified` event fires only when the asset is actually mutated (like `Mut`/`ResMut`). +- **Migration**: Mark the returned value `mut` and guard writes (e.g. compare against the new value first) to avoid unnecessary re-extraction cost. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#avoiding-unnecessary-assetevent-modified-events-that-lead-to-rendering-performance-costs + +### 0.19 — `Command` error handling simplified (`Out` associated type) +- **Old**: + ```rust + fn my_command() -> impl Command { move |world: &mut World| -> Result { /* ... */ } } + ``` +- **New**: + ```rust + fn my_command() -> impl Command { move |world: &mut World| -> Result { /* ... */ } } + ``` +- **Migration**: `Command` now takes `Out` as an associated type instead of a generic parameter; implementors must fill in `type Out = ();` (or `Result`). `HandleError` and `CommandWithEntity` functionality folded into `Command`/`EntityCommand`. +- **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#command-error-handling-has-been-simplified + +### 0.18 — `DragEnter` now fires on drag starts +- **Old**: `DragEnter` fired only when entering an entity other than the dragged one. +- **New**: `DragEnter` also fires when a drag starts over an already-hovered entity. +- **Migration**: Behavioral change; filter by checking whether the trigger entity is the dragged entity if the old behavior is needed. +- **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#dragenter-now-fires-on-drag-starts + +### 0.17 — `scale_value` removed from `bevy_text` text2d +- **Old**: `scale_value(value, scale_factor)` from `bevy::text::text2d` +- **New**: multiply by the scale factor directly. +- **Migration**: Remove the call and multiply by the scale factor instead. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#remove-scale-value + +### 0.17 — `RelativeCursorPosition` is now object-centered +- **Old**: coordinates relative to the node origin; `normalized_visible_node_rect` field existed. +- **New**: (0, 0) at the center of the node, corners at (±0.5, ±0.5); `normalized_visible_node_rect` replaced by a `cursor_over: bool` field. +- **Migration**: Update picking logic that consumed `RelativeCursorPosition` coordinates. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#relativecursorposition-is-now-object-centered + +--- + +### Band coverage notes + +- **High Risk 0.16→0.17**: covered above (Event/Message split, `bevy_render` reorganization, `*Systems` naming, reflection auto-registration, `Handle::Weak`→`Handle::Uuid`). Additional widespread 0.17 changes: `System::run` now returns `Result` (https://bevy.org/learn/migration-guides/0-16-to-0-17/#system-run-returns-result) and the `wgpu` 25 bind-group renumbering for custom shaders (https://bevy.org/learn/migration-guides/0-16-to-0-17/#wgpu-25). +- **High Risk 0.17→0.18**: covered above; see also the `Entities`/`EntityRow` rework entry under 0.18 for the largest compile-breaking surface. +- **No notable changes in the Low Risk band for 0.16→0.17 beyond the entries above.** All three guides contain additional narrow/niche renames not reproduced here; consult the guide for the exact subsystem before migrating code that touches ECS internals, render phases, or reflection. diff --git a/docs/engine-reference/bevy/current-best-practices.md b/docs/engine-reference/bevy/current-best-practices.md new file mode 100644 index 0000000..b8b68fc --- /dev/null +++ b/docs/engine-reference/bevy/current-best-practices.md @@ -0,0 +1,269 @@ +# Bevy Current Best Practices (0.17–0.19) + +**Last verified:** 2026-08-09 + +Practices below are 0.17–0.19 idioms that differ from pre-0.17 training data, +each verified against the official Migration Guides. Rule: anything not +verifiable against a cited source is omitted. + +## ECS + +- **Practice**: Buffered events are now *messages*. Derive `Message` (not `Event`) for anything you send/read with writers/readers, and use `MessageWriter`/`MessageReader`/`Messages`. Reserve `Event` for observer events. + ```rust + #[derive(Message)] + struct PlayerDied { player: Entity } + + fn send_death(mut messages: MessageWriter, ...) { /* ... */ } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#event-trait-split-rename + +- **Practice**: Observers take `On` (renamed from `Trigger`); entity-targeted events derive `EntityEvent` and are fired with `world.trigger(...)` (not `trigger_targets`). + ```rust + #[derive(EntityEvent)] + #[entity_event(propagate)] // defaults to ChildOf propagation + struct Explode { entity: Entity } + + commands.add_observer(|explode: On| { + info!("{} exploded!", explode.entity); + }); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#observer-event-api-changes + +- **Practice**: In 0.19 resources are components stored on dedicated entities. Do NOT derive both `Component` and `Resource` on one type — split into distinct types. When using broad queries (`Query`, `Query`...), exclude resource entities with `Without` to avoid conflicts with `Res`/`NonSend` params. + ```rust + #[derive(Component)] + struct MyDataComp(f32); + + #[derive(Resource)] + struct MyDataRes(f32); + + fn system(entity_query: Query>, res: Res) { /* ... */ } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#resources-as-components + +- **Practice**: Use `NextState::set_if_neq` instead of `set` when you do not want same-state transitions; `set` now always runs `OnEnter`/`OnExit` (and `DespawnOnEnter`/`DespawnOnExit`) even if the state is unchanged. + ```rust + next_state.set_if_neq(State::Menu); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#same-state-transitions + +- **Practice**: Name system sets with the `*Systems` suffix and schedule with executors passed as instances (0.19 removed `ExecutorKind`). + ```rust + #[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] + enum MySystems { Movement, Physics } + + schedule.set_executor(MultiThreadedExecutor::new()); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#consistent-systems-naming-convention-for-system-sets and https://bevy.org/learn/migration-guides/0-18-to-0-19/#set-executor-replaced-executorkind + +- **Practice**: Reflection auto-registration: with `reflect_auto_register` (a Bevy default feature) enabled, non-generic `Reflect` types register automatically — drop explicit `register_type` calls in app code. Generic types still need manual registration. + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#changes-to-type-registration-for-reflection + +## Rendering + +- **Practice**: Custom render passes are now systems (the `RenderGraph` API was removed in 0.19). Use a `ViewQuery` param + `RenderContext` system param, and order with `.before()`/`.after()` on actual pass systems, scoped by `Core3dSystems::Prepass` / `MainPass` / `EarlyPostProcess` / `PostProcess`. + ```rust + pub fn my_render_pass( + world: &World, + view: ViewQuery<(&ExtractedCamera, &ViewTarget)>, + mut ctx: RenderContext, + ) { + let (camera, target) = view.into_inner(); + // ... + } + + render_app.add_systems( + Core3d, + my_render_pass + .after(main_opaque_pass_3d) + .in_set(Core3dSystems::MainPass), + ); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#render-graph-as-systems + +- **Practice**: Import render types from the crates they were split into (0.17+): cameras from `bevy::camera`, shaders from `bevy::shader`, lights/skybox from `bevy::light`, meshes from `bevy::mesh`, images from `bevy::image`, post-process from `bevy::post_process`, AA from `bevy::anti_alias`. Do not use `bevy::render::` paths for these (re-exports were removed). + ```rust + use bevy::camera::Camera3d; + use bevy::mesh::Mesh; + use bevy::post_process::Bloom; + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#bevy-render-reorganization + +- **Practice**: `RenderTarget` is a required component, not a `Camera` field (0.18). + ```rust + commands.spawn(( + Camera3d::default(), + RenderTarget::Image(image_handle.into()), + )); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#rendertarget-is-now-a-component + +- **Practice**: Many render pipeline resources are initialized in the `RenderStartup` schedule (0.17+), not in `Plugin::finish`. Initialize render resources from a system added to `RenderStartup` instead of `FromWorld`, and order after the pipeline init sets when needed. + ```rust + fn init_my_resource( + mut commands: Commands, + render_device: Res, + asset_server: Res, + ) { + commands.insert_resource(MyRenderResource { /* ... */ }); + } + + render_app + .add_systems(RenderStartup, init_my_resource) + .add_systems(Render, my_render_system); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#many-render-resources-now-initialized-in-renderstartup + +- **Practice**: Material config moved onto the `Material` trait (0.18): implement `enable_prepass()`/`enable_shadows()` instead of configuring `MaterialPlugin` fields. + ```rust + impl Material for MyMaterial { + fn enable_prepass() -> bool { false } + fn enable_shadows() -> bool { false } + } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#enable-prepass-and-enable-shadows-are-now-material-methods + +- **Practice**: Bloom luma is computed in linear space since 0.19 — expect a subtly dimmer effect; tune `Bloom::intensity` / `prefilter` rather than assuming the old sRGB look. + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#bloom-luma-calculation-now-in-linear-space + +## UI + +- **Practice**: `Window` is split into multiple components (0.17): configure cursor settings via the `CursorOptions` component / `WindowPlugin::primary_cursor_options`, not `Window.cursor_options`. + ```rust + app.add_plugins(DefaultPlugins.set(WindowPlugin { + primary_cursor_options: Some(CursorOptions { + grab_mode: CursorGrabMode::Locked, + ..default() + }), + ..default() + })); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#window-is-now-split-into-multiple-components + +- **Practice**: `UiWidgetsPlugins` and `InputDispatchPlugin` are already part of `DefaultPlugins` since 0.19 — do not add them manually (adding them alongside `DefaultPlugins` would double-register). + ```rust + App::new() + .add_plugins(DefaultPlugins) + // .add_plugins(UiWidgetsPlugins) // removed: already included + .run(); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#uiwidgetsplugins-and-inputdispatchplugin-are-now-in-defaultplugins + +- **Practice**: `BorderRadius` is a field on `Node`, not a separate component (0.18). + ```rust + commands.spawn(Node { + border_radius: BorderRadius::all(Val::Px(4.)), + ..default() + }); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#borderradius-has-been-added-to-node-and-is-no-longer-a-component + +- **Practice**: `TextFont` in 0.19 takes a `FontSource` and a `FontSize`, and `LineHeight` is a separate required component (since 0.18). + ```rust + TextFont { + font: asset_server.load("FiraMono-medium.ttf").into(), + font_size: FontSize::Px(35.), + ..default() + } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#changes-to-textfont-s-font-size-and-font-fields and https://bevy.org/learn/migration-guides/0-17-to-0-18/#lineheight-is-now-a-separate-component + +- **Practice**: UI debug options live in `bevy_ui_render` (0.17): `bevy::ui_render::UiDebugOptions` (still re-exported via `bevy::prelude`). + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#move-ui-debug-options-from-bevy-ui-to-bevy-ui-render + +## Assets + +- **Practice**: `AssetPath::resolve`/`resolve_embed` take `&AssetPath` (0.19); use the `*_str` variants for string paths. + ```rust + let resolved = base_asset_path.resolve(&relative_asset_path); + let resolved_str = base_asset_path.resolve_str("models/foo.gltf#Scene0"); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#assetpath-resolve-and-resolve-embed-now-take-assetpath + +- **Practice**: Prefer `AssetServer::load_builder()` for anything beyond a plain typed load (untyped loads, settings, guards) — all the old `load_*` variants have deprecation messages pointing at it (0.19). + ```rust + asset_server + .load_builder() + .with_settings(settings) + .override_unapproved() + .load(path) + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#advanced-assetserver-load-variants-are-now-exposed-through-a-builder-pattern + +- **Practice**: `Assets::insert` / `get_or_insert_with` return `Result` since 0.17 — handle (or `unwrap()`) the error instead of panicking. + ```rust + assets.insert(handle, my_asset).unwrap(); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#assets-insert-and-assets-get-or-insert-with-now-return-result + +- **Practice**: Custom asset loaders/transformers/savers/processors must derive `TypePath` (0.18). + ```rust + #[derive(TypePath)] + struct MyFunkyLoader { add_funk: u32 } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#traits-assetloader-assettransformer-assetsaver-and-process-all-now-require-typepath + +- **Practice**: Custom asset sources are built with a required reader (0.18) and hand out `async_channel::Sender` watchers. + ```rust + AssetSourceBuilder::new(move || /* reader logic */) + .with_writer(move || /* ... */) + .with_processed_reader(move || /* ... */) + .with_processed_writer(move || /* ... */); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#custom-asset-sources-now-require-a-reader and https://bevy.org/learn/migration-guides/0-17-to-0-18/#assetsources-now-give-an-async-channel-sender-instead-of-a-crossbeam-channel-sender + +## Input + +- **Practice**: Use `Pointer` / `Pointer` (0.17 renamed from `Pressed`/`Released`); `Pressed` is now a marker component meaning "held down". + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#rename-pointer-pressed-and-pointer-released-to-pointer-press-and-pointer-release + +- **Practice**: With `default-features = false` on `bevy`/`bevy_input`, explicitly enable the input sources you use (0.18) — mouse, keyboard, gamepad, touch, gestures. + ```toml + bevy = { version = "0.19", default-features = false, features = [ + "mouse", "keyboard", "gamepad", "touch", "gestures", + ] } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-17-to-0-18/#put-input-sources-for-bevy-input-under-features + +- **Practice**: `RelativeCursorPosition` coordinates are object-centered since 0.17: (0,0) at the node center, corners at (±0.5, ±0.5), with a `cursor_over: bool` field. + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#relativecursorposition-is-now-object-centered + +## Audio + +- **Practice**: Use `increase_by_percentage` instead of `+`/`-` on `Volume::Linear` (Add/Sub impls removed in 0.17). + ```rust + let linear = Volume::Linear(0.5); + let louder = linear.increase_by_percentage(10.0); + let quieter = linear.increase_by_percentage(-10.0); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#remove-the-add-sub-impls-on-volume + +- **Practice**: With `default-features = false`, enable audio format features explicitly (0.19): `vorbis` (default when using Bevy defaults), `wav`, `mp3`, `flac`, `mp4`, `aac`, or the `audio-all-formats` collection. `audio` is no longer implied by `3d`/`2d`/`ui`. + ```toml + bevy = { version = "0.19", default-features = false, features = ["3d", "audio", "vorbis", "wav"] } + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#rodio-0-22-update and https://bevy.org/learn/migration-guides/0-18-to-0-19/#audio-feature-is-now-no-longer-implied-by-the-3d-2d-or-ui-features + +- **Practice**: Use the `mp3` feature (symphonia backend), not `minimp3` — the `minimp3` feature is no longer exposed (0.17); it is unmaintained, broken on wasm, and has known security vulnerabilities. + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#stop-exposing-mp3-support-through-minimp3 + +## Testing + +- **Practice**: `System::run` and friends return `Result` since 0.17 — `unwrap()` or use `?`; parameter validation happens automatically. + ```rust + world.run_system_once(my_system).unwrap(); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#system-run-returns-result + +- **Practice**: `SystemState::get`/`get_mut`/`fetch` return `Result<..., SystemParamValidationError>` since 0.19 — add `.unwrap()` where results were destructured directly. + ```rust + let (res, query) = system_state.get(&world).unwrap(); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-18-to-0-19/#systemparam-validation-is-now-done-when-fetching-the-data + +- **Practice**: Constructing entities manually in tests: `Entity::from_raw_u32` (returns `Option`, 0.17) and `EntityGeneration::FIRST.after_versions(...)` replaced the old `from_raw`/`NonZeroU32` APIs. + ```rust + let entity = Entity::from_raw_u32(1).unwrap(); + assert_eq!(entity.generation(), EntityGeneration::FIRST.after_versions(0)); + ``` + **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#manual-entity-creation-and-representation diff --git a/docs/engine-reference/bevy/deprecated-apis.md b/docs/engine-reference/bevy/deprecated-apis.md new file mode 100644 index 0000000..69a44b6 --- /dev/null +++ b/docs/engine-reference/bevy/deprecated-apis.md @@ -0,0 +1,62 @@ +# Bevy Deprecated APIs + +**Last verified:** 2026-08-09 + +If an agent suggests any API in the "Don't use" column, it MUST be replaced +with the "Use instead" column. Rows are taken from the official Migration +Guides (https://bevy.org/learn/migration-guides/); the "Deprecated in" column +is the version in which the old name was deprecated/renamed. For a version's +full change list see the corresponding guide URL in the Source column. + +## Lookup Table + +| Don't use | Use instead | Deprecated in | Source | +|-----------|-------------|---------------|--------| +| `App::init_non_send_resource` | `App::init_non_send` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `App::insert_non_send_resource` | `App::insert_non_send` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `World::init_non_send_resource` / `World::insert_non_send_resource` / `World::remove_non_send_resource` | `World::init_non_send` / `insert_non_send` / `remove_non_send` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `World::non_send_resource` / `World::non_send_resource_mut` / `World::get_non_send_resource(_mut)` | `World::non_send` / `non_send_mut` / `get_non_send(_mut)` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `UnsafeWorldCell::get_non_send_resource(_mut)(_by_id)` | `UnsafeWorldCell::get_non_send(_mut)(_by_id)` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `DeferredWorld::non_send_resource_mut` / `get_non_send_resource_mut` | `DeferredWorld::non_send_mut` / `get_non_send_mut` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#renaming-non-send-resources-to-non-send-data | +| `Components::get_valid_resource_id` / `valid_resource_id` / `resource_id` | `Components::get_valid_id` / `valid_component_id` / `component_id` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#component-registration | +| `ComponentsRegistrator::register_resource` | `ComponentsRegistrator::register_component` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#component-registration | +| `ComponentsQueuedRegistrator::queue_register_resource` | `ComponentsQueuedRegistrator::queue_register_component` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#component-registration | +| `ComponentDescriptor::new_resource` | `ComponentDescriptor::new` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#component-registration | +| `Access::add_component_read` / `add_resource_read` / `add_component_write` / `add_resource_write` | `Access::add_read` / `add_write` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `Access::has_component_read` / `has_resource_read` / `has_component_write` / `has_resource_write` (and `has_any_*`) | `Access::has_read` / `has_write` / `has_any_read` / `has_any_write` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `Access::read_all_components` / `write_all_components` | `Access::read_all` / `write_all` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `Access::is_components_compatible` / `is_subset_components` | `Access::is_compatible` / `is_subset` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `FilteredAccess::add_component_read` / `add_component_write` | `FilteredAccess::add_read` / `add_write` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `FilteredAccess::read_all_components` / `write_all_components` | `FilteredAccess::read_all` / `write_all` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#access | +| `System::type_id` | `System::system_type` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#rename-system-type-id-to-system-system-type | +| `DefaultErrorHandler` / `default_error_handler` | `FallbackErrorHandler` / `fallback_error_handler` (deprecated alias kept for one release) | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#defaulterrorhandler-renamed-to-fallbackerrorhandler | +| `TextureFormat::bevy_default()` / `ViewTargets::TEXTURE_FORMAT_HDR` | source the format from `ExtractedView::target_format` | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#camera-textureformat-rework | +| `AssetServer::load_with_settings` / `load_with_settings_override` / other advanced load variants | `AssetServer::load_builder().with_settings(...)` (all variants reimplementable via `load_builder`) | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#advanced-assetserver-load-variants-are-now-exposed-through-a-builder-pattern | +| `LoadContext::loader()` (`NestedLoader`) | `LoadContext::load_builder()` (`NestedLoadBuilder`) | 0.19 | https://bevy.org/learn/migration-guides/0-18-to-0-19/#nestedloader | +| `EntityCommands::clear_children` / `remove_children` / `remove_child` / `clear_related` | `detach_all_children` / `detach_children` / `detach_child` / `detach_all_related` | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#renamed-clear-children-and-clear-related-methods-to-detach | +| `EntityWorldMut::clear_children` / `remove_children` / `remove_child` / `clear_related` | `EntityWorldMut::detach_all_children` / `detach_children` / `detach_child` / `detach_all_related` | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#renamed-clear-children-and-clear-related-methods-to-detach | +| `ThinSlicePtr::get()` | `ThinSlicePtr::get_unchecked()` | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#rename-thinsliceptr-get-to-thinsliceptr-get-unchecked | +| `MaterialPlugin { prepass_enabled, shadows_enabled }` fields | `Material::enable_prepass()` / `Material::enable_shadows()` methods | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#enable-prepass-and-enable-shadows-are-now-material-methods | +| `NextState::set` for same-state transitions | `NextState::set_if_neq` (if same-state transitions are undesired) | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#same-state-transitions | +| `Gizmos::cuboid` | `Gizmos::cube` | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#gizmos-cuboid-has-been-renamed-to-gizmos-cube | +| `AssetSourceBuilder::build()` | `AssetSourceBuilder::new(reader_fn)` (a reader is now required) | 0.18 | https://bevy.org/learn/migration-guides/0-17-to-0-18/#custom-asset-sources-now-require-a-reader | +| `World::send_event` / `send_event_default` / `send_event_batch` | `World::write_message` / `write_message_default` / `write_message_batch` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rename-send-event-and-similar-methods-to-write-message | +| `Commands::send_event` | `Commands::write_message` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rename-send-event-and-similar-methods-to-write-message | +| `Events` / `EventWriter` / `EventReader` for buffered events | `Messages` / `MessageWriter` / `MessageReader` (derive `Message`) | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#event-trait-split-rename | +| `Events::send` / `send_default` / `send_batch` | `Messages::write` / `write_default` / `write_batch` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rename-send-event-and-similar-methods-to-write-message | +| `RemovedComponents::events` / `reader_mut_with_events` / `RemovedComponentEvents` | `RemovedComponents::messages` / `reader_mut_with_messages` / `RemovedComponentMessages` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#removedcomponents-methods-renamed-to-match-event-to-message-rename | +| `Condition` (trait) | `SystemCondition` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-condition-to-systemcondition | +| `StateScoped` / `add_state_scoped_event` | `DespawnOnExit` / `add_event` + `clear_events_on_exit` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-state-scoped-entities-and-events | +| `app.enable_state_scoped_entities::()` | nothing (state-scoped entities always enabled; call is a no-op) | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#state-scoped-entities-are-now-always-enabled-implicitly | +| `JustifyText` | `Justify` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-justifytext-to-justify | +| `Handle::Weak` / `weak_handle!` / `Handle::clone_weak` | `Handle::Uuid` / `uuid_handle!` / `Handle::clone` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#handle-weak-has-been-replaced-by-handle-uuid | +| `Timer::paused()` / `Timer::finished()` | `Timer::is_paused()` / `Timer::is_finished()` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-timer-paused-to-timer-is-paused-and-timer-finished-to-timer-is-finished | +| `World::iter_entities()` / `World::iter_entities_mut()` | `world.query::().iter(&world)` / `world.query::().iter(&mut world)` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#deprecate-iter-entities-and-iter-entities-mut | +| `MergeMeshError` (0.16 name `MergeMeshError` struct) | `MeshMergeError` (enum, with `IncompatiblePrimitiveTopology` variant) | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rework-mergemesherror | +| `ScaleVolume` Add/Sub arithmetic on `Volume::Linear` | `Volume::Linear(x).increase_by_percentage(...)` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#remove-the-add-sub-impls-on-volume | +| `SceneSpawner::despawn`/`despawn_sync`/`update_spawned_scenes` (0.16, dynamic-scene variants) | `despawn_dynamic` / `despawn_dynamic_sync` / `update_spawned_dynamic_scenes`; the un-suffixed names now act on `Scene` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#scenespawner-methods-have-been-renamed-and-replaced | + +Notes: + +- The 0.16→0.17 guide also documents deprecations that were removed outright in 0.18: `SimpleExecutor` (deprecated in 0.17, removed in 0.18 — use `SingleThreadedExecutor` or `MultiThreadedExecutor`) — https://bevy.org/learn/migration-guides/0-16-to-0-17/#deprecated-simple-executor and https://bevy.org/learn/migration-guides/0-17-to-0-18/#removed-simpleexecutor. +- The guides for 0.16→0.17, 0.17→0.18, and 0.18→0.19 all document deprecations, so no version is without a deprecation note. From 8d679430789fd00a12037181af78bebefde79010 Mon Sep 17 00:00:00 2001 From: Jaco du Preez Date: Sun, 9 Aug 2026 20:32:43 +0200 Subject: [PATCH 03/10] docs(engine-reference): fix review findings in Bevy reference docs - breaking-changes.md: drop dead 0-17-to-0-18/#bevy-render-reorganization anchor; attribute mesh/image bevy_render re-export removal to 0.17 (per 0-16-to-0-17 guide) - VERSION.md: label Key Theme rows as X-to-X+1 transitions (themes were off-by-one; 0.19 row duplicated 0.18); note 0.19 is latest with no 0.19-to-0.20 guide yet - VERSION.md: Skybox moved to bevy_light in 0.19 (from bevy_core_pipelines), not part of the 0.17 split - deprecated-apis.md: un-garble MergeMeshError 'Don't use' cell (0.16 name; was a struct) --- docs/engine-reference/bevy/VERSION.md | 10 +++++----- docs/engine-reference/bevy/breaking-changes.md | 4 ++-- docs/engine-reference/bevy/deprecated-apis.md | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/engine-reference/bevy/VERSION.md b/docs/engine-reference/bevy/VERSION.md index ec85ce0..6620fe2 100644 --- a/docs/engine-reference/bevy/VERSION.md +++ b/docs/engine-reference/bevy/VERSION.md @@ -23,10 +23,10 @@ The Migration Guides are the authoritative source for version transitions. | Version | Release | Risk Level | Key Theme | |---------|---------|------------|-----------| -| 0.16 | 2025-04-24 | HIGH | `Event` trait split into `Message` (buffered) and `Event` (observers); `bevy_render` reorganized into `bevy_camera` / `bevy_shader` / `bevy_light` / `bevy_mesh` / `bevy_image`; system sets standardized on `*Systems` naming | -| 0.17 | 2025-09-30 | HIGH | Entities rework (`EntityRow` index, flush removed, `EntitiesAllocator`); `RenderTarget` moved from a `Camera` field to a component; Cargo feature collections; `Internal` component removed | -| 0.18 | 2026-01-13 | HIGH | Resources are now stored as components on dedicated entities; `RenderGraph` replaced by systems; text moved from `cosmic-text` to `parley`; `bevy_scene` renamed to `bevy_world_serialization` (BSN arrives) | -| 0.19 | 2026-06-18 | HIGH | Resources-as-components; render graph as systems; Parley text overhaul; `audio`/`ui` Cargo features no longer implied by `3d`/`2d`; bloom luma now computed in linear space | +| 0.16 | 2025-04-24 | HIGH | **0.16 → 0.17:** `Event` trait split into `Message` (buffered) and `Event` (observers); `bevy_render` reorganized into `bevy_camera` / `bevy_shader` / `bevy_light` / `bevy_mesh` / `bevy_image`; system sets standardized on `*Systems` naming | +| 0.17 | 2025-09-30 | HIGH | **0.17 → 0.18:** Entities rework (`EntityRow` index, flush removed, `EntitiesAllocator`); `RenderTarget` moved from a `Camera` field to a component; Cargo feature collections; `Internal` component removed | +| 0.18 | 2026-01-13 | HIGH | **0.18 → 0.19:** Resources are now stored as components on dedicated entities; `RenderGraph` replaced by systems; text moved from `cosmic-text` to `parley`; `bevy_scene` renamed to `bevy_world_serialization` (BSN arrives); `audio`/`ui` Cargo features no longer implied by `3d`/`2d`; bloom luma now computed in linear space | +| 0.19 | 2026-06-18 | HIGH | — (latest release; no 0.19 → 0.20 migration guide exists yet) | ## Bevy Characteristics @@ -50,7 +50,7 @@ The Migration Guides are the authoritative source for version transitions. | bevy_audio | Audio playback (rodio backend; format support behind `vorbis`/`wav`/`mp3`/`flac` features) | | bevy_camera | Camera types (`Camera`, `Camera3d`, `Camera2d`, projections) — split out of `bevy_render` in 0.17 | | bevy_shader | Shader types (`Shader`, `ShaderRef`, `ShaderCache`) — split out in 0.17 | -| bevy_light | Light types (`PointLight`, `SpotLight`, `DirectionalLight`, `AmbientLight`, `Skybox`, `Atmosphere`) — split out in 0.17 | +| bevy_light | Light types (`PointLight`, `SpotLight`, `DirectionalLight`, `AmbientLight`, `Atmosphere`) — split out in 0.17; `Skybox` moved here from `bevy_core_pipelines` in 0.19 | | bevy_mesh | Mesh types (`Mesh`, `Mesh3d`, `Mesh2d`, `Indices`, `Meshable`) — split out in 0.17 | | bevy_image | Image types (`Image`, `ImagePlugin`, `ImageFormat`) — split out in 0.17 | | bevy_material | Material machinery extracted from `bevy_pbr`/`bevy_render` in 0.19 (`AlphaMode`, `MaterialProperties`) | diff --git a/docs/engine-reference/bevy/breaking-changes.md b/docs/engine-reference/bevy/breaking-changes.md index dc28a7f..3157bd0 100644 --- a/docs/engine-reference/bevy/breaking-changes.md +++ b/docs/engine-reference/bevy/breaking-changes.md @@ -152,8 +152,8 @@ Migration Guides (https://bevyengine.org/learn/migration-guides/). ### 0.17 — `bevy_render` reorganization into new crates - **Old**: `use bevy::render::mesh::Mesh;` / `use bevy::core_pipeline::core_3d::Camera3d;` (0.16 paths) - **New**: `use bevy::mesh::Mesh;` / `use bevy::camera::Camera3d;` -- **Migration**: Many rendering types moved to new crates: camera types → `bevy_camera` (`bevy::camera`), shader types → `bevy_shader` (`bevy::shader`), light types → `bevy_light` (`bevy::light`), mesh types → `bevy_mesh` (`bevy::mesh`), image types → `bevy_image` (`bevy::image`); post-process effects → `bevy_post_process` (`bevy::post_process`), AA → `bevy_anti_alias` (`bevy::anti_alias`); sprite/UI render types → `bevy_sprite_render` / `bevy_ui_render`. In 0.18 the remaining `bevy_render` re-exports for mesh/image were removed — import from the new crates. -- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#bevy-render-reorganization and https://bevy.org/learn/migration-guides/0-17-to-0-18/#bevy-render-reorganization +- **Migration**: Many rendering types moved to new crates: camera types → `bevy_camera` (`bevy::camera`), shader types → `bevy_shader` (`bevy::shader`), light types → `bevy_light` (`bevy::light`), mesh types → `bevy_mesh` (`bevy::mesh`), image types → `bevy_image` (`bevy::image`); post-process effects → `bevy_post_process` (`bevy::post_process`), AA → `bevy_anti_alias` (`bevy::anti_alias`); sprite/UI render types → `bevy_sprite_render` / `bevy_ui_render`. As part of this reorganization, the remaining `bevy_render` re-exports for mesh/image were removed in 0.17 — import from the new crates. +- **Source**: https://bevy.org/learn/migration-guides/0-16-to-0-17/#bevy-render-reorganization ### 0.17 — System sets standardized on `*Systems` naming - **Old**: `RenderSet`, `TransformSystem`, `UiSystem`, `InputSystem`, `PickSet` diff --git a/docs/engine-reference/bevy/deprecated-apis.md b/docs/engine-reference/bevy/deprecated-apis.md index 69a44b6..19a7f2a 100644 --- a/docs/engine-reference/bevy/deprecated-apis.md +++ b/docs/engine-reference/bevy/deprecated-apis.md @@ -52,7 +52,7 @@ full change list see the corresponding guide URL in the Source column. | `Handle::Weak` / `weak_handle!` / `Handle::clone_weak` | `Handle::Uuid` / `uuid_handle!` / `Handle::clone` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#handle-weak-has-been-replaced-by-handle-uuid | | `Timer::paused()` / `Timer::finished()` | `Timer::is_paused()` / `Timer::is_finished()` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#renamed-timer-paused-to-timer-is-paused-and-timer-finished-to-timer-is-finished | | `World::iter_entities()` / `World::iter_entities_mut()` | `world.query::().iter(&world)` / `world.query::().iter(&mut world)` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#deprecate-iter-entities-and-iter-entities-mut | -| `MergeMeshError` (0.16 name `MergeMeshError` struct) | `MeshMergeError` (enum, with `IncompatiblePrimitiveTopology` variant) | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rework-mergemesherror | +| `MergeMeshError` (0.16 name; was a struct) | `MeshMergeError` (enum, with `IncompatiblePrimitiveTopology` variant) | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#rework-mergemesherror | | `ScaleVolume` Add/Sub arithmetic on `Volume::Linear` | `Volume::Linear(x).increase_by_percentage(...)` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#remove-the-add-sub-impls-on-volume | | `SceneSpawner::despawn`/`despawn_sync`/`update_spawned_scenes` (0.16, dynamic-scene variants) | `despawn_dynamic` / `despawn_dynamic_sync` / `update_spawned_dynamic_scenes`; the un-suffixed names now act on `Scene` | 0.17 | https://bevy.org/learn/migration-guides/0-16-to-0-17/#scenespawner-methods-have-been-renamed-and-replaced | From 996a4713ee349b0af77adffbba17f1b6b09c512e Mon Sep 17 00:00:00 2001 From: Jaco du Preez Date: Sun, 9 Aug 2026 20:43:31 +0200 Subject: [PATCH 04/10] docs(bevy): add 8 engine-reference module guides (Task 3) Quick-reference guides for Bevy 0.19.0: ecs, 2d, 3d, ui, asset, input, audio, testing. Every API name verified against docs.rs bevy 0.19.0 pages and the official migration guides; reuses Task 2 verified facts (breaking-changes, deprecated-apis). Documents 0.16->0.19 renames: Message/MessageWriter/MessageReader, WorldAssetRoot, Resources-as- components, removed *Bundle structs, Gamepad-as-component, no PhysicalKey, Touches resource, LoadState, load_builder, FontSource/FontSize. --- docs/engine-reference/bevy/modules/2d.md | 79 ++++++++++++ docs/engine-reference/bevy/modules/3d.md | 87 +++++++++++++ docs/engine-reference/bevy/modules/asset.md | 82 +++++++++++++ docs/engine-reference/bevy/modules/audio.md | 66 ++++++++++ docs/engine-reference/bevy/modules/ecs.md | 114 ++++++++++++++++++ docs/engine-reference/bevy/modules/input.md | 72 +++++++++++ docs/engine-reference/bevy/modules/testing.md | 78 ++++++++++++ docs/engine-reference/bevy/modules/ui.md | 95 +++++++++++++++ 8 files changed, 673 insertions(+) create mode 100644 docs/engine-reference/bevy/modules/2d.md create mode 100644 docs/engine-reference/bevy/modules/3d.md create mode 100644 docs/engine-reference/bevy/modules/asset.md create mode 100644 docs/engine-reference/bevy/modules/audio.md create mode 100644 docs/engine-reference/bevy/modules/ecs.md create mode 100644 docs/engine-reference/bevy/modules/input.md create mode 100644 docs/engine-reference/bevy/modules/testing.md create mode 100644 docs/engine-reference/bevy/modules/ui.md diff --git a/docs/engine-reference/bevy/modules/2d.md b/docs/engine-reference/bevy/modules/2d.md new file mode 100644 index 0000000..fb55647 --- /dev/null +++ b/docs/engine-reference/bevy/modules/2d.md @@ -0,0 +1,79 @@ +# Bevy 2D — Quick Reference + +**Last verified:** 2026-08-09 + +## Core Concepts +- **Sprite** — component describing a 2D image render: fields `image: Handle`, `color`, `flip_x`, `flip_y`, `custom_size: Option`, `rect: Option`, `texture_atlas: Option`. Required components `Transform`, `Visibility`, `VisibilityClass`, `Anchor` are auto-inserted. +- **Camera2d** — unit-struct component (`commands.spawn(Camera2d)`); requires `Camera`, `Projection` (defaults to `OrthographicProjection::default_2d()`), `Frustum`. +- **Transform** — `translation: Vec3`, `rotation: Quat`, `scale: Vec3`; `GlobalTransform` auto-inserted. In 2D, `translation.z` is the z-ordering. +- **Sprite sheets** — `TextureAtlasLayout` asset + `TextureAtlas { layout, index }` struct (see below). +- **Parallax** — not built into Bevy 0.19; layer multiple cameras at different `Camera.order` depths or offset layers per frame. +- **Bundles removed** — `SpriteBundle` no longer exists (0.16+); spawn plain components and required components fill in the rest. + +## Spawning Sprites +```rust +fn setup(mut commands: Commands, asset_server: Res) { + commands.spawn(Camera2d); + commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png"))); +} +``` +- `Sprite::from_image(handle)` — full-image sprite (example above is a verified rustdoc example). +- `Sprite::sized(Vec2::new(75., 75.))` — custom-size sprite. +- `Sprite::from_atlas_image(handle, atlas)` — sprite-sheet sprite. +- Pair with `Transform` for placement: `commands.spawn((Sprite::from_image(h), Transform::from_xyz(10.0, 20.0, 0.0)))`. + +## Sprite Sheets +```rust +fn setup( + mut commands: Commands, + asset_server: Res, + mut texture_atlas_layouts: ResMut>, +) { + let texture = asset_server.load("textures/rpg/chars/gabe/gabe-idle-run.png"); + let layout = TextureAtlasLayout::from_grid(UVec2::splat(24), 7, 1, None, None); + let texture_atlas_layout = texture_atlas_layouts.add(layout); + + commands.spawn(( + Sprite::from_atlas_image( + texture, + TextureAtlas { + layout: texture_atlas_layout, + index: 0, + }, + ), + Transform::from_scale(Vec3::splat(6.0)), + )); +} +``` +- `TextureAtlasLayout` is the asset: `from_grid(tile_size: UVec2, columns: u32, rows: u32, padding: Option, offset: Option)`, added via `texture_atlas_layouts.add(layout)` → `Handle`. +- `TextureAtlas` is a plain struct (`layout: Handle`, `index: usize`) nested inside `Sprite.texture_atlas` — not a standalone component. +- Animate by changing `Sprite.texture_atlas.index` (`Query<&mut Sprite>`) on a `Timer`. + +## Cameras & Transforms +```rust +// Move a sprite; translation.z = draw order (higher = closer to camera) +fn move_sprite(mut query: Query<&mut Transform>, time: Res