163 Commits

Author SHA1 Message Date
Seliksi cb02e96b6d Move bevy_window, bevy_input_focus, custom_cursor features to alternate feature collections (#22488)
Related: Cargo Feature Collections
https://github.com/bevyengine/bevy/pull/21472
## Context:

> If `default_app` is meant to be
> > The core pieces that most apps need. This serves as a baseline
feature set for other higher level feature collections (such as "2d" and
"3d"). It is also useful as a baseline feature set for scenarios like
headless apps that require no rendering (ex: command line tools,
servers, etc).
>
> why should `bevy_window` / `custom_cursor` be there? I would expect
these to be in `common_api`.

\- Me,
https://discord.com/channels/691052431525675048/692572690833473578/1460424003486224517

> Imo this is a mistake. Can you open a PR with a migration guide
please?

\- Alice,
https://discord.com/channels/691052431525675048/692572690833473578/1460429142376845404

## Solution


- <strike>Move `bevy_window`, `bevy_input_focus`, `custom_cursor`
features from `default_app` collection to `common_api`</strike>

- From `default_app` collection move: `bevy_window` to `common_api`,
`bevy_input_focus` to `ui_api`, and `custom_cursor` to
`default_platform`.

## Testing
- Did you test these changes? If so, how?

Confirmed that `default_app` collection no longer introduces the crates
to the dependency tree:
```sh
$ git checkout bevy/main -q

$ cargo tree --no-default-features -Fdefault_app -e normal | grep -e bevy_window -e bevy_input_focus -e custom_cursor
    ├── bevy_input_focus v0.18.0-dev
    │   ├── bevy_window v0.18.0-dev
    ├── bevy_window v0.18.0-dev (*)
        ├── bevy_input_focus v0.18.0-dev (*)
        ├── bevy_window v0.18.0-dev (*)

$ git checkout reduced-feature-group
Previous HEAD position was f8ea30965 Add support for reflected math operations ✖️ (#22478)
Switched to branch 'reduced-feature-group'

$ cargo tree --no-default-features -Fdefault_app -e normal | grep -e bevy_window -e bevy_input_focus -e custom_cursor

$
```

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

I'm not sure how cross-cutting changes to features have to be since I
haven't worked with such a complicated feature set before, so it's
possible I've omitted a change to some place that needs to be updated.
Please point it out to me, thank you.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-06 00:05:19 +00:00
Luo Zhihao c757497b27 Gate LTC LUTs behind a feature and merge them to a texture array (#24065)
# Objective

Alternative to #24004.

https://github.com/bevyengine/bevy/pull/23288 adds ltc luts for rect
light support which implicitly requires `bevy_image/ktx2` and
`bevy_image/zstd` otherwise loading ltc luts will panic.

We either accept to always enable area light supoort (#24004), or add a
feature to opt out it (this PR).

## Solution

Gate ltc luts behind a feature and merge them to a texture array.

## Testing

`rect_light` example works.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-05-04 16:15:20 -07:00
Alice Cecile ba7b3c8950 Rename bevy_experimental_feathers feature to bevy_feathers (#24108)
# Objective

> With the introduction of scene components, the feathers API has now
reached its final form. This has a number of consequences:
> - There's no longer any reason to keep the experimental flag around
> - The effort of migrating the Bevy examples to feathers widgets is
unblocked, however I think we should start with migrating just one
example


- @viridia 

## Solution

1. Rename the feature flag.
2. Write a migration guide.

This was previously attempted as part of
https://github.com/bevyengine/bevy/pull/22934, but I got pushback there.
Now that bsn! is more complete (scene components!) things are better.

I've opted not to change the default features here, even though it makes
it much harder to move our examples over, because that's a much more
contentious change. While I feel that Bevy's default features should be
example-oriented, that's still up for debate!
2026-05-03 23:53:51 +00:00
Christian Oelschlegel f6ff3c334e Remove android game activity from default (#23708)
android handle only one activity, either game or native. To use native,
the default could now be used, but all other android need to add the
game activity.

# Objective

android native activities should be able to use the default

## Solution

remove android-game-activity from default

## Testing

created a default app for android native activity with default

## Important

Will be a breaking change for apps using android-game-activity.

---------

Co-authored-by: Christian Oelschlegel <oelschle@sciphy.de>
Co-authored-by: leomeinel <leo@meinel.dev>
2026-04-28 20:39:04 +00:00
ickshonpe 41f170c0a3 Basic clipboard support (#19106)
# Objective

Add a platform-agnostic interface for interacting with the clipboard.

## Solution

New crate `bevy_clipboard` with a `ClipboardPlugin` that adds a
`Clipboard` resource. The clipboard is accessed using the methods
`fetch_text`, `fetch_image`, `set_text` and `set_image` on the
`Clipboard` resource. `fetch_text` returns a `ClipboardRead` with a
`poll_result` method that's used to get the actual value once it's
ready.

The `windows` and `unix` implementations both use the `arboard` crate.
On windows the `Clipboard` resource is a unit struct and a new arboard
clipboard instance is created and dropped for each clipboard access. On
unix targets the `Clipboard` resource holds a clipboard instance it
reuses each time. On both targets the `fetch_*` and `set_*` methods work
instantly.

On `wasm32` `Clipboard` is a unit struct. The `fetch_text` and
`set_text` functions spawn async tasks. The task spawned by `fetch_text`
updates the shared arc mutex option once the future is evaluated to get
the clipboard text. There is no image support on `wasm32`.

Everything seems to work but it feels like the design is a bit clumsy
and not very idiomatic. I don't tend to do much asynchronous
programming, maybe a reviewer can suggest an improved construction.

I also added an alternative `fetch_text_async` function for async access
that returns a `Result<String, ClipboardError>` future.

### Notes
* Doesn't support android targets yet. 
* The wasm32 implementation doesn't support images. It's much more
complicated and probably best to left to a follow up.

## Testing

The PR includes a basic example `clipboard` that can be used for
testing.
The image display will only work if the image is already in the
clipboard before the example starts.

---------

Co-authored-by: Gilles Henaux <ghx_github_priv@fastmail.com>
Co-authored-by: Andrew Zhurov <zhurov.andrew@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-04-23 21:18:07 +00:00
Dylan Sechet 5927c47b8d Use a LUT for F_AB (#23737)
# Objective

`F_AB` currently uses a polynomial approximation. This replaces it it
with a more precise LUT.

## Solution

Add a LUT computed using Monte-Carlo sampling. Generation script is
available
[here](https://gist.github.com/dylansechet/6086e924266caf8dd975c127f73f1e45).

The minimum value was clipped to `1e-6`, which modifies 0.4% of the
values that were below that but should help prevent bugs like #22833.

Open questions:
- Do we want to feature-gate this with the polynomial version as a
fallback?
## Testing

- White furnace still looks white
- Solari example runs
- Put a camera at grazing angles in the atmosphere example to make sure
we weren't reintroducing #22833
---

## Showcase

### F_AB tables

Current PR uses the Monte-Carlo based LUT, bevy currently uses the
polynomial approximation.

<img width="600" height="600" alt="f_ab_monte_carlo"
src="https://github.com/user-attachments/assets/f5f47c57-94a5-4a3b-886c-ae1cac72d3d5"
/>
<img width="600" height="600" alt="f_ab_polynomial_approx"
src="https://github.com/user-attachments/assets/f946a3a1-7206-4de2-952b-b28d588d0e11"
/>
<img width="600" height="600" alt="mae"
src="https://github.com/user-attachments/assets/70679caf-a9ec-4389-8bc8-d7b8fc24b3b1"
/>

### Solari white furnace
This new approximation significantly improves the solari white furnace.

Main:
<img width="1280" height="720" alt="solari_wf_main"
src="https://github.com/user-attachments/assets/3a5aed1b-8449-491f-bedf-1d73614b202d"
/>

With this PR:
<img width="1280" height="720" alt="solari_wf_fablut"
src="https://github.com/user-attachments/assets/e2d2c585-b201-4194-8c94-5376d8f24706"
/>


### LUT size vs error
I ended up going with 64x64.
<img width="2500" height="600" alt="size_error"
src="https://github.com/user-attachments/assets/3d94c2bf-1768-4a04-bc02-e621bf6ad3a9"
/>
2026-04-18 03:34:40 +00:00
andriyDev efc6464f9b Create types to store serializable data about the ECS schedule and provide tools for extracting this data. (#22520)
# Objective

- A step towards #10981.
- Allow us to extract data from an app about the schedules.

Here are also some **non-goals** for this PR. These are left as future
work:

- Extract every piece of data in the schedule. I've focused on a rough
set of information that should let us visualization the most important
parts.
- Provide utilities for interpreting the data. This PR is focused on
just extracting the data, interpreting it comes next.
- Any sort of dot graph tools.

## Solution

- Create ser/de compatible structs for representing schedule data.
- Create a function to get schedule data from an initialized `Schedule`.
- Create a plugin to automatically extract the schedule data for every
schedule in the `App`.
- Note this doesn't include other subapps, I'll also leave that to
another PR.
- Make `bevy_ecs` return edges that build passes added.
- Make `bevy_ecs` return the "build metadata" to the caller, and also
trigger as an event.

## Testing

- Added tests!
- Added an example - it outputs a ron file. I assume its all valid.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-04-06 23:06:15 +00:00
Carter Anderson 6b0fb37e2c Rename bevy_scene2 to bevy_scene (#23668)
# Objective

Part 3 of #23619 

## Solution

Renames `bevy_scene2` to `bevy_scene` and adds it to the prelude.
2026-04-05 02:19:43 +00:00
Carter Anderson 535cf401cc Reframe old "scene" terminology as "world serialization" (#23630)
Part 2 of #23619 

In **Bevy 0.19** we are landing a subset of Bevy's Next Generation Scene
system (often known as BSN), which now lives in the `bevy_scene` /
`bevy::scene` crate. However the old `bevy_scene` system still needs to
stick around for a bit longer, as it provides some features that Bevy's
Next Generation Scene system doesn't (yet!):

1. It is not _yet_ possible to write a World _to_ BSN, so the old system
is still necessary for "round trip World serialization".
2. The GLTF scene loader has not yet been ported to BSN, so the old
system is still necessary to spawn GLTF scenes in Bevy.

For this reason, we have renamed the old `bevy_scene` crate to
`bevy_world_serialization`. If you were referencing `bevy_scene::*` or
`bevy::scene::*` types, rename those paths to
`bevy_world_serialization::*` and `bevy::world_serialization::*`
respectively.

Additionally, to avoid confusion / conflicts with the new scene system,
all "scene" terminology / types have been reframed as "world
serialization":

- `Scene` -> `WorldAsset` (as this was always just a World wrapper)
- `SceneRoot` -> `WorldAssetRoot`
- `DynamicScene` -> `DynamicWorld`
    - `DynamicScene::from_scene` -> `DynamicWorld::from_world_asset`
- `DynamicSceneBuilder` -> `DynamicWorldBuilder`
- `DynamicSceneRoot` -> `DynamicWorldRoot`
- `SceneInstanceReady` -> `WorldInstanceReady`
- `SceneLoader` -> `WorldAssetLoader`
- `ScenePlugin` -> `WorldSerializationPlugin`
- `SceneRootTemplate` -> `WorldAssetRootTemplate`
- `SceneSpawner` -> `WorldInstanceSpawner`
- `SceneFilter` -> `WorldFilter`
- `SceneLoaderError` -> `WorldAssetLoaderError`
- `SceneSpawnError` -> `WorldInstanceSpawnError`

Note that I went with `bevy_world_serialization` over
`bevy_ecs_serialization`, as that is what all of the internal features
described themselves as. I think it is both more specific and does a
better job of making itself decoupled from `bevy_ecs` proper.
2026-04-04 00:31:47 +00:00
Carter Anderson 45e454a83b Rename bevy_scene to bevy_ecs_serialization (#23619)
# Objective

The first part of #23606.

## Solution

Rename `bevy_scene` to `bevy_ecs_serialization`. No other changes were
made.

## Testing

The `scene` example still works as expected.
2026-04-02 02:22:58 +00:00
Carter Anderson f4d17d9eb2 Next Generation Scenes: Core scene system, bsn! macro, Templates (#23413)
After much [iteration](https://github.com/bevyengine/bevy/pull/20158),
[designing](https://github.com/bevyengine/bevy/discussions/14437) and
[collaborating](https://discord.com/channels/691052431525675048/1264881140007702558),
it is finally time to land a baseline featureset of Bevy's Next
Generation Scene system, often known by its new scene format name ...
BSN (Bevy Scene Notation).

This PR adds the following:
- **The new scene system**: The core in-memory traits, asset types, and
functionality for Bevy's new scene system. Spawn `Scene`s and
`SceneList`s. Inherit from other scenes. Patch component fields. Depend
on assets before loading as scene. Resolve Entity references throughout
your scene.
- **The `bsn!` and `bsn_list!` macro**s: Define Bevy scenes in your code
using a new ergonomic Rust-ey syntax, which plays nicely with Rust
Analyzer and supports autocomplete, go-to definition, semantic
highlighting, and doc hover.
- **`Template` / `GetTemplate`**: construct types (ex: Components) from
a "template context", which includes access to the current entity _and_
access to the `World`. This is a foundational piece of the scene system.

Note that this _does not_ include a loader for the BSN asset format,
which will be added in a future PR. See the "Whats Next?" section for a
roadmap of the future.

Part of #23030 

## Review Etiquette

This is a big PR. _Please use threaded comments everywhere, not top
level comments_. Even if what you have to say is not anchored in code,
find a line to leave your comment on.

## Overview

This is a reasonably comprehensive conceptual overview / feature list.
This uses a "bottom up" approach to illustrate concepts, as they build
on each other. If you just want to see what BSN looks like, scroll down
a bit!
### Templates

`Template` is a simple trait implemented for "template types", which
when passed an entity/world context, can produce an output type such as
a `Component` or `Bundle`:

```rust
pub trait Template {
    type Output;
    fn build_template(&mut self, context: &mut TemplateContext) -> Result<Self::Output>;
}
```

Template is the cornerstone of the new scene system. It allows us to
define types (and hierarchies) that require no `World` context to
define, but can _use_ the `World` to produce the final runtime state.
Templates are notably:

* **Repeatable**: Building a Template does not consume it. This allows
us to reuse "baked" scenes / avoid rebuilding scenes each time we want
to spawn one. If a Template produces a value this often means some form
of cloning is required.
* **Clone-able**: Templates can be duplicated via
`Template::clone_template`, enabling scenes to be duplicated, supporting
copy-on-write behaviors, etc.
* **Serializable**: Templates are intended to be easily serialized and
deserialized, as they are typically composed of raw data.

The poster-child for templates is the asset `Handle<T>`. We now have a
`HandleTemplate<T>`, which wraps an `AssetPath`. This can be used to
load the requested asset and produce a strong `Handle` for it.

```rust
impl<T: Asset> Template for HandleTemplate<T> {
    type Output = Handle<T>;
    fn build_template(&mut self, context: &mut TemplateContext) -> Result<Handle<T>> {
        Ok(context.resource::<AssetServer>().load(&self.path))
    }
}
```

Types that have a "canonical" `Template` can implement the `GetTemplate`
trait, allowing us to correlate to something's `Template` in the type
system.

```rust
impl<T: Asset> GetTemplate for Handle<T> {
    type Template = HandleTemplate<T>;
}
```

This is where things start to get interesting. `GetTemplate` can be
derived for types whose fields also implement `GetTemplate`:

```rust
#[derive(Component, GetTemplate)]
struct Sprite {
  image: Handle<Image>,
}
```

Internally this produces the following:

```rust
#[derive(Template)]
struct SpriteTemplate {
  image: HandleTemplate<Image>,
}

impl GetTemplate for Sprite {
    type Template = SpriteTemplate;
}
```

Another common use case for templates is `Entity`. With templates we can
resolve an identifier of an entity in a scene to the final `Entity` it
points to (for example: an entity path or an "entity reference" ... this
will be described in detail later).

Both `Template` and `GetTemplate` are blanket-implemented for any type
that implements both Clone and Default. This means that _most_ types are
automatically usable as templates. Neat!

```rust
impl<T: Clone + Default> Template for T {
    type Output = T;

    fn build_template(&mut self, context: &mut TemplateContext) -> Result<Self::Output> {
        Ok(self.clone())
    }
}

impl<T: Clone + Default> GetTemplate for T {
    type Template = T;
}
```

It is best to think of `GetTemplate` as an alternative to `Default` for
types that require world/spawn context to instantiate. Note that because
of the blanket impl, you _cannot_ implement `GetTemplate`, `Default`,
and `Clone` together on the same type, as it would result in two
conflicting GetTemplate impls. This is also why `Template` has its own
`Template::clone_template` method (to avoid using the Clone impl, which
would pull in the auto-impl).
### Scenes

Templates on their own already check many of the boxes we need for a
scene system, but they aren't enough on their own. We want to define
scenes as _patches_ of Templates. This allows scenes to inherit from /
write on top of other scenes without overwriting fields set in the
inherited scene. We want to be able to "resolve" scenes to a final group
of templates.

 This is where the `Scene` trait comes in:

```rust
pub trait Scene: Send + Sync + 'static {
    fn resolve(&self, context: &mut ResolveContext, scene: &mut ResolvedScene) -> Result<(), ResolveSceneError>;
    fn register_dependencies(&self, _dependencies: &mut Vec<AssetPath<'static>>);
}
```

The `ResolvedScene` is a collection of "final" `Template` instances
which can be applied to an entity. `Scene::resolve` applies the `Scene`
as a "patch" on top of the final `ResolvedScene`. It stores a flat list
of templates to be applied to the top-level entity _and_ typed lists of
related entities (ex: Children, Observers, etc), which each have their
own ResolvedScene. `Scene`s are free to modify these lists, but in most
cases they should probably just be pushing to the back of them.
`ResolvedScene` can handle both repeated and unique instances of a
template of a given type, depending on the context.

`Scene::register_dependencies` allows the Scene to register whatever
asset dependencies it needs to perform `Scene::resolve`. The scene
system will ensure `Scene::resolve` is not called until all of the
dependencies have loaded.

`Scene` is always _one_ top level / root entity. For "lists of scenes"
(such as a list of related entities), we have the `SceneList` trait,
which can be used in any place where zero to many scenes are expected.
These are separate traits for logical reasons: world.spawn() is a
"single entity" action, scene inheritance only makes sense when both
scenes are single roots, etc.
### Template Patches

The `TemplatePatch` type implements `Scene`, and stores a function that
mutates a template. Functionally, a `TemplatePatch` scene will
initialize a `Default` value of the patched `Template` if it does not
already exist in the `ResolvedScene`, then apply the patch on top of the
current Template in the `ResolvedScene`. Types that implement `Template`
can generate a `TemplatePatch` like this:

```rust
#[derive(Template)]
struct MyTemplate {
    value: usize,
}

MyTemplate::patch_template(|my_template, context| {
    my_template.value = 10;
});
```

Likewise, types that implement `GetTemplate` can generate a patch _for
their template type_ like this:

```rust
#[derive(GetTemplate)]
struct Sprite {
    image: Handle<Image>,
}

Sprite::patch(|sprite_template| {
    // note that this is HandleTemplate<Image>
    sprite.image = "player.png".into();
})
```

We can now start composing scenes by writing functions that return `impl
Scene`!

```rust
fn player() -> impl Scene {
    (
        Sprite::patch(|sprite| {
            sprite.image = "player.png".into();
        ),
        Transform::patch(|transform| {
            transform.translation.y = 4.0;
        }),
    )
}
```

### The `on()` Observer / event handler Scene

`on` is a function that returns a scene that creates an Observer
template:

```rust
fn player() -> impl Scene {
    (
        Sprite::patch(|sprite| {
            sprite.image = "player.png".into();
        ),
        on(|jump: On<Jump>| {
            info!("player jumped!");
        })
    )
}
```

### The BSN Format

`BSN` is a new specification for defining Bevy Scenes. It is designed to
be as Rust-ey as possible, while also eliminating unnecessary syntax and
context. The goal is to make defining arbitrary scenes and UIs as easy,
delightful, and legible as possible.

It is intended to be usable as both an asset format (ex: `level.bsn`
files) _and_ defined in code via a `bsn!` macro. These are notably
_compatible with each other_. You can define a BSN asset file (ex: in a
visual scene editor, such as the upcoming Bevy Editor), then inherit
from that and use it in `bsn!` defined in code.

```rust
:"player.bsn"
Player
Sprite { image: "player.png" }
Health(10)
Transform {
	translation: Vec3 { y: 4.0 }
}
on(|jump: On<Jump>| {
	info!("player jumped!");
})
Children [
	(
		Hat
		Sprite { image: "cute_hat.png" }
		Transform { translation: Vec3 { y: 3.0 } } )
	),
	(:sword Transform { translation: Vec3 { x: 10. } } 
]
```

Note that this PR includes the `bsn!` macro, but it does not include the
BSN asset format. It _does_ include all of the in-memory / in-code
support for the asset format. All that remains is defining a BSN asset
loader, which will be done in a followup.
### The `bsn!` Macro

`bsn!` is an _optional_ ergonomic syntax for defining `Scene`
expressions. It was built in such a way that Rust Analyzer autocomplete,
go-to definition, doc hover, and semantic token syntax highlighting
works as expected pretty much everywhere (but there are _some_ gaps and
idiosyncrasies at the moment, which I believe we can iron out).

It looks like this:

```rust
fn player() -> impl Scene {
    bsn! {
        Player
        Sprite { image: "player.png" }
        Health(10)
        Transform {
            translation: Vec3 { y: 4.0 }
        }
        on(|jump: On<Jump>| {
            info!("player jumped!");
        })
        Children [
            (
                Hat
                Sprite { image: "cute_hat.png" }
                Transform { translation: Vec3 { y: 3.0 } } )
            ),
            (:sword Transform { translation: Vec3 { x: 10. } } 
        ]
    }
}

fn sword() -> impl Scene {
    bsn! {
       Sword
       Sprite { image: "sword.png" } 
    }
}

fn blue_player() -> impl Scene {
    bsn! {
        :player
        Team::Blue
        Children [
            Sprite { image: "blue_shirt.png" } 
        ]
    }
}
```

I'll do a brief overview of each implemented `bsn!` feature now.

### `bsn!`: Patch Syntax

When you see a normal "type expression", that resolves to a
`TemplatePatch` as defined above.

```rust
bsn! {
    Player {
        image: "player.png"
    }
}
```

This resolve to the following:

```rust
<Player as GetTemplatePatch>::patch(|template| {
    template.image = "player.png".into();
})
```

This means you only need to define the fields you actually want to set!

Notice the implicit `.into()`. Wherever possible, `bsn!` provides
implicit `into()` behavior, which allows developers to skip defining
wrapper types, such as the `HandleTemplate<Image>` expected in the
example above.

This also works for nested struct-style types:

```rust
bsn! {
    Transform {
        translation: Vec3 { x: 1.0 }
    }
}
```

Note that you can just define the type name if you don't care about
setting specific field values / just want to add the component:

```rust
bsn! {
    Transform
}
```

To add multiple patches to the entity, just separate them with spaces or
newlines:

```rust
bsn! {
    Player
    Transform
}
```

Enum patching is also supported:

```rust
#[derive(Component, GetTemplate)]
enum Emotion {
    Happy { amount: usize, quality: HappinessQuality },
    Sad(usize),
}

bsn! {
    Emotion::Happy { amount: 10. }
}
```

Notably, when you derive GetTemplate for an enum, you get default
template values for _every_ variant:

```rust
// We can skip fields for this variant because they have default values
bsn! { Emotion::Happy }

// We can also skip fields for this variant
bsn! { Emotion::Sad }
```

This means that unlike the `Default` trait, enums that derive
`GetTemplate` are "fully patchable". If a patched variant matches the
current template variant, it will just write fields on top. If it
corresponds to a different variant, it initializes that variant with
default values and applies the patch on top.

For practical reasons, enums only use this "fully patchable" approach
when in "top-level scene entry patch position". _Nested_ enums (aka
fields on patches) require specifying _every_ value. This is because the
majority of types in the Rust and Bevy ecosystem will not derive
`GetTemplate` and therefore will break if we try to create default
variants values for them. I think this is the right constraint solve in
terms of default behaviors, but we can discuss how to support both
nested scenarios effectively.

Constructors also work (note that constructor args are _not_ patched.
you must specify every argument). A constructor patch will fully
overwrite the current value of the Template.

```rust
bsn! {
    Transform::from_xyz(1., 2., 3.)
}
```

You can also use type-associated constants, which will also overwrite
the current value of the template:

```rust
bsn! {
    Transform::IDENTITY
}
```

If you have a type that does not currently implement
Template/GetTemplate, you have two options:

```rust
bsn! {
    // This will return a Template that produces the returned type.
    // `context` has World access!
	template(|context| {
	    Ok(TextFont {
	        font: context
	            .resource::<AssetServer>()
	            .load("fonts/FiraSans-Bold.ttf").into(),
	        ..default()
	    })
	})
	
	// This will return the value as a Template
	template_value(Foo::Bar)
}
```
### `bsn!` Template patch syntax

Types that are expressed using the syntax we learned above are expected
to implement `GetTemplate`. If you want to patch a `Template` _directly_
by type name (ex: your Template is not paired with a GetTemplate type),
you can do so using `@` syntax:

```rust
struct MyTemplate {
    value: usize,
}

impl Template for MyTemplate {
    /* impl here */
}

bsn! {
    @MyTemplate {
        value: 10.
    }
}
```

In most cases, BSN encourages you to work with the _final_ type names
(ex: you type `Sprite`, not `SpriteTemplate`).

However in cases where you really want to work with the template type
directly (such as custom / manually defined templates), "Template patch
syntax" lets you do that!
### `bsn!`: Inline function syntax

You can call functions that return `Scene` impls inline. The `on()`
function that adds an Observer (described above) is a particularly
common use case

```rust
bsn! {
    Player
    on(|jump: On<Jump>| {
        info!("Player jumped");
    })
}
```

### `bsn!`: Relationship Syntax

`bsn!` provides native support for spawning related entities, in the
format `RelationshipTarget [ SCENE_0, ..., SCENE_X ]`:

```rust
bsn! {
    Node { width: Px(10.) } 
    Children [
        Node { width: Px(4.0) },
        (Node { width: Px(4.0) } BackgroundColor(srgb(1.0, 0.0, 0.0)),
    ]
}
```

Note that related entity scenes are comma separated. Currently they can
either be flat _or_ use `()` to group them:

```rust
bsn! {
    Children [
        // Child 1
        Node BorderRadius::MAX,
        // Child 2
        (Node BorderRadius::MAX),
    ]
}
```

It is generally considered best practice to wrap related entities with
more than one entry in `()` to improve legibility.

### `bsn!`: Expression Syntax

`bsn!` supports expressions in a number of locations using `{}`:

```rust
let x: u32 = 1;
let world = "world";
bsn! {
    // Field position expressions
    Health({ x + 2 })
    Message {
        text: {format!("hello {world}")}
    }
}
```

Expressions in field position have implicit `into()`.

Expressions are also supported in "scene entry" position, enabling
nesting `bsn!` inside `bsn!`:

```rust
let position = bsn! {
    Transform { translation: Vec3 { x: 10. } }
};

bsn! {
    Player
    {position}
}
```

### `bsn!`: Inline variables

You can specify variables inline:

```rust
let black = Color::BLACK;
bsn! {
    BackgroundColor(black)
}
```

This also works in "scene entry" position:

```rust
let position = bsn! {
    Transform { translation: Vec3 { x: 10. } }
};

bsn! {
    Player
    position
}
```

### Inheritance

`bsn!` uses `:` to designate "inheritance". Unlike defining scenes
inline (as mentioned above), this will _pre-resolve_ the inherited
scene, making your current scene cheaper to spawn. This is great when
you inherit from large scene (ex: an asset defined by a visual editor).
Scenes can only inherit from one scene at a time, and it must be defined
first.

You can inherit from scene assets like this:

```rust
fn red_button() -> impl Scene {
    bsn! {
        :"button.bsn"
        BackgroundColor(RED)
    }
}
```

Note that while there is currently no implemented `.bsn` asset format,
you can still test this using `AssetServer::load_with_path`.

You can also inherit from functions that return a `Scene`:

```rust
fn button() -> impl Scene {
    bsn! {
        Button
        Children [
            Text("Button")
        ]
    }
}

fn red_button() -> impl Scene {
    bsn! {
        :button
        BackgroundColor(RED)
    }
}
```

Note that because inheritance is cached / pre-resolved, function
inheritance does not support function parameters. You can still use
parameterized scene functions by defining them directly in the scene
(rather than using inheritance):

```rust
fn button(text: &str) -> impl Scene {
    bsn! {
        Button
        Children [
            Text(text)
        ]
    }
}

fn red_button() -> impl Scene {
    bsn! {
        button("Click Me")
        BackgroundColor(RED)
    }
}
```

Related entities can also inherit:

```rust
bsn! {
    Node
    Children [
        (:button BackgroundColor(RED)),
        (:button BackgroundColor(BLUE)),
    ]
}
```

Inheritance concatenates related entities:

```rust
fn a() -> impl Scene {
    bsn! {
        Children [
            Name("1"),
            Name("2"),
        ]
    }
}

fn b() -> impl Scene {
    /// this results in Children [ Name("1"), Name("2"), Name("3") ]
    bsn! {
        :a
        Children [
            Name("3"),
        ]
    }
}
```

### `bsn_list!` / SceneList

Relationship expression syntax `{}` expects a SceneList. Many things,
such as `Vec<S: Scene>` implement `SceneList` allowing for some cool
patterns:

```rust
fn inventory() -> impl Scene {
    let items = (0..10usize)
        .map(|i| bsn! {Item { size: {i} }})
        .collect::<Vec<_>>();
    bsn! {
        Inventory [
            {items}
        ]
    } 
}
```

The `bsn_list!` macro allows defining a list of BSN entries (using the
same syntax as relationships). This returns a type that implements
`SceneList`, making it useable in relationship expressions!

```rust
fn container() -> impl Scene {
    let children = bsn_list! [
        Name("Child1"),
        Name("Child2"),
        (Name("Child3") FavoriteChild),
    ]
    bsn! {
        Container [
            {children}
        ]
    } 
}
```

This, when combined with inheritance, means you can build abstractions
like this:

```rust
fn list_widget(children: impl SceneList) -> impl Scene {
    bsn! {
        Node {
            width: Val::Px(1.0)
        }
        Children [
            Text("My List:")
            {children}
        ]
    }
}

fn ui() -> impl Scene {
    bsn! {
        Node
        Children [
            list_widget({bsn_list! [
                Node { width: Px(4.) },
                Node { width: Px(5.) },
            ]})
        ]
    }
}
```

### `bsn!`: Name Syntax

You can quickly define `Name` components using `#Name` shorthand.

```rust
bsn! {
    #Root
    Node
    Children [
        (#Child1, Node),
        (#Child2, Node),
    ]
}
```

`#MyName` produces the `Name("MyName")` component output.

Within a given `bsn!` or `bsn_list!` scope, `#Name` can _also_ be used
in _value position_ as an `Entity` Template:

```rust
#[derive(Component, GetTemplate)]
struct UiRoot(Entity);

#[derive(Component, GetTemplate)]
struct CurrentButton(Entity);

bsn! {
	#Root
	CurrentButton(#MyButton)
	Children [
		(
		  #MyButton,
		  UiRoot(#Root)
		)
	]
}
```

These behave a bit like variable names. In the context of inheritance
and embedded scenes, `#Name` is only valid within the current "scene
scope":

```rust
fn button() -> impl Scene {
	bsn! {
		#Button
		Node
		Children [
			ButtonRef(#Button)
		]
	}
}

fn red_button() -> impl Scene {
	bsn! {
		:button
		// #Button is not valid here, but #MyButton
		// will refer to the same final entity as #Button
		#MyButton
		Children [
			AnotherReference(#MyButton)
		]
	}
}
```

In the example above, because `#MyButton` is defined "last" / is the
most "specific" `Name`, the spawned entity will have `Name("MyButton")`

Name references are allowed to conflict across inheritance scopes and
they will not interfere with each other.

`#Name` can also be used in the context of `bsn_list!`, which enables
defining graph structures:

```rust
bsn_list! [
	(#Node1, Sibling(#Node2)),
	(#Node2, Sibling(#Node1)),
]
```
### Name Restructure

The core name component has also been restructured to play nicer with
`bsn!`. The impl on `main` requires `Name::new("MyName")`. By making the
name string field public and internalizing the prehash logic on that
field, and utilizing implicit `.into()`, we can now define names like
this:

```rust
bsn! {
    Name("Root")
    Children [
        Name("Child1"),
        Name("Child2"),
    ]
}
```

### BSN Spawning

You can spawn scenes using `World::spawn_scene` and
`Commands::spawn_scene`:

```rust
world.spawn_scene(bsn! {
    Node
    Children [
        (Node BackgroundColor(RED))
    ]
})?;

commands.spawn_scene(widget());
```

The `spawn_scene` operation happens _immediately_, and therefore assumes
that all of the `Scene`'s dependencies have been loaded (or
alternatively, that there are no dependencies). If the scene has a
dependency that hasn't been loaded yet, `World::spawn_scene` will return
an error (or log an error in the context of `Commands::spawn_scene`).

If your scene has dependencies, you can use `World::queue_spawn_scene`
and `Commands::queue_spawn_scene`. This will spawn the entity as soon as
all of the `Scene`'s dependencies have been loaded.

```rust
// This will spawn the entity once the "player.bsn" asset is loaded
world.queue_spawn_scene(bsn! {
  :"player.bsn"
  Transform { position: Vec3 { x: 10. } }
});
```

There are also `spawn_scene_list` variants for everything above:

```rust
world.spawn_scene_list(bsn_list! [
	button("Ok"),
	button("Cancel"),
])
```

`EntityWorldMut` and `EntityCommands` also have some new functionality:

```rust
entity.queue_spawn_related_scene::<Children>(bsn_list! [
	(:"player.bsn", #Player1),
	(:"player.bsn", #Player2),
]);
```

```rust
entity.apply_scene(bsn! {
	Transform { position: Vec3 { x: 10. } }
})?;
```

For scene assets, you can also just add the `ScenePatchInstance(handle)`
component, just like the old Bevy scene system.
### VariantDefaults derive

`GetTemplate` automatically generates default values for enum Template
variants. But for types that don't use `GetTemplate`, I've also
implemented a `VariantDefaults` derive that also generates these
methods.

## What's Next?

### Must happen before 0.19
- [ ] **Sort out `bevy_scene` vs `bevy_scene2`**: The current plan is to
rename `bevy_scene` to `bevy_ecs_serialization`, and remove "scene"
terminology from it. That then frees up `bevy_scene2` to be renamed to
`bevy_scene`. The current `bevy_scene` will need to exist for awhile in
parallel to BSN, as BSN is not yet ready for "full world serialization"
scenarios.
- [x] ~~**Resolve the Default Handle situation**: Currently, to provide
Template support for `Handle`, it implements `GetTemplate`. This of
course conflicts with `impl Default for Handle`. This is pretty
disruptive to non-BSN users (which is currently everyone). We'll want to
sort out a middleground solution in the short term that ideally allows
us to keep `impl Default for Handle` during the transition.~~
- Resolved this by using a [specialization
trick](https://github.com/bevyengine/bevy/pull/23413#discussion_r2961341173)
- [ ] Nested `bsn!` `Scene` tuples to surpass tuple impl limits


### Ideally before 0.19

We likely won't land all of these. The plan is to (ideally) land this PR
before Bevy 0.19 RC1, then _maybe_ land a couple more of these before

- [ ] **Feathers BSN Port**: Largely already done. Just need to
reconcile with current state of main. This will help BSN land well, so
landing it alongside BSN is a high priority.
- [ ] **ResolvedScene-as-dynamic-bundle**: ResolvedScene should insert
all of the components at once as a single bundle, rather than
one-by-one, which is really bad from an archetype move perspective.
Without this, using `world.spawn_scene(scene)` as a
`world.spawn(bundle)` replacement will result in a pretty significant
performance reduction.
- [ ] **`#Name` references in more places**: The UI eventing scenario
_really_ wants `#Name` to be usable in closures. This would functionally
be expressed as a template that returns a closure that accesses a
specific entity. This unlocks a lot of value for UI devs, so ideally it
lands alongside BSN.
- [ ] **Top-down vs bottom-up spawn order**: Currently BSN follows the
normal bevy top-down spawn order. I think we should heavily consider
spawning bottom-up, in the interest of making scene contents available
to "higher level" components in their lifecycle events (ex: a `Player`
component accessing nested entities like "equipment" when inserted). If
we decide to keep things as they are, we probably want to introduce
additional "scene ready" entity events that trigger "bottom up".
- [ ] **Inline field value expressions**: Support cases such as
`px(10).all()
- [ ] **Add EntityPath to EntityTemplate**: Support resolving entity
paths (ex: `"Root/Child1/GrandChild1"`). This is relatively low hanging
fruit, especially if we switch to bottom-up spawning order.
- [ ] **Function Inheritance Caching**: Currently only scene asset
inheritance is pre-computed / cached. For consistency / predictability /
optimizations, function inheritance (ex `:button`) should also be
cached.
- [ ] **`derive(GetTemplate)` generics ergonomics**: Currently this
requires casting spells: `T: GetTemplate<Template: Default +
Template<Output = T>>`

### Near Future
- [ ] **BSN Asset Format**: Add a `.bsn` parser / AssetLoader that can
produce the current `ScenePatch` assets.
- [ ] **Struct-style inheritance**: It would be nice to be able to do
something like `:Button { prop } ` instead of `:button(prop)`. I'd
really like us to explore this being component-tied (ex: associate a
scene with a Button component).
- [ ] **Descendant Patching**: It should be possible to "reach in" to an
inherited scene and patch one of its descendants / children.
- [ ] **Optimize Related Entity Spawning**: This currently inserts the
relationship component first, then spawns the related scene. This
results in an unnecessary archetype move.
- [ ] Observers as relationships
- [ ] **Scene-owned-entities**: Currently when spawning a `Scene`, every
entity defined in the scene is instantiated. Some scenarios would
benefit from Scene instances _sharing_ some unique entity. For example:
defining assets _inside_ of scenes (this would pair nicely with Assets
as Entities) , sharing Observer entities, etc.
- [ ] The `touch_type::<Nested>()` approach could be replaced with `let
x: &mut Nested` for actual type safety (and probably better
autocomplete).
- [ ] Fix Rust Analyzer autocomplete bug that fails to resolve functions
and enums for `<Transform as GetTemplate>::Template::from_transform()`
- [ ] Fix Rust Analyzer autocomplete bug that also suggests function
names when type struct field names. This _should_ be fixed by using
irrefutable `if let` statements. And it would probably allow us to reuse
macro code across enums / structs (and avoid needing to use PathType
inference in this case, which has gnarly corner cases).
### Longer Term
- [ ] **`bsn!` hot patching via subsecond**: [Proof of concept
here](https://github.com/cart/bevy/pull/36)
- [ ] **Reactivity**: This has been proven out
[here](https://github.com/viridia/bevy_reactor/)
- [ ] **BSN Sets**: See the [old design
doc](https://github.com/bevyengine/bevy/discussions/14437) for the
design space I'm talking about here
* This would also allow expressing "flattened" forms of BSN, which makes
diffs easier to read in some case
- [ ] **World to BSN**: If we can support this, BSN can be used for
things like saving Worlds to disk. This might also be useful for
building scene editors.

---------

Co-authored-by: andriyDev <andriydzikh@gmail.com>
Co-authored-by: Nico Zweifel <34443492+NicoZweifel@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: copygirl <copygirl@mcft.net>
2026-03-27 03:18:26 +00:00
Alice Cecile 525636050f Remove ui from the 2d and 3d feature collections (#23180)
# Objective

Fixes #23170.

## Solution

> Swapping the UI framework for your Bevy project is a common form of
customization.
> We think that users should be able to do this easily, without having
to give up the ease of use (and updates!)
> that come with our top-level feature collections.
> 
> To achieve this, the `ui` feature collection is now no longer implied
by the `3d` or `2d` feature collection.
> 
> To migrate:
> 
> - If you used all default features before, nothing changes for you.
> - If you want to opt out of using `bevy_ui`, it is now as simple as
disabling default features, and manually opting into `3d` or `2d` (and
optionally `audio`).
> - If you already opted into non-default features and want to continue
using `bevy_ui`, you will now have to add the `ui` feature.
2026-03-25 21:34:57 +00:00
Martín Maita a80470f5ec Update Rodio to 0.22 (#20323)
# Objective

- Closes #19672 

## Solution

- Updated both `cpal` and `rodio` to their latest versions.
- Updated code to address `rodio`'s breaking changes.
- Reworked audio related feature flags. NOTE: `symphonia` will only be
the default backend for formats with no alternative fallback.
- Added `audio-all-formats` feature collection to easily enable all the
available audio formats using their default backends.
- Replaced `aarch64-apple-ios-sim` target with
`arm64-apple-ios-simulator`.

## Testing

- Tested audio related examples.
- CI checks passing.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2026-03-24 23:31:06 +00:00
Talin 53050f90e2 New bevy_settings crate (#23034)
Yet another attempt at implementing bevy preferences. This version uses
bevy_reflect serialization to convert resources from toml values into
Rust types and vice versa. This is based on the feedback that I got from
the earlier attempt in #22770

To indicate that a resource type should be loaded as preferences, you'll
need to add the `SettingsGroup` annotation:

```rust
#[derive(Resource, SettingsGroup, Reflect, Default)]
#[reflect(Resource, SettingsGroup, Default)]
struct Counter {
    count: i32,
}
```

This will produce a TOML file that looks like this:

```toml
[counter]
count = 3
```

## Theory of Operation

The `PreferencesPlugin` scans the type registry for all resource types
that impl `SettingsGroup` and `Default`. Derive attributes can be used
to write the resource to a different file (or different key in browser
local storage).

`PreferencesPlugin` should be added before other plugins. This ensures
that any other plugins can have access to the settings data during
initialization.

The loader checks to see if the resource already exists; if so, it uses
that resource instance and patches the toml values into it, preserving
any defaults that have been set. If the resource does not exist, it
constructs a new one via `ReflectDefault` before applying the toml
properties.

(There was a suggestion of using `FromWorld` instead of `Default`. This
is worth considering, although there may be issues with calling
`FromWorld` so early in the app initialization lifecycle, before most
resources have been created.)

On `wasm` platforms, this uses browser local storage rather than the
filesystem to store preferences. On platforms which have neither,
preferences are not supported (although it's possible that some
platform-specific settings storage could be implemented).

## Note on terminology

I've tried to consistently use the term "preferences" rather than
"settings" or "config" because those are broader terms. For example, the
`xorg.conf` file, commonly used to configure an XWindows display, is
technically a "settings" file, but it is not "preferences". However, for
end users it's perfectly permissible to use the word "Settings" in menus
and navigation elements since that is the term most commonly used in
software today.

## Open Issues

### Syncing with non-resources

Some important settings are not stored in resources: one of the most
common things that users will want to preserve is the window position
and size, which exist on the window entity. It's not possible, under my
design, to store arbitrary entities as preferences, so in order for the
window properties to be saved they will have to be copied to a resource
before being serialized. We probably don't want to be continually
copying the window size every time the window is dragged or moved, so
we'll need some way to know when serialization is about to happen. I'm
thinking that possibly some global event could be triggered just before
serialization, and the handlers could use this event to make last-minute
patches to resources.

## Saving If Changed

Because saving involves i/o, we want to only save when preferences have
actually changed. This involves two discrete checks:

* Whether a save operation needs to be done at all
* Which files need to be saved

The reason for these two steps is that even checking which files need to
be saved is non-trivial and probably should not be done every frame.

Rather than check the `is_changed()` field of every preference resource
every frame, the code currently relies on the user to issue an explicit
`Command` whenever they change a preferences property. This gets
especially tricky if the settings to be saved aren't actually in a
resource, like the aforementioned window position.

There are two forms of the command: `SavePreferences` and
`SavePreferencesSync`. The former, which uses an i/o task, is the
preferred approach, unless the app is about to exit, in which case the
sync version is preferred.

Once we know that a save will take place, a second pass can be used to
check the timestamp on every resource: if any resource has a tick value
later than the last time the file was either loaded or saved, then we
know that file is out of date.

Also some properties can change at high frequency - for example,
dragging the master volume slider changes the volume every frame. For
this reason, we will generally want to put in a delay / debounce logic
to batch updated together (not present in this PR). However, this delay
means that if the user adjusts the setting and then immediately
terminates the app, the setting won't be recorded. (There is no chance
of the file being corrupted, as it uses standard practices for ensuring
file integrity.)

Unfortunately, on some platforms, depending on how the user chooses to
quit (Command-Q on Mac) there's no opportunity to listen for the
`AppExit` event. For this reason, it's best to use a "belt and
suspenders" approach which listens for both `AppExit` and autosave timer
events.

Fixes #23172
Fixes #13311

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-03-10 20:29:09 +00:00
Jan Hohenheim 6ab2b07b90 Make it easier to opt out of bevy_audio (#23126)
# Objective

- bevy_seedling is incompatible with `bevy_audio`
- all our profile features (`3d`, `2d`, `ui`) enable the `audio`
collection feature
- That means that a seedling user needs to do this to land at the
current `default`:
```toml
[dependencies]
bevy = { version = "0.18.0", default-features = false, features = [
  # 2d
  "2d_bevy_render",
  "default_app",
  "picking",
  "scene",

  # 3d
  "3d_bevy_render",

  # ui
  "ui_api",
  "ui_bevy_render",

  # default_platform
  "android-game-activity",
  "bevy_gilrs",
  "bevy_winit",
  "default_font",
  "multi_threaded",
  "std",
  "sysinfo_plugin",
  "wayland",
  "webgl2",
  "x11",
] }
```

## Solution

- Disable the `audio` collection features for all profile features and
instead enable it by default
- The new seedling config now looks like this:
```toml
[dependencies]
bevy = { version = "0.18.0", default-features = false, features = [
  "2d",
  "3d",
  "ui",
] }
```

## Testing

- None, CI should take care of this
2026-02-28 17:10:56 +00:00
Alice Cecile 06a444ac65 Remove experimental designation from bevy_ui_widgets feature flag (#22934)
# Objective

`bevy_ui_widgets is still incomplete and unstable, but the utility of
the `experimental` designation is questionable:

1. Running examples with required non-default features suck. This is
frustrating for UI examples, and hampers adoption in our other examples
even when real UI-based controls would be more elegant.
2. These widgets have proven useful to end users in practice, even in
0.19.
3. These widgets have seen a number of small bug fixes and improvements
since their initial release.
4. It's not clear that this label is effective for slowing adoption, or
if slowing adoption is currently desirable. Users don't have a ton of
other great options: writing their own widgets will waste work *and*
still need to be rewritten with BSN.
5. Bevy as a whole is still quite experimental. Unlike e.g. ghost nodes,
there's no indication that we are considering wholly reverting these
features.

## Solution

Amended based on review feedback:

> The `experimental_ui_widgets` feature have been renamed to
`ui_widgets`.
>
> The `ui_widgets` feature has been added to the `ui` feature collection
(and thus `bevy`'s default features) for ease of use.

Previous solution, from the original migration guide:

> The `experimental_ui_widgets` and `experimental_bevy_feathers`
features have been renamed to `ui_widgets` and `bevy_feathers`
respectively.
>
> The `ui_widgets` feature has been added to the `ui` feature collection
(and thus `bevy`'s default features) for ease of use.
> The `bevy_feathers` feature remains off by default: it is primarily
intended for use in dev tools, and should typically not be included in
shipped end-user applications. As a result, it needs to be easy to
enable and disable conditionally. This would be very challenging if it
were a default feature or in a popular feature collection.
> 
> These crates remain immature, and subject to heavy breaking changes,
even relative to Bevy's pre-1.0 standards.
> However, they are useful enough to see wider adoption, and this
changes substantially improves the user experience when setting up new
projects and running Bevy examples.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-02-18 21:23:39 +00:00
atlv bb60d126c7 add bevy_picking back (#22990)
# Objective

- #22933 removed the `bevy_picking` feature because it had the same
description as `picking` yet a different purpose. I believe this
different purpose is worth preserving and the fix is to document them
more adequately instead. The rest of the PR was good, i agree with
making it not enable `bevy_input_focus` when its enabled. Furthermore, I
would be in favor of a `picking_input_focus` feature.

## Solution

- Restore `bevy_picking` feature
- Adjust docs

## Testing

- ci

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-02-17 19:28:53 +00:00
Alice Cecile 052c272f35 Condense bevy_picking (input focus) feature into bevy_ui_picking feature (#22933)
# Objective

The feature flags "bevy_picking" and "picking" have the same description
despite fulfilling different goals. This is very confusing!

Fixes #22931.

The status quo before this PR.

> - picking is a feature collection in bevy, which enables
["bevy_picking", "mesh_picking", "sprite_picking", "ui_picking"].
> - the ui feature collection enables picking itself
> - bevy_picking is defined in bevy, which defers to
["bevy_internal/bevy_picking"]
> - in bevy_internal, this toggles bevy_picking = ["dep:bevy_picking",
"bevy_input_focus?/bevy_picking"]
> - this then toggles the bevy_picking dependency (apparently that works
as if it were a feature?) in bevy_input_focus
> - which is ultimately used to enable mouse / virtual cursor based
input focus selection
> - @viridia is concerned about making this mandatory because of worries
about observer overhead

## Solution

Condense bevy_picking at the bevy_internal level into bevy_ui_picking.
There's no way someone wants general UI picking but not input focus
picking. This fixes the redundancy, and groups functionality more
reasonably, while still making it possible to avoid UI picking as a
whole off if you're concerned for whatever reason.

Users who want even more granularity than that can of course compose the
various Bevy crates however they please.

## Alternative

1. Keep this feature around, renaming it to `input_focus_picking`.
2. Enable that feature inside of `ui_picking`.

This adds another niche feature flag at the top level, but makes it
easier for users who want to use `bevy_input_focus` without `bevy_ui`. I
have never met such a user, but maybe they exist!
2026-02-17 00:45:41 +00:00
ickshonpe 48ec375a3a bevy_text parley migration (#22879)
# Objective

Migrate `bevy_text` from Cosmic Text to Parley.

Closes #21940. Fixes #21767, fixes #21768. Part of #21676.

## Solution

I came down with the flu yesterday when I was about halfway done. I
managed to work through it and drag this to a sort of finished state
anyway but there's probably some weird decisions because I haven't been
entirely coherent.

Most of the significant changes are to the pipeline module. There is
also a new `parley_context` module.
`FontAtlasKey` has a bunch of new fields, I can't remember why there's
both an `id` and a `index` now.

## Testing

Weird bug in `testbed_2d`:

<img width="893" height="168" alt="symbols"
src="https://github.com/user-attachments/assets/29288e16-9c3a-4aee-9ec5-638179b0bac0"
/>

Most other things seem to work the same as main, ymmv.

## Showcase

`testbed_2d`'s text scene on main with Cosmic Text:

<img width="1924" height="1127" alt="main-text2d-layout"
src="https://github.com/user-attachments/assets/55d0c7b7-7517-4a50-b76f-2a24e7cdc28f"
/>

`testbed_2d`'s text scene on this PR with Parley:

<img width="1924" height="1127" alt="testbed-2d-text"
src="https://github.com/user-attachments/assets/c87265fa-6e5f-4c03-aa5e-730f09f83ca3"
/>

`testbed_ui`'s text scene on main with Cosmic Text:

<img width="1924" height="1127" alt="testbed-ui-main"
src="https://github.com/user-attachments/assets/ce764891-3ca6-4c63-83af-8fe285a4a229"
/>

`testbed_ui`'s text scene on this PR with Parley:

<img width="1924" height="1127" alt="testbed_ui_parley"
src="https://github.com/user-attachments/assets/45bcbfe7-1ce4-44f7-bad7-7fa8f46c66ce"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-02-11 05:52:47 +00:00
atlv f3cb87b8fc render buffer debug label type prepopulation (#22698)
# Objective

- The vast majority of our buffers are unlabelled. This makes debugging
wgpu errors really annoying, cus they lack context.

## Solution

- We have type information, and buffers predominantly are custom struct
types, and the few cases in which they arent they seem to be manually
named anyways. Let's exploit the type info to populate the buffer names
under a debug gate.

## Testing

- ran occlusion_culling example with and without the debug feature, it
currently crashes due to a wgpu 28 change.

## Showcase

Before:
```
Caused by:
  In a CommandEncoder
    In a dispatch command, indirect:true
      Attempted to use Buffer with '' label with conflicting usages. Current usage BufferUses(STORAGE_READ_WRITE) and new usage BufferUses(INDIRECT). BufferUses(STORAGE_READ_WRITE) is an exclusive usage and cannot be used with any other usages within the usage scope (renderpass or compute dispatch).
```

After:
```
Caused by:
  In a CommandEncoder
    In a dispatch command, indirect:true
      Attempted to use Buffer with 'bevy_render::render_resource::buffer_vec::RawBufferVec<bevy_render::batching::gpu_preprocessing::LatePreprocessWorkItemIndirectParameters>' label with conflicting usages. Current usage BufferUses(STORAGE_READ_WRITE) and new usage BufferUses(INDIRECT). BufferUses(STORAGE_READ_WRITE) is an exclusive usage and cannot be used with any other usages within the usage scope (renderpass or compute dispatch).
```

Note that now we know 1. its a `RawBufferVec`, 2. of
`LatePreprocessWorkItemIndirectParameters`. This lets us greatly narrow
the scope of the search for an offender.



Note: this is the evolution of several different attempts at improving
debug info. First attempt was with `#[track_caller]`, but that doesn't
work in const contexts because Location isnt allowed there. Second
attempt was to prepopulate type name info in constructors, but
`std::any::type_name()` returns a `&'static str`, and label is
`Option<String>`, and `.into()` and `.to_string()` are both not const
because `String` is heap allocated. Finally, i moved it to the buffer
creation site, and then extracted it into a generic function to
deduplicate.
2026-01-26 00:05:35 +00:00
Terra 51fc15b1a9 Fix doc for cargo feature profiles doc (#22566)
# Objective

- Bevy 0.17 does not have a feature named `2d`. It was introduced in
0.18.
- Feel free to change the PR title if it's ambiguous or close the PR if
I'm wrong.

## Solution

- Update to 0.18.

## Testing
- None
2026-01-17 12:38:27 +00:00
Martín Maita f478cb3e5b Detailed Feature List for Collections (#22506)
# Objective

- Make it easier to understand what each feature collection is enabling.

## Solution

- Added the list of features that a collection will enable on its
description. These are located in the "cargo_features" templated doc
page.

## Testing

- Running the templated page generator for "features" and checking the
resulting markdown.

---

## Showcase

<img width="996" height="373" alt="image"
src="https://github.com/user-attachments/assets/9b31de60-ef33-4291-bd5f-2d1583467447"
/>
2026-01-14 18:25:09 +00:00
atlv ff376dea7c bevy_material (#22426)
# Objective

- extract material infrastructure to be usable for scene description
without a renderer
- rework of #21543 on top of #22408, you can view a clean diff here:
https://github.com/tychedelia/bevy/compare/type-erase-more-materials...atlv24:ad/material2?expand=1
- this is the culmination of numerous crate splits and refactors leading
up to this point, and the another step towards shared 2d and 3d
rendering infrastructure deduplication.

## Solution

- new crate bevy_material with MaterialProperties struct that lets one
define when a material draws, how it behaves, what shaders it uses,
specialization functions, and bind group layouts expected.

## Testing

---------

Co-authored-by: charlotte 🌸 <charlotte.c.mcelwain@gmail.com>
Co-authored-by: Daniel Skates <zeophlite@gmail.com>
2026-01-13 21:41:06 +00:00
Hennadii Chernyshchyk 40c0edbb0b Put input sources for bevy_input under features (#21447)
# Objective

`bevy_input` provides primitives for all kinds of input. But on consoles
you usually don't have things like touch. On more obscure platforms,
like GBA, only gamepad input is needed.

## Solution

To avoid including extra stuff, I put each source under a feature. I
didn't enable them by default to avoid typing

```
default-features = false, features = [
    "std",
    "bevy_reflect",
    "bevy_ecs/async_executor",
    "smol_str"
]
```

in all places that include `bevy_input`. Instead, I just enabled the
used input sources in `bevy_window` and `bevy_gilrs`. This way, when a
crate that provides hardware support for a specific input source is not
used, the corresponding feature in `bevy_input` also won't be enabled.

For GBA this reduced the binary size for the `game` example from 1.6M to
1.4M.

## Considered alternatives

I also considered doing something like this:

```rust
pub struct InputPlugin {
    pub keyboard: bool,
    pub mouse: bool,
    pub gamepad: bool,
    pub touch: bool,
}
```

But this doesn't eliminate extra code even with LTO enabled and might be
confusing for users, since toggling these values could cause a crash due
to a missing resource when a crate like `bevy_window` expects it.
2025-12-16 20:05:29 +00:00
Daniel Skates f9d59f8206 Fix cargo features lint (#22008)
# Objective

`markdownlint` fails on `docs/cargo_features.md` as it doesn't like the
space before the pipe at the end of this line

## Solution

- Add a `.`

## Testing

- CI
2025-12-02 17:03:54 +00:00
syszery 9a9817bba1 Update PanCam and FreeCam to use full term Camera (#21592)
# Objective

This PR fixes #21569, which proposes renaming the newly introduced
camera controller modules `FreeCam` and `PanCam` to use the full term
`Camera`.

## Solution

* Renamed the `PanCam` controller, `PanCamPlugin`, and related methods
to use the full term `Camera` instead of the abbreviation `Cam`.
* Renamed the module from `pan_cam` to `pan_camera` for consistency with
naming conventions.
* Updated the example `pan_camera_controller` and adjusted usage of the
renamed controller and plugin.
* Updated documentation and release notes accordingly.


## Follow-up Work

I see two options from here:

1. **Use this PR as a reference** for renaming `FreeCam`. The process is
similar and could be a great first issue for someone looking to
contribute to the new camera modules or Bevy in general. Most of the
changes follow the same pattern, although `FreeCam` has more examples
that need updating. One could find them using `grep` (e.g., `grep
FreeCam`) or by reviewing the diff from the PR that introduced
`FreeCam`: #20215

2. **I can continue and update this PR** to also handle the `FreeCam`
renaming, if you'd prefer to resolve the entire issue in one go.

---------

Co-authored-by: syszery <syszery@users.noreply.github.com>
2025-10-20 21:49:37 +00:00
WaterWhisperer a48d6cd336 Rename bevy_reflect's documentation feature to reflect_documentation (#21577)
# Objective

Fixes #14309 

## Solution

Renamed the `bevy_reflect` feature from `documentation` to
`reflect_documentation` to follow the naming convention where features
are prefixed with their module name.

## Changes

- Renamed feature `documentation` to `reflect_documentation` in:
  - `bevy_reflect/Cargo.toml`
  - `bevy_reflect/derive/Cargo.toml`
  - `bevy_internal/Cargo.toml`
- Updated all conditional compilation attributes from `#[cfg(feature =
"documentation")]` to `#[cfg(feature = "reflect_documentation")]`
- Updated example documentation in `reflect_docs.rs`

## Testing

<img width="1414" height="688" alt="截图 2025-10-17 18-52-14"
src="https://github.com/user-attachments/assets/461d827a-c958-4c0d-862d-aae25598f2f7"
/>
2025-10-19 17:30:19 +00:00
syszery 81d9c88950 feat(pan-cam): add scaffolding for 2D pan camera controller (#21520)
# Objective

Implements scaffolding for a 2D pan camera controller.

Fixes #21468 


## Solution

- Introduced a `PanCam` component with settings for panning, zooming,
and rotation via keyboard input, following the design of the existing
`FreeCam`.
- Added a `PanCamPlugin` to register the controller system.
- Implemented keyboard-based panning and rotation.


## TODOs

- Movement is currently world-axis aligned. 
  - TODO: Consider movement relative to camera rotation.
- Zooming support is scaffolded with config fields but not yet
implemented.


## Testing

Unfortunately, I was unable to fully test this implementation due to
issues running graphical output with GPU acceleration under WSL.
As a result, zoom behavior and rotation effects remain TODOs, and the
whole code could not be fully verified.

Once I resolve the GPU passthrough issues, I plan to complete and test
the remaining features (with a more meaningful example).

---

I'm happy to hear any suggestions or feedback in the meantime!

---------

Co-authored-by: syszery <syszery@users.noreply.github.com>
Co-authored-by: Janis <130913856+janis-bhm@users.noreply.github.com>
2025-10-16 21:32:24 +00:00
Carter Anderson 1e7f4931aa Fix typo in features.md.tpl (#21546)
# Objective

Fix typo

## Solution

Fix typo
2025-10-14 22:24:42 +00:00
atlv b81dabe433 bevy_gizmos_render (#21536)
# Objective

- make gizmos render agnostic

## Solution

- split crate

## Testing

- ci and a few examples

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-10-14 21:36:36 +00:00
Carter Anderson f3ec3c070e Cargo Feature Collections (#21472)
## Objective

Users of the `bevy` crate currently live one of two lifestyles:

1. Use all of Bevy's default features, potentially compiling many
features you don't need or don't want. If there is a feature you _cannot
have_ in your app, you must move on to option (2)
2. Disable Bevy's default features, and compose the complete list of
features yourself.

Living in the world of (2) is an exercise in frustration, as the list of
required features to accomplish a given task changes regularly across
releases as we add and change features. This is an _expert level_ task
that requires intimate knowledge of engine internals to get right. Even
I, Bevy's lead developer, would struggle here. To the point that I would
never voluntarily choose to disable Bevy's default features.

Most games/apps are 2D-only, 3D-only, or UI-only and don't require the
full set of features. We cannot currently in good conscience recommend
that those developers live in the "no default features" world. That is a
fast track to pain, suffering, and perhaps a quick exit from the Bevy
ecosystem.

The same problem exists for developers that want to build their own Bevy
renderer or replace Bevy UI with their own framework. Once again, we
_cannot_ recommend that those developers manage every Bevy feature
themselves.

Fixes: #21369
Alternative to: #20741 #21236

## Solution

Define a "standalone" set of features that enable Bevy developers to
disable default features, then opt in to the funtionality they want. The
"default" `bevy` feature set is now just:

```toml
default = ["2d", "3d", "ui"]
```

This enables developers to select only the features they need. For
example, a UI-only app would look like this:

```toml
bevy = { version = "0.17", default-features = false, features = [ "ui" ] }
```

"2d", "3d", and "ui" each contain the "full" Bevy experience for that
domain. This also includes:
- `default_platform`: the default "platform support" features (see docs)
- `default_app`: the default "app framework" features (see docs)

For developers that do not want the default bevy render / platform / app
functionality, this breaks down further into:

- `common_api`: common / core backend-less user-facing Bevy render api
- `2d_api`: common / core backend-less user-facing Bevy 2d api
- `3d_api`: common / core backend-less user-facing Bevy 3d api
- `ui_api`: common / core backend-less user-facing Bevy ui api

(and many others)

I've also added the `dev` feature to this PR, which enables the
recommended "dev only" features like dynamic linking, asset watching /
hot reloading, and dev / debug tools. Including dynamic linking is a bit
controversial here given that it doesn't work everywhere. But I'd like
to aggressively push people into the dynamic linking workflow wherever
possible, as developing without it is signficantly worse. And removing a
single `dev` feature is a much simpler release workflow.

---------

Co-authored-by: atlv <email@atlasdostal.com>
2025-10-10 02:42:54 +00:00
atlv 44b904ed05 Rename bevy_mesh_picking_backend to mesh_picking (#21436)
# Objective

- Only prefix features bevy_ if they correspond to a crate
- Another step towards #20867

## Solution

- rename it

## Testing

- ci
2025-10-07 23:49:49 +00:00
Alice Cecile 66e8232412 Add bevy_camera_controllers crate and move freecam implementation into it (#20215)
# Objective

Moving the camera around is really important to validate that our scenes
are rendered correctly.

Bevy engine devs currently do this via a fairly cursed "library example"
which includes a basic freecam controller (which is technically distinct
from a flycam apparently). This has three problems:

1. Oh god why are we taking pseudo-dependencies on other examples.
2. Something like this would be useful for debugging for users.
3. Something like this would be useful for the editor and other tooling.

## Solution

Create a new `bevy_camera_controllers` crate, and move the existing
freecam implementation into it, nearly verbatim.

This cleans up some ugly tech debt in how we do this, makes it easier to
add a camera controller to other examples, and also gives us a scaffold
for future camera controllers.

This PR has been marked `X-Blessed`, as I went over this plan with @cart
in a [meeting on
2025-06-23](https://discord.com/channels/691052431525675048/692572690833473578/1386847828923519038),
and we both agreed that this was the right first step.

## Testing

I've tested the examples that rely on this camera controller: they work
just like before.

## Notes for reviewers

- I don't intend to land this in Bevy 0.17: the existing example code is
not high enough quality for me to be happy shipping this
- we're also soft feature-frozen; I was just in the mood to do this
today
- this PR has some minimal cleanup: just enough naming and docs work to
make this code not an active liability. Any more will risk derailing
this PR and making it harder to review
- I've opted to expose top-level feature flags for the various camera
controllers. This is a bit noisy, but it was the only sensible way I
could see to both have "no camera controllers by default" and "still
easy to use these controllers in examples"
- this will not be the only camera controller in this crate, or the Bevy
Editor
- this is not the place to discuss "what should the default camera
controller for the Bevy Editor be"
- if you think this crate, or this particular move is the wrong strategy
for some other reason though, please do speak up :)
- my personal (unblessed) hope is that we continue to add camera
controllers to this crate as needed for various first-party tooling. I
will probably largely push-back on adding camera controllers that we do
not actively use to this crate, since I don't think they make great
libraries in general (much better to copy-paste)

## TODO

- [x] add release note. I'm waiting until after Bevy 0.17 ships to do
this
- [x] update the examples/README.md file. I was lazy and didn't want to
constantly resolve merge conflicts on that while this PR sits
- [x] change to singular crate name

## Future work

- split apart the giant camera controller component
- make keybinding better, either with or without a real input manager
solution
- split apart the system to make it more modular
- make the system handle fixed timesteps better
- use the camera controller in more examples for debugging
- add more camera controllers!

---------

Co-authored-by: atlv <email@atlasdostal.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2025-10-07 19:39:17 +00:00
atlv 14756e100c Rename bevy_ui_picking_backend to ui_picking (#21435)
# Objective

- Only prefix features bevy_ if they correspond to a crate
- Another step towards #20867

## Solution

- rename it

## Testing

- ci
2025-10-07 19:06:20 +00:00
atlv f73e3bc11e Add generator command to features md file (#21434)
# Objective

- i always forget what it is

## Solution

- put it at the top of the file (another md template does this - not
new)

## Testing

- umm
2025-10-07 18:07:24 +00:00
atlv 9fe6234b8e rename bevy_sprite_picking_backend to sprite_picking (#21437)
# Objective

- Only prefix features bevy_ if they correspond to a crate
- Another step towards #20867

## Solution

- rename it

## Testing

- ci
2025-10-07 16:20:28 +00:00
atlv 40df90cf73 Make bevy_mikktspace optional (#21390)
# Objective

- allow users to cut unneeded deps

## Solution

- feature gate

## Testing

- clearcoat example uses generated tangents, still works.
2025-10-06 22:05:51 +00:00
atlv b7a90ae653 make bevy_mesh optional for bevy_animate (#20742)
# Objective

- make bevy_mesh optional for bevy_animate as mentioned in
https://github.com/bevyengine/bevy/pull/20714#issuecomment-3218581329

## Solution

- copy paste the morph weights stuff out into a module, gate it, then
add the optional dep
2025-10-06 21:04:14 +00:00
atlv ff7837ef38 Rename animation to gltf_animation (#21388)
# Objective

- Step towards #20867

## Solution

- Do a rename

## Testing

- Ran some examples
2025-10-06 20:54:26 +00:00
atlv c23377228c bevy_mesh optional morph (#21389)
# Objective

- make morph support optional on bevy_mesh
- unblock #20742
- another step towards #20867

## Solution

- feature

## Testing

- morph targets example works
2025-10-06 18:53:27 +00:00
Alice Cecile d38a1ec982 Mark bevy_ui_widgets as experimental for now (#20972)
# Objective

- These are still going to undergo *extensive* change: users should be
aware of what they're getting into.
- Fixes #20957.

## Solution

- [x] rename the feature
- [x] remove from our default features
- [x] add warning to crate docs
- [x] add warning to release notes
- [x] add warnings to examples

## Testing

I've run both the `standard_widgets` and `standard_widgets_observers`
examples succesfully.
2025-09-12 16:03:03 +00:00
Talin f07c12570a Renamed bevy_core_widgets to bevy_ui_widgets. (#20944)
Renamed `CoreXXX` components to `XXXBehavior`.
Fixes: #20664

@alice-i-cecile @cart
2025-09-10 23:25:51 +00:00
atlv f6b77e4e49 bevy_post_process (#20778)
# Objective

Split out post process effects from bevy_core_pipeline because they are
not core pipelines.

## Solution

@IceSentry proposed something like this, not sure if the split is
exactly as he envisioned but this seems reasonable to me.

The goal is to move absolutely everything possible out of
bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation.

Future PRs may attempt to move more little bits out.

## Testing
2025-09-05 04:26:08 +00:00
atlv ac380673b7 rename bevy_anti_aliasing to bevy_anti_alias (#20857)
# Objective

- rename to have less suffixing
- match future bevy_post_process crate

## Solution

- remove ing

## Testing

- run anti_aliasing example (not renamed, can rename this too if
desired)
2025-09-04 21:11:20 +00:00
atlv cbf989c9da WebAssets without filtering (#20628)
# Objective

- adopt #17889
- Fixes #5061

---------

Co-authored-by: Peter Hayman <peteyhayman@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: jf908 <jf908@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: jf908 <josh@thefindons.com>
2025-08-29 03:23:11 +00:00
atlv c24491e449 Clean up root toml features (#20752)
# Objective

- We currently specify transitive feature dependencies in two places:
bevy and bevy_internal Cargo.tomls
- This means they get out of sync often, accumulate unnecessary
duplication, and sometimes forget certain transitive deps.

## Solution

- Standardize on bevy_internal. Why: this makes it impossible to use it
incorrectly if you depend on bevy_internal directly for some reason. If
we standardized on bevy Cargo.toml holding these, it would mean that
they could be bypassed by depending on bevy_internal. Not sure why
someone would do that, but this feels right.
- Move the few transitive feature dependency specifications that are
still in bevy to bevy_internal
- clean up a lot of duplicates
- add a few missing dependencies
- add top level bevy_mesh, bevy_camera, bevy_light, and bevy_shader
features.


## Testing

- this stuff is hard to test automatically or comprehensively. #20741
might make it easy to have a no-render test suite we can maintain
coverage for, but other than that its just manual verification.
2025-08-26 23:21:52 +00:00
Jan Hohenheim bf4f0e5e1d Rebrand glTF coordinate conversion to an alternative strategy that is biased towards glTF models (#20131)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/20121
- Reverts https://github.com/bevyengine/bevy/pull/19816

Per long discussion with @superdump (see
https://github.com/bevyengine/bevy/issues/19686#issuecomment-3069180465),
the new coordinate loading system is still wrong, just now biased in
favor of having correct forward semantics for models instead of cameras.
Which is still what I need, but it should not be the new default, as we
may well change `Transform::forward` instead.

## Solution

Since changing forward semantics is a bigger change, let's rebrand the
coordinate conversion code and keep it opt-in so that users that don't
use glTF cameras get correct semantics in the meantime.

## Testing

- Ran 3D examples and Blender test scenes.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2025-08-16 00:57:06 +00:00
Daniel Skates 9ee0aaafc5 Split out sprite rendering (#20587)
# Objective

- Split out `bevy_sprite_render` from `bevy_sprite` .

## Solution

- Do the thing

## Testing

- CI
- `cargo run --example sprite`
2025-08-15 22:41:05 +00:00
JMS55 1bb17a94dd Initial DLSS implementation (#19864)
# Objective
- Closes https://github.com/bevyengine/bevy/issues/8420

## Solution
- Initial implementation of DLSS upscaling, via
https://github.com/bevyengine/dlss_wgpu.
- Future PRs will work more on transparency, exposure, working with
custom viewports, fixing inevitable resolution override bugs, etc.
- DLSS framegen is not planned, but ray-reconstruction is for solari.
- FSR3/4, XeSS2, and MetalFX temporal upscaling should be easy to add
now if a future contributor wants to. In the future we could have an
auto-temporal AA component that handles DLSS/FSR/XeSS/MetalFX/TAA
fallbacks automatically.

## Testing

- Did you test these changes? If so, how?
  - Run the anti_aliasing example
- Are there any parts that need more testing?
- Different types of scene content and rendering effects to make sure
they work with DLSS/upscaling
  - Reviewing dlss_wgpu code

---

## Showcase

![bafkreib4u2hc7kgru7n6ujh6tjq5aydfcz7m7lfleexvfa6fdixegveaee](https://github.com/user-attachments/assets/891b32af-54d5-41da-81d8-d63fc085afec)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2025-08-15 21:07:25 +00:00
Carter Anderson 7a869253d1 Opt-in raw vulkan initialization with hooks (#20565)
# Objective

Currently registering additional required Vulkan features requires
either hard-coding them into `bevy_render` (see the current [DLSS
proposal](https://github.com/bevyengine/bevy/pull/19864)), or forcing
the plugin to take full manual control over wgpu initialization. Neither
is an acceptable or scalable option for a modular engine like Bevy.

## Solution

* Add a new `raw_vulkan_init` Cargo feature, that when enabled switches
to wgpu's raw Vulkan init path, which accepts callbacks that allow
checking and requiring additional Vulkan features.
* Add a new `WgpuRawVulkanInitSettings` resource, which provides wgpu
Vulkan Instance and Device init callbacks, which can be used to detect
and register vulkan features.
* These callbacks can register arbitrary features in the new
`AdditionalVulkanFeatures` resource, which is inserted into the
RenderApp at the same time that the RenderDevice is.

This enables plugins to register initialization callbacks, which must
happen _before_ RenderPlugin. They can then feed off of
`AdditionalVulkanFeatures`, after the renderer is initialized, to detect
if a given feature is supported.

Due to the current lifecycles, this is best accomplished with either:
* A separate "init plugin" that is registered before RenderPlugin, and a
"logic plugin" that does everything else. This should be used if the
plugin logic needs `Plugin::build()` access to render device state,
which needs to be registered _after_ RenderPlugin to have access. The
proposed DLSS feature needs this pattern.
* A single "init plugin" that is registered before RenderPlugin and does
everything. Use this pattern if you can as it is simpler.

With deferred plugin init, we could remove the need for this split.

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2025-08-15 02:56:48 +00:00