Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
8ae4d57
Cut new_ui_debug_overlay_features
alice-i-cecile May 6, 2026
16e7437
Cut platform_dirs release note
alice-i-cecile May 6, 2026
88000cb
Cut snap_to_axes release note
alice-i-cecile May 6, 2026
3fa7a4a
Add image todos
alice-i-cecile May 6, 2026
092703b
Merge post-processing release notes
alice-i-cecile May 6, 2026
b8dd2c6
Revise text input notes
alice-i-cecile May 6, 2026
d5765b9
Add usage examples to settings note + include dirs module
alice-i-cecile May 6, 2026
dc717b7
Rewrite resources-as-components release note
alice-i-cecile May 6, 2026
18eb564
Revise delayed commands release note
alice-i-cecile May 6, 2026
6cbb216
Better framing for observer run conditions
alice-i-cecile May 6, 2026
cf885f5
Contextualize text_gizmos
alice-i-cecile May 6, 2026
a96509d
Better explain significance of reflect_serde_handles
alice-i-cecile May 6, 2026
5d8e4e0
Improve framing for skinned_mesh_culling.md
alice-i-cecile May 6, 2026
e0f899a
Review Partial Bindless on Metal
alice-i-cecile May 6, 2026
414979a
Clean up diagnostics_overlay release note
alice-i-cecile May 6, 2026
4b153b5
Rewrite render recovery release note
alice-i-cecile May 6, 2026
3e575a0
Explain why we don't handle inputs for TransformGizmo
alice-i-cecile May 6, 2026
3275b7f
Better storytelling for allow_self_relationships
alice-i-cecile May 6, 2026
024ddf2
Rewrite PCCM release note to make it more approachable
alice-i-cecile May 6, 2026
4f1ec04
Revise asset_saving notes for flow
alice-i-cecile May 6, 2026
cd00aa6
Resource hooks are coming too
alice-i-cecile May 7, 2026
554872e
Revise infinite grid release note
alice-i-cecile May 7, 2026
116ace5
Rewrite contiguous access release note
alice-i-cecile May 7, 2026
ffa9970
Merge and rewrite font features
alice-i-cecile May 7, 2026
aa5ea7d
Delete area_lights.md: no shadows means not yet ready!
alice-i-cecile May 7, 2026
6ef804b
Cut render diagnostics note: too niche
alice-i-cecile May 7, 2026
c620f7a
Cut sprite_mesh release note: confusing and incomplete
alice-i-cecile May 7, 2026
d69fb23
Expand web_tasks.md note
alice-i-cecile May 7, 2026
0816581
Revise Feather widgets release notes
alice-i-cecile May 7, 2026
4bc369b
Fix up example in settings.md
alice-i-cecile May 7, 2026
5a06e77
Typos
alice-i-cecile May 7, 2026
6985045
Fix links
alice-i-cecile May 7, 2026
eab59fa
Demonstrate fields in post_process_effects.md examples
alice-i-cecile May 7, 2026
0bda699
a -> an
alice-i-cecile May 7, 2026
01fc634
Capture relevance of release notes to editor progress
alice-i-cecile May 7, 2026
83992f5
Reduce stiffness
alice-i-cecile May 7, 2026
83df011
Strengthen hook for post_processing_effects
alice-i-cecile May 7, 2026
3a7f751
Revise text_gizmos note again for tone, motivation and brevity
alice-i-cecile May 7, 2026
ee4d830
Cut API-docs note from reflect_serde_handles
alice-i-cecile May 7, 2026
b06554a
Ground post-processing effects in actual game usage
alice-i-cecile May 7, 2026
fd4a8ec
Less hedging in more_widgets
alice-i-cecile May 7, 2026
64a8aa4
Fix duplicated sentence fragment in text_gizmos
alice-i-cecile May 7, 2026
291a579
Less words good
alice-i-cecile May 7, 2026
aa1f4cc
Awkward phrasing in transform_gizmo
alice-i-cecile May 7, 2026
797c25d
Call out epilepsy risk clearly
alice-i-cecile May 7, 2026
c168147
Cut vague "data-processing applications"
alice-i-cecile May 7, 2026
5963a0a
Clean up wording on resources_as_components
alice-i-cecile May 7, 2026
5fe0caa
Mention cancellation caveat for delayed commands
alice-i-cecile May 7, 2026
83ccd38
Make new_font_features less stiff
alice-i-cecile May 7, 2026
634c161
More natural flow for vignette examples
alice-i-cecile May 7, 2026
b1dfedb
Clarify tangled asset saving line
alice-i-cecile May 7, 2026
cd1dda9
Remove redundant eventually
alice-i-cecile May 7, 2026
888b557
Remove duplicate Bevy 0.19 reference in the same note
alice-i-cecile May 7, 2026
7ec4da9
Contextualize partial_bindless better
alice-i-cecile May 7, 2026
f6f6249
Immutable resources!!
alice-i-cecile May 7, 2026
5d3ae42
Merge branch 'main' into release-note-pass
alice-i-cecile May 7, 2026
7dad104
Apply suggestion from @Trashtalk217
alice-i-cecile May 7, 2026
9ea6acd
Apply suggestions from code review
alice-i-cecile May 7, 2026
fdf1855
Apply suggestions from code review
alice-i-cecile May 7, 2026
61e4588
Apply suggestions from code review
alice-i-cecile May 7, 2026
5af0c03
Manually apply buggy suggestion
alice-i-cecile May 7, 2026
8015d51
Reduce jargon in skinned mesh culling note
alice-i-cecile May 7, 2026
4c99bc1
Specify "Vulkan" validation errors
alice-i-cecile May 7, 2026
ffb18a8
Linting
alice-i-cecile May 7, 2026
bb8188e
Incorporate API tweak from PR #24181
alice-i-cecile May 8, 2026
2269c63
Fix failing doc link
alice-i-cecile May 8, 2026
a84cd0f
Clarify Reverse Domain Name usage
alice-i-cecile May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 4 additions & 16 deletions _release-content/release-notes/allow_self_relationships.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ authors: ["@mrchantey"]
pull_requests: [22269]
---

Relationships can now optionally point to their own entity by setting the `allow_self_referential` attribute on the `#[relationship]` macro.
By default, Bevy rejects relationship components that point to the entity they live on. If you insert one, Bevy will log a warning and remove it.
This default exists for good reason: structural relationships like `ChildOf` form hierarchies that Bevy traverses recursively — a self-referential `ChildOf` would produce an infinite loop.

By default pointing a relationship to its own entity will log a warning and remove the component. However, self-referential relationships are semantically valid in many cases: `Likes(self)`, `EmployedBy(self)`, `TalkingTo(self)`, `Healing(self)`, and many more.

## Usage

To allow a relationship to point to its own entity, add the `allow_self_referential` attribute:
But many relationships are purely semantic. `Likes(self)`, `EmployedBy(self)`, `Healing(self)` — these don't imply any traversal, and self-reference is perfectly valid. You can now opt in with `allow_self_referential`:

```rust
#[derive(Component)]
Expand All @@ -22,13 +19,4 @@ pub struct LikedBy(pub Entity);
pub struct PeopleILike(Vec<Entity>);
```

Now entities can have relationships that point to themselves:

```rust
let entity = world.spawn_empty().id();
world.entity_mut(entity).insert(LikedBy(entity));

// The relationship is preserved
assert!(world.entity(entity).contains::<LikedBy>());
assert!(world.entity(entity).contains::<PeopleILike>());
```
With the attribute set, inserting a self-referential relationship is accepted without warning.
17 changes: 0 additions & 17 deletions _release-content/release-notes/area_lights.md

This file was deleted.

27 changes: 13 additions & 14 deletions _release-content/release-notes/asset_saving.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
---
title: Asset Saving
authors: ["@andriyDev"]
pull_requests: []
pull_requests: [22622]
---

Since Bevy 0.12, we've had the `AssetSaver` trait. Unfortunately, this trait was not really usable
for asset saving: it was only intended for use with asset processing! This was a common stumbling
block for users, and pointed to a gap in our API.
Bevy has had an `AssetSaver` trait since 0.12.
However, it was only ever intended for use inside asset processing pipelines, not for saving assets at runtime.
This left a frustrating gap: if you wanted to save a procedurally generated mesh, a baked lightmap, or the output of an in-editor workflow, there was no supported path to do it.

Now, users can save their assets using `save_using_saver`. To use this involves two steps.
Now there is. `save_using_saver` lets you save any asset to disk using an `AssetSaver` implementation of your choice.

## 1. Building the `SavedAsset`

To build the `SavedAsset`, either use `SavedAsset::from_asset`:
For simple assets with no sub-assets, use `SavedAsset::from_asset`:

```rust
let main_asset = InlinedBook {
Expand All @@ -21,10 +21,10 @@ let main_asset = InlinedBook {
let saved_asset = SavedAsset::from_asset(&main_asset);
```

Or for more complicated cases, `SavedAssetBuilder`:
For assets that reference other assets (sub-assets), use `SavedAssetBuilder`:

```rust
let asset_path: AssetPath<'static> = "my/file/path.whatever";
let asset_path: AssetPath<'static> = "my/file/path.whatever".into();
let mut builder = SavedAssetBuilder::new(asset_server.clone(), asset_path.clone());

let subasset_1 = Line("howdy".into());
Expand All @@ -40,13 +40,11 @@ let main_asset = Book {
let saved_asset = builder.build(&main_asset);
```

Note that since these assets are borrowed, building the `SavedAsset` should happen in the same async
task as the next step.
`SavedAsset` borrows rather than owns its assets.
That means you can build and save in the same async block — no need to transfer ownership first.

## 2. Calling `save_using_saver`

Now, with a `SavedAsset`, we can just call `save_using_saver` and fill in any arguments:

```rust
save_using_saver(
asset_server.clone(),
Expand All @@ -57,5 +55,6 @@ save_using_saver(
).await.unwrap();
```

Part of this includes implementing the `AssetSaver` trait on `MyAssetSaver`. In addition, this is an
async function, so it is likely you will want to spawn this using `IoTaskPool::get().spawn(...)`.
`save_using_saver` is async.
Generally, you'll want to spawn it with `IoTaskPool::get().spawn(...)`.
You'll also need to implement `AssetSaver` for `MyAssetSaver` to define the serialization format.
50 changes: 34 additions & 16 deletions _release-content/release-notes/contiguous_access.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
---
title: Contiguous access
title: Contiguous query access
authors: ["@Jenya705"]
pull_requests: [21984]
pull_requests: [21984, 24181]
---

Enables accessing slices from tables directly via Queries.
[SIMD] is a critical modern tool for performance optimization, but using it in Bevy has always been harder than it needed to be.
Table components in Bevy are already laid out flat in memory — all `Transform` components are stored as values in a contiguous table, exactly what SIMD wants.
The `Query` iterator just wasn't exposing that structure: it handed you one entity's component at a time, and the compiler had no way to know the underlying data was a contiguous array.

## Goals
`contiguous_iter` and `contiguous_iter_mut` hand you the whole table slice at once. LLVM can see the contiguous array and auto-vectorize — or you can reach for explicit SIMD yourself.

`Query` and `QueryState` have new methods `contiguous_iter`, `contiguous_iter_mut` and `contiguous_iter_inner`, which allows querying contiguously (i.e., over tables). For it to work the query data must implement `ContiguousQueryData` and the query filter `ArchetypeFilter`. When a contiguous iterator is used, the iterator will jump over whole tables, returning corresponding data. Some notable implementors of `ContiguousQueryData` are `&T` and `&mut T`, returning `&[T]` and `ContiguousMut<T>` correspondingly, where the latter structure lets you get a mutable slice of components as well as corresponding ticks. Some notable implementors of `ArchetypeFilter` are `With<T>` and `Without<T>` and notable types **not implementing** it are `Changed<T>` and `Added<T>`.
On a bulk `position += velocity` update over 10,000 entities, this gives some serious speedups:

For example, this is useful, when an operation must be applied on a large amount of entities lying in the same tables, which allows for the compiler to auto-vectorize the code, thus speeding it up.
| Method | Time | Time (AVX2) |
| ------------------------------- | ------- | ----------- |
| Normal iteration | 5.58 µs | 5.51 µs |
| Contiguous iteration | 4.88 µs | 1.87 µs |
| Contiguous, no change detection | 4.40 µs | 1.58 µs |

### Usage

`Query::contiguous_iter` and `Query::contiguous_iter_mut` return a `Option<QueryContiguousIter>`, which is only `None`, when the query is not dense (i.e., iterates over archetypes, not over tables).
If your project has CPU-heavy workloads (physics engines are a prime example), you should try this out immediately.

```rust
fn apply_velocity(query: Query<(&Velocity, &mut Position)>) {
// `contiguous_iter_mut()` cannot ensure all invariants on the compilation stage, thus
// when a component uses a sparse set storage, the method will return `None`
for (velocity, mut position) in query.contiguous_iter_mut().unwrap() {
// we could also have used position.bypass_change_detection() to do even less work.
for (v, p) in velocity.iter().zip(position.iter_mut()) {
p.0 += v.0;
fn apply_health_decay(mut query: Query<(&mut Health, &HealthDecay)>) {
for (mut health, decay) in query.contiguous_iter_mut().unwrap() {
for (h, d) in health.iter_mut().zip(decay) {
h.0 *= d.0;
}
}
}
```

The `contiguous_iter` family of methods only returns `Ok` if the query is dense. That means:

- All of the fetched components must use the default "table" storage strategy.
- The query filters cannot disrupt the returned query data. "Archetypal filters" like `With<T>` and `Without<T>` are fine; `Changed<T>` and `Added<T>` are not, since they require a per-entity check that makes it impossible to return raw table slices.

Because these conditions are fixed properties of the query type, you're safe to unwrap here unless you are writing generic code,
or working with dynamic components.

You may have noticed that the table above had *three* rows.
While change detection is a generally useful feature, it does incur measurable performance overhead.
By default, `contiguous_iter_mut` returns `ContiguousMut<T>`.
Just like the ordinary `Mut<T>`, it triggers change detection automatically on dereference.
If you don't care about that, `bypass_change_detection()` gives you the raw `&mut [T]` directly for even faster access.
Vroom!

[SIMD]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
16 changes: 8 additions & 8 deletions _release-content/release-notes/delayed_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ pull_requests: [23090]
---

Scheduling things to happen some time in the future is a common and useful tool in game development
for everything from gameplay logic to VFX. To support common use-cases, Bevy now has a general mechanism
for delaying commands to be executed after a specified duration.
for everything from gameplay logic to audio cues to VFX.

While this was previously possible through careful use of timers,
getting the details right was surprisingly tricky and naive solutions were heavy on boilerplate.

Now, you can simply delay arbitrary commands to be executed later.

```rust
fn delayed_spawn(mut commands: Commands) {
Expand All @@ -20,9 +24,5 @@ fn delayed_spawn_then_insert(mut commands: Commands) {
}
```

Our goal for this mechanism is to provide a "good-enough" system for simple use-cases. As a result,
there are certain limitations - for example, delayed commands are currently always ticked by the default
clock during `PreUpdate` (typically `Time<Virtual>`).

If you need something more sophisticated, you can always roll your own version of delayed commands using
the new helpers added for this feature.
Note that this does not have a built-in, blessed cancellation mechanism yet.
We recommend embedding the originating `Entity` into the command if you want to cancel the action if that entity dies or is despawned.
28 changes: 11 additions & 17 deletions _release-content/release-notes/diagnostics_overlay.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,28 @@ authors: ["@hukasu"]
pull_requests: [22486]
---

You can now visualize values from the `DiagnosticStore` using a `DiagnosticsOverlay` window.
*TODO: Add a screenshot of the DiagnosticsOverlay in a real app.*

An overlay can be built by spawning an entity with the [`DiagnosticsOverlay`] component
passing your custom [`DiagnosticPath`] list or using one of the provided presets.
Bevy's diagnostics have always been easy to dump to the terminal, but displaying them in-game meant wiring up your own UI.
`DiagnosticsOverlayPlugin` adds a built-in overlay for this, with presets for common cases:

```rust
commands.spawn(DiagnosticsOverlay::new("MyDiagnostics", vec![MyDiagnostics::COUNTER.into()]));
commands.spawn(DiagnosticsOverlay::fps());
commands.spawn(DiagnosticsOverlay::mesh_and_standard_materials());
```

By default the overlay will display the smoothed moving average for the diagnostic, but
you can also visualize the latest value or the moving average by passing
[`DiagnosticsOverlayStatistic`]. The floating point precision can also be configured
through the [`DiagnosticsOverlayItem::precision`] field.
You can also build a custom overlay from any [`DiagnosticPath`] list:

```rust
commands.spawn(DiagnosticsOverlay::new("MyDiagnostics", vec![MyDiagnostics::COUNTER.into()]));
```

By default the overlay shows the smoothed moving average. You can switch to the latest value or the raw moving average via [`DiagnosticsOverlayStatistic`], and configure floating-point precision with [`DiagnosticsOverlayItem::precision`]:

```rust
commands.spawn(DiagnosticsOverlay::new("MyDiagnostics", vec![DiagnosticsOverlayItem {
path: MyDiagnostics::COUNTER,
statistic: DiagnosticsOverlayStatistic::Value,
precisiom: 4,
precision: 4,
}]));
```

All [`DiagnosticsOverlay`] will be managed by the [`DiagnosticsOverlayPlugin`], this includes
having them being added as a child of [`DiagnosticsOverlayPlane`]. The plane will be initially
spawned on the [`GlobalZIndex`] defined by [`INITIAL_DIAGNOSTICS_OVERLAY_Z_INDEX`]. You can order
the UIs relative to it, or edit the [`GlobalZIndex`] of the plane.

The contents of the [`DiagnosticsOverlay`] entity are rebuilt every second. The system that rebuilds
the contents of the overlays is defined on the [`DiagnosticsOverlaySystems::Rebuild`] system set.
23 changes: 0 additions & 23 deletions _release-content/release-notes/generic_font_families.md

This file was deleted.

59 changes: 51 additions & 8 deletions _release-content/release-notes/infinite_grid.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,57 @@
---
title: "Add an infinite grid to bevy_dev_tools"
authors: [ "@icesentry" ]
title: "Infinite Grid"
authors: [ "@IceSentry" ]
pull_requests: [ 23482 ]
---

When working on a 3d scene in an editor it's often very useful to have a transparent grid that indicates the ground plane and the major axis.
*TODO: Add a screenshot of the infinite grid with a real model.*

There are various techniques to render an infinite grid and avoid artifacts.
This implementation works by rendering the grid as a fullscreen shader.
The grid is rendered from the perspective of the camera and fades out relative to the camera position.
The fade out hides artifacts from drawing lines too far in the horizon.
A transparent ground-plane grid is a staple of 3D editor tooling: it marks the major axes, orients the scene, and makes scale immediately legible.

This is an upstreamed version of the bevy_infinite_grid crate that is maintained by foresight spatial labs.
Simply drawing lines doesn't work well: the mesh has to end somewhere, and the lines that reach toward the horizon create aliasing artifacts and Moiré patterns no matter how far you extend it.

Our implementation renders the grid as a fullscreen shader: the grid is computed per-pixel in screen space from the camera's perspective, and fades out with distance to eliminate aliasing at the horizon.

To add an infinite grid to your app, register `InfiniteGridPlugin` and spawn the `InfiniteGrid` component:

```rust
use bevy::dev_tools::infinite_grid::{InfiniteGrid, InfiniteGridPlugin};
use bevy::prelude::*;

App::new()
.add_plugins((DefaultPlugins, InfiniteGridPlugin))
.add_systems(Startup, setup)
.run();

fn setup(mut commands: Commands) {
commands.spawn(InfiniteGrid);
}
```

Grid appearance — colors, fade distance, line scale — is controlled by `InfiniteGridSettings`, which can be placed on the grid entity or on a specific camera to override it per-view:

```rust
use bevy::dev_tools::infinite_grid::{InfiniteGrid, InfiniteGridSettings};

// On the grid entity (applies to all cameras)
commands.spawn((
InfiniteGrid,
InfiniteGridSettings {
fadeout_distance: 200.0,
..default()
},
));

// On a camera (overrides settings for that camera only)
commands.spawn((
Camera3d::default(),
InfiniteGridSettings {
scale: 0.5,
..default()
},
));
```

This is an upstreamed version of the [`bevy_infinite_grid` crate], created and maintained by Foresight Spatial Labs — thank you for building it and generously contributing it to Bevy!

[`bevy_infinite_grid` crate]: https://github.com/fslabs/bevy_infinite_grid
16 changes: 0 additions & 16 deletions _release-content/release-notes/lens_distortion.md

This file was deleted.

Loading
Loading