https://github.com/bevyengine/bevy/pull/22460 broke the material change
detection trigger in the large scenes mip map generator plugin.
## Testing
Ran the test_image example in mipmap_generator and the bistro scene and
textures with mip maps were shown as expected after this fix.
# Objective
`bsn!` currently requires surrounding macros in "field value position"
with `{}`:
```rust
bsn! {
Foo { value: {vec![ 100, 200 ]} }
}
```
This is annoying!
## Solution
Support macros in field-value-position:
```rust
bsn! {
Foo { value: vec![ 100, 200 ] }
}
```
## Testing
- Added a test that checks that this works
- Ported bsn! examples to use this
# Objective
- bevy_city needed a way to merge all the `Mesh3d` from a `WorldAsset`.
Instead of keeping that function hidden inside bevy_city we can make it
public
## Solution
- Add `world_asset_helpers` to `bevy_dev_tools`. It's in
`bevy_dev_tools` because it depends on multiple different parts of bevy
and that's the only crate that users can use that already depends on a
lot of things.
- Add `marge_all_mesh_3d()` to `world_asset_helpers`
- Update bevy_city to use that helper
## Testing
- I ran bevy_city and the meshes were merged like they should
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Changes discussed with cart:
- `:` will not be called "inheritance" anymore, but instead "cacheable"
(name not final)
- the Template patching prefix changes `@` -> `~`
- the SceneComponent prefix changes `:` -> `@`
- the `:` prefix is allowed in front of `@SceneComponent` as well,
marking it as being cached
>> me: do we forbid caching of functions which take an argument?
> cart: We should forbid it until we support it, and I don't plan on
supporting this in the short term, as it adds new controversial design
aspects to the system (building a mapping from parameters to cached
scenes, ensuring the parameters are all hashable, etc).
Link to the discord thread, specifically my [recap
message](https://discord.com/channels/691052431525675048/1264881140007702558/1506422311056576702).
The exact reasoning is in the linked discord discussion, but the tldr
is:
"Inheritance" as a term for the ":" syntax didn't really fit what bsn
was doing, since scenes without `:` produce the same result. All `:` is,
is a way to say "cache this pls" with the design of bsn imposing the
limitation that only the first scene can be cached
That was all fine, except for one case: Disambiguating SceneComponents
from normal components. So if we redefine `:` to just mean "caching" we
needed to untangle it from SceneComponents. That means disambiguating
SceneComponents needed a different syntax, and the decision ended up
being to take the @ prefix from the *much* less common `@Template`
usecase, since `SceneComponent {@prop: val}` already used @ as well and
introduce a new prefix to replace `@Template` instead, replacing it with
`~Template`.
## Solution
Implement these changes in macros.
Notably, this *still* doesn't implement/enable caching right now.
Most docs are updated, except for the big blocks in
`bevy_scene/src/lib.rs` and `bevy_scene/macros/src/lib.rs` since i've
been working on reworking those on another branch and didn't want to
duplicate whats already been a lot of work and likely to be a bunch more
## Testing
- [x] `bevy_scene` tests passing
- [x] `cargo check --workspace` and `cargo check --workspace --examples`
passing
Since this PR does not yet enable caching, I think passing the current
tests should be enough.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Use our "shorthand" conventions for `Val` everywhere in feathers code /
usage
This also:
- adds a `VariantDefaults` derive to `Visibility` to make it usable
without `template_value`
- adds `From<Val>` to BorderRadius to support `px(10)` assignments
instead of `BorderRadius::all(px(10))`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
This is my first bevy PR, please tell me if I'm doing anything wrong.
# Objective
Contribute to #22695.
Showcase the preferred coding style in all examples.
## Solution
Replace Val:: constructors with the more ergonomic shorthand functions.
Change their float literals to integer literals if they are integral.
Exceptions:
- const contexts (the shorthand functions are not const)
- inside bsn! macros (these are new and presumably know what they are
doing)
- in testbed (these are not really examples)
- Val::ZERO (no helper function)
## Testing
Ran the changed examples before and after, except the library example
`widgets` where I just checked that it still builds.
## Context
There was PR #22765 that fixed the same thing but only in the UI
examples.
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
# 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!
# Objective
It is essentially a Bevy rite of passage to define a `Player` component
and then ask "ok when I spawn `Player`, how do I spawn all of the other
entities / components / scenes it needs to function with it?".
In Bevy, components are the "unit of behavior". The presence of a
component indicates that the entity should behave a certain way. Scenes
are _inextricable_ from behaviors, yet currently there is no way to tie
Components (bevy's unit of behavior) to scenes. _This is a fundamental
gap in the Bevy data model_. It is a problem that developers expect
their engine to solve for them.
It is high time that we had an official solution to this problem. BSN
was built to be that solution, and it is now time to do the last-mile
work to facilitate the `Component <-> Scene` relationship
## Solution
It is now possible to define "scene components", where `SceneComponent:
Component`:
```rust
#[derive(SceneComponent, Default, Clone)]
struct Player {
score: usize
}
impl Player {
fn scene() -> impl Scene {
bsn! {
Transform { translation: Vec3 { x: 10. } }
Children [
LeftHand,
RightHand,
]
}
}
}
```
This enables inheriting from the Player component as a scene:
```rust
world.spawn_scene(bsn! {
:Player { score: 0 }
})
```
After the inherited `Player` scene component is spawned, the _entire_
scene is available. This means that you can `Query<&Player>` in your ECS
systems, and _trust_ that the entire scene is also present.
### Inheritance Syntax vs Patch Syntax
Notice that this uses inheritance syntax in BSN (`:`), rather than
normal "component patch" syntax (ex: `bsn! { Player { score: 0 } }`.
Semantically these are different things:
- Scene inheritance syntax: constructs the full scene and inherits from
it
- Component patch syntax: _Just_ patches the component directly and
creates it if it doesn't exist. This will not do any scene inheritance.
You can still patch scene components this way as long as the scene
component is inherited somewhere "earlier" in the inheritance hierarchy.
Attempting to spawn a scene component on its own _without_ the scene
(ex: `commands.spawn(Player::default())`) will log an error, as Scene
Components should never exist without their scene.
### Custom Scene Functions
When deriving `SceneComponent`, it defaults to using `Self::scene` as
the "scene function". Scene functions can also be manually specified:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(player)]
struct Player {
score: usize
}
fn player() -> impl Scene {
bsn! { /* scene here */}
}
```
### Inherit BSN Asset Paths
Alternatively, a scene asset path can be specified:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene("player.bsn")]
struct Player {
score: usize
}
```
Once we port the glTF loader to BSN, this will also be supported:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene("player.gltf")]
struct Player {
score: usize
}
```
### Scene Props
Sometimes it is desirable to "parameterize" a scene: pass in values to
the scene which determine what the scene outputs are.
The answer to this in BSN is "scene props":
```rust
/// A UI widget that repeats "hello" text a given number of times.
#[derive(SceneComponent, Default, Clone)]
#[scene(HelloRepeaterProps)]
struct HelloRepeater;
#[derive(Default)]
struct HelloRepeaterProps {
repeat: usize,
}
impl HelloRepeater {
fn scene(props: HelloRepeaterProps) -> impl Scene {
let hellos = (0..props.repeat)
.map(|_| bsn!{ Text("hello") })
.collect::<Vec<_>>();
bsn! {
Node
Children [
{hellos}
]
}
}
}
world.spawn_scene(bsn! {
:HelloRepeater {
@repeat: 5
}
});
```
Notice the `@field` syntax, which specifies that a prop is being set
instead of a field. Props are evaluated "immediately" at the point of
inheritance where the scene is constructed. This means that they are not
"patchable".
You can set _both_ props and normal fields at the same time:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(WidgetProps)]
struct Widget {
value: usize
}
#[derive(Default)]
struct WidgetProps {
border: bool,
}
world.spawn_scene(bsn! {
:Widget {
@border: true,
value: 10,
}
});
```
Scene props can be used with templates:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(PlayerProps)]
struct Player;
#[derive(Default)]
struct PlayerProps {
head: AssetPath<'static>,
body: AssetPath<'static>,
}
impl Player {
fn scene(props: PlayerProps) -> impl Scene {
bsn! {
Transform
Visibility
Children [
(Head, Sprite { image: {props.head} }),
(Body, Sprite { image: {props.body} }),
]
}
}
}
world.spawn_scene(bsn! {
:Player {
@head: "big_head.png"
@body: "small_body.png"
}
});
```
### Scene Components are Template-able
```rust
#[derive(SceneComponent, FromTemplate)]
struct Player {
image: Handle<Image>,
}
impl Player {
fn scene() -> impl Scene {
bsn! { /* scene here */}
}
}
world.spawn_scene(bsn! {
:Player { image: "player.png" }
});
```
### The Scene Component is Always Added
Specifying the scene component manually in the scene function is not
necessary. It will be added automatically:
```rust
#[derive(SceneComponent, Default, Clone)]
struct Player {
score: usize
}
impl Player {
fn scene() -> impl Scene {
bsn! {
// No need to specify a Player component here.
// It is implied!
}
}
}
```
However you _can_ patch the scene component in the scene if you would
like. This comes in handy if you would like props to contribute to the
scene component's value:
```rust
impl Player {
fn scene(props: PlayerProps) -> impl Scene {
bsn! {
Player {
size_in_meters: {props.size_in_millimeters / 1000. }
}
}
}
}
```
### SceneComponent Trait
This is what SceneComponent looks like under the hood:
```rust
pub trait SceneConstructor: FromTemplate<Template: Default>
where
<Self::Template as Template>::Output: Component,
{
type Props: Default;
fn scene(props: Self::Props) -> impl Scene;
}
```
In general, developers should prefer `#[derive(SceneComponent)`, which
derives this trait automatically, ensures the Component is never spawned
without its scene, and automatically initializes the `Component` even if
it isn't specified explicitly in the user-defined scene function.
### Reusable Component Derive Logic
This PR moves the component derive logic into a new
`bevy_ecs_macro_logic` crate and refactors it to be reusable and
extendable.
This enables the `SceneComponent` derive to reuse and configure the
`Component` derive. I also took the liberty of porting the redundant
`Resource` derive logic to this system, as it follows the same pattern.
## PR Todo
- [ ] Port this PR description to docs on `Scene`.
## Whats Next
- Scene Component scene caching: It might make sense to cache
unparameterized scenes (like we do for scene assets) to cut down on
spawn costs. We could even have an opt-in parameterized scene cache (ex:
hash the props).
- Reactivity: It is important to note that props _are not reactive_.
They do not exist post-spawn (aka "at runtime") and they cannot be
changed. However they could easily be _part_ of a reactivity story:
- Props as components: insert props as components and re-run the scene
constructor when they are mutated
- Signal props: Reactive "signal" types could be passed down the init
hierarchy via props.
- Simpler "prop patching" codegen: currently for simplicity props reuse
the template-patching logic, but this introduces a few constraints and
complexities that are unnecessary. We should consider writing
specialized logic for them.
# Objective
As discussed in [this discord
thread](https://discord.com/channels/691052431525675048/1492688648360165406),
using the `Children` relation to append caption elements to feathers
widgets is dodgy.
## Solution
Make `caption` an explicit parameter for button, radio, and checkbox
widgets.
Also fixed some erroneous docs.
## Testing
Manual testing of feathers and bevy_city examples.
Note that there's no migration guide because this only affects the bsn
functions, which are new.
# Objective
- In the asset pack used for bevy_city the tires of all the cars are
separate meshes from the car body. In some of the cars even the doors
are also separate meshes.
- Since we don't animate these elements of the car we can trivially
combine all the meshes of each car scene into one single car mesh. This
helps a lot to keep performance manageable and eventually increase the
scale of bevy_city.
## Solution
- Wait for the assets to load and once they are loaded loop over all the
car scenes and combine their meshes. This is mainly possible because the
entire asset pack uses a single texture so we don't need a separate
material for each part of the mesh.
- To do this I also refactored a bit how each step happens when starting
the app. I also made sure that each step is reflected on the loading
screen.
- I also added a bit more docs
## Testing
- I ran bevy_city and confirmed that the tires are where they should be
relative to the mesh and that performance was better. I went from 90fps
to 112fps on my machine
---
## Showcase
https://github.com/user-attachments/assets/c2a10681-d148-4394-a3ca-fffe928fa09c
# Objective
**Anecdotal feedback:**
- no floating origin support for implementing large-scale worlds, forked
Bevy's atmosphere at
https://github.com/philpax/veldera/blob/main/crates/bevy_pbr_atmosphere_planet/NOTICE.md
- no custom up axis support, resorted to using a custom sky shader for
flight simulator with Z up coordinate system. Bevy's atmosphere appears
tilted at a 90 degree angle with no way of changing it.
## Solution
- Atmosphere component can be spawned stand-alone
- AtmosphereSettings remains on camera
- A closest-to-camera heuristic is used to pick the primary atmosphere
to render. Deliberately no multi-atmosphere support to keep the scope of
this PR small and self contained. See
https://github.com/mate-h/bevy/pull/19 at an attempt.
- `scene_units_to_m` removed in favor of using `Transform`
- Z up now possible by offsetting the viewer position to the equator
- Floating origin systems now possible
- Simplify the `AtmosphereBuffer` / `AtmosphereData` structs to just use
the plain extracted `GpuAtmosphere` struct. this reduces the complexity
of the struct in the mesh view bindings. Since atmosphere settings is
coupled with the rendering pipeline of the atmosphere this makes sense
architecturally.
- We no longer hard code the offset to the north pole from the planet
center in places.
**Why not multi atmosphere:**
The atmosphere uses multiple LUTs (lookup textures) to accelerate the
rendering performance. Some of them are not view dependent:
- Transmittance LUT
- Multiple scattering LUT
- Scattering / density LUTs
These can be coupled and rendered for each atmosphere individually.
However the remainder of the pipeline is view dependent:
- Aerial View LUT
- Sky View LUT
- Render Sky pass
In raymarched rendering mode, these LUTs can be skipped and only the
render sky pass runs sampling on all of the atmospheres with a raymarch
in screen space.
Further, the Sky View LUT uses a local reference frame to concentrate
texel density along the horizon's local up axis. This in turn means it's
coupled with both a _specific_ atmosphere's local coordinates as well as
the view's transform matrix. We cannot consider rendering both
atmospheres into a single LUT for this reason. So it has to be unique
for each pair of (view, atmosphere). Given two views and two atmospheres
we would need 4 of these Sky View LUTs and at some point, raymarched
rendering will become the less expensive option.
Lastly the Render Sky pass needs to happen once per view, we cannot
realistically composite them in sequence with simple dual-source
blending as we do with the scene, this would result in incorrect
scattering integration. This in turn means we need to bind ALL of the
luts calculated previously so a single render sky pass and render aerial
view lut - perhaps making use of array textures. Rely on unified
volumetric ingegration in the raymarching loop: for each light,for each
atmosphere, attenuate inscattering and transmittance along the path
integral. It is suffice to say this change is overall _too complex_ for
the time being and is likely the reason Unreal Engine also do not
support multiple atmospheres. For context: our research is based heavily
on Sebastian Hillarie's work, one of the Unreal graphics engineers.
That being said about multiple atmospheres - I am thinking of this PR as
a segway into unified volumetrics in Bevy. that is: Render the FogVolume
and Atmosphere in a single pass! Making use of the frustum aligned voxel
grid "froxel" approach to accelerate the rendering. This would
drastically increase the performance for scenes wanting to make use of
both the atmosphere and local fog volumes.
## Testing
- Ran the `examples/3d/atmosphere.rs` example.
---
## Showcase
(example screenshot unchanged compared to main.)
```rs
// Spawn earth atmosphere
commands.spawn(Atmosphere::earth(earth_medium));
commands.spawn((
Camera3d::default(),
// Can be adjusted to change the rendering quality
AtmosphereSettings::default(),
));
```
---------
Co-authored-by: Emerson Coskey <emerson@coskey.dev>
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.
# 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.
# Objective
Now that BSN is on main, we can port Feathers over!
Related: #23030#23413
## Solution
Port Feathers, leaving the bundle functions around (renamed to
`x_bundle` and deprecated). This is largely 1:1, other than removing
HandleOrPath (which is filling the same role as HandleTemplate). I've
also ported the `feathers` and `virtual_keyboard` examples to BSN.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- When starting bevy_city it just shows a window with a black screen and
nothing going on
- Some of that is because it's spawning the city and some of that is
because it's loading the asset
- We can make this a bit less painful by showing a loading screen that
shows a progress bar and which assets are still being loaded. I also
want to eventually spawn the city in chunks instead of in one go to keep
the app interactive instead of freezing for a while
## Solution
- Track all the assets in a flat vec of untyped handles and check their
load state until they are all ready
- Spawn a UI node that covers the screen and shows the path of the all
assets that aren't ready yet
- When all the assets are ready trigger an event that spawns the city
## Testing
- I ran the example and it worked
---
## Showcase
https://github.com/user-attachments/assets/30d60287-c442-4f37-aaf1-868b5ae2bb03
Currently, adding `NoCpuCulling` to a mesh on a frame after that mesh
was spawned causes that mesh to disappear. This is due to two bugs:
1. Meshes are unconditionally, and incorrectly, added to
`RenderGpuCulledEntities`, even if they are subject to CPU culling.
Entities are only added to the GPU culling bucket if they (1) don't
participate in CPU culling, (2) are in `RenderGpuCulledEntities` *now*,
and (3) weren't in `RenderGpuCulledEntities` *before*. Right now, since
entities are always in `RenderGpuCullingEntities`, these conditions are
never met when adding `NoCpuCulling` to an existing mesh that didn't
have that component before. This PR fixes the issue by excluding
entities without the `NoCpuCulling` component from
`RenderGpuCulledEntities`.
2. The `extract_meshes_for_gpu_building` system tries to extract meshes
for which `Changed<NoCpuCulling>` is true, but it fails because the
query is written like `Or<(Changed<Foo>, (Changed<Bar>,
Changed<NoCpuCulling>))>` instead of `Or<(Changed<Foo>,
Or<(Changed<Bar>, Changed<NoCpuCulling>)>)>`. The former is interpreted
as `Changed(Foo) || (Changed(Bar) && Changed(NoCpuCulling))` instead of
`Changed(Foo) || Changed(Bar) || Changed(NoCpuCulling)`, which was the
intention. Because of this, we were failing to extract meshes that had
`NoCpuCulling` assigned to them unless they were changed in some other
way.
This PR fixes both of these issues, and also refactors
`extract_meshes_for_gpu_building` a bit to reduce rightward drift.
This issue was noticed when attempting to add a check box to `bevy_city`
to disable CPU culling. I went ahead and added the check box to that
example, now that the issue preventing it from working is fixed.
# Objective
- We want to see the impact of `NoCpuCulling` in `bevy_city`
## Solution
- Add a new flag that adds the component on all meshes in the scene
## Testing
- I ran bevy_city with and without the flag. On my machine enabling it
went from 82fps to 95fps and being effectively gpu bound.
Adds support for line width (stroke) and quad topology for wireframes.
The triangle line fast path stays the same, but we add a new "wide" draw
function path that uses a specialized vertex shader in order to do the
following via vertex pulling from the appropriate mesh slab:
- Compute screen-space altitudes for our edges.
- Find and suppress diagonals when quad topology is enabled.
Doing this in the vertex shader allows us to avoid needing to de-dupe on
the CPU or spend additional bandwidth uploading a mesh copy at the
expense of a bit of extra shading.
Right now, we have to break batches on the mesh when in the "wide" path,
meaning we don't get full advantage of MDI, but this is mostly because
we don't have a great way to support per-draw data. This could be fixed
in the future.
## Examples:
<img width="1924" height="1126" alt="image"
src="https://github.com/user-attachments/assets/cd73eb9d-f215-413d-ba28-bddc6bd980b0"
/>
<img width="1924" height="1127" alt="Screenshot 2026-02-16 160350"
src="https://github.com/user-attachments/assets/901f5dbb-c900-43b3-bd6b-ce5c9eece82f"
/>
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: atlv <email@atlasdostal.com>
# Objective
- Add a test scene that pushes a lot of rendering features while also
pushing the ECS with a lot of entity updates
## Solution
- Add a procedurally generated city with a lot of different assets.
- Spawn cars that move on every frame, eventually this will have a full
traffic simulation that should stress the ECS
## Testing
- The example runs
---
## Showcase

---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- Fixes#16751
## Solution
- `Assets::get_mut` now returns a wrapper `AssetMut` type instead of
`&mut impl Asset`.
- `AssetMut` implements `Deref` and `DerefMut`.
- `DerefMut` marks assets as changed.
- when dropped `AssetMut` will add `AssetEvent::Modified` event to a
queue only in case asset was marked as changed.
## Testing
- Did you test these changes? If so, how?
- No unit tests were added, change is pretty straightforward.
- Test project: https://github.com/MatrixDev/bevy-feature-16751-test.
- With change: ~100 fps.
- Without change: ~15 fps.
- Are there any parts that need more testing?
- I don't really see how this can break anything or add a measurable
overhead.
- `AssetEvent::Modified` will now be sent after the asset was modified
instead of before. It should not affect anything but still worth noting.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Have a big amount of entities that constantly update their materials.
- Properties of those materials should be animated in a stepped maned
(like changing color every 0.1 seconds).
- Update material only if value has actually changed:
```rust
if material.base_color != new_color {
material.base_color = new_color;
}
```
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- tested on macos (Mackbook M1)
- not a platform-specific issue
PS: This is my first PR, so please don’t judge.
# Objective
Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.
## Solution
Introduce a new `FontSize` enum:
```rust
pub enum FontSize {
/// Font Size in logical pixels.
Px(f32),
/// Font size as a percentage of the viewport width.
Vw(f32),
/// Font size as a percentage of the viewport height.
Vh(f32),
/// Font size as a percentage of the smaller of the viewport width and height.
VMin(f32),
/// Font size as a percentage of the larger of the viewport width and height.
VMax(f32),
/// Font Size relative to the value of the `RemSize` resource.
Rem(f32),
}
```
This replaces the `f32` value of `TextFont`'s `font_size` field.
The viewport variants work the same way as their respective `Val`
counterparts.
`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).
`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.
Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.
`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.
### Change detection
`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.
The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
pub fn needs_rerender(
&self,
is_viewport_size_changed: bool,
is_rem_size_changed: bool,
) -> bool {
self.needs_rerender
|| (is_viewport_size_changed && self.uses_viewport_sizes)
|| (is_rem_size_changed && self.uses_rem_sizes)
}
```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.
#### Limitations
There are some limitations because we don't have any sort of font style inheritance yet:
* "rem" units aren't proper rem units, and just based on the value of a resource.
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.
#### Notes
* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.
* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.
## Testing
The changes to the text systems are relatively trivial and easy to understand. I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.
Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.
---------
Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
# Objective
- It makes no sense for bevy_camera::Camera3d to talk about transmission
quality settings
- transmission is not a core thing its a purely pbr thing, why is in
bevy_core_pipelines
- the implementation is generally scattered all over the place
- ScreenSpaceTransmissionQuality is a resource for no reason at all
## Solution
- split out a struct for transmission stuff
- consolidate stuff in bevy_pbr
- make ScreenSpaceTransmissionQuality not a resource
## Testing
transmission example looks good
# Objective
- whether a Camera needs to draw Hdr content or not is an aspect of
scene description
- as such, it should live in a non-rendering crate
## Solution
- move it to bevy_camera
- dont extract it to the render world anymore. audited all usages of it
and none are in the render world queries, instead `ExtractedCamera::hdr`
is used.
## Testing
- manual spot check of a few examples
- example runner regression test
# Objective
#### Some cleanup
1. `many_gradients` inserts `WinitSettings` twice.
2. Replace manual configuration where `WinitSettings::continuous()`
could be used.
With #22603 landed, all known issues that could cause Bevy to cull
meshes that shouldn't have been culled are fixed, so there now seems to
be consensus that we can remove occlusion culling from the
`experimental` namespace. This patch does that (and in fact removes the
`experimental` module from `bevy_render` entirely, as it's now empty).
Updates the requirements on
[fast_image_resize](https://github.com/cykooz/fast_image_resize) to
permit the latest version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cykooz/fast_image_resize/releases">fast_image_resize's
releases</a>.</em></p>
<blockquote>
<h2>[6.0.0] - 2026-01-13</h2>
<h3>Added</h3>
<ul>
<li>
<p><strong>BREAKING</strong>: Added support of <code>no_std</code>
environment (<a
href="https://redirect.github.com/Cykooz/fast_image_resize/issues/58">#58</a>).
To use the crate in a such environment, you must disable
default features and enabled the <code>no_std</code> feature.</p>
<p>If you already have default features disabled and want to continue
using the crate in <code>std</code> environment, you have to enable
the <code>std</code> feature.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Cykooz/fast_image_resize/blob/main/CHANGELOG.md">fast_image_resize's
changelog</a>.</em></p>
<blockquote>
<h2>[6.0.0] - 2026-01-13</h2>
<h3>Added</h3>
<ul>
<li>
<p><strong>BREAKING</strong>: Added support of <code>no_std</code>
environment (<a
href="https://redirect.github.com/Cykooz/fast_image_resize/issues/58">#58</a>).
To use the crate in a such environment, you must disable
default features and enabled the <code>no_std</code> feature.</p>
<p>If you already have default features disabled and want to continue
using the crate in <code>std</code> environment, you have to enable
the <code>std</code> feature.</p>
</li>
</ul>
<h2>[5.6.0] - 2026-01-07 (yanked)</h2>
<p>This version was yanked due to a backwards compatibility break -
a new feature <code>std</code> was added to the list of default
features.</p>
<h2>[5.5.0] - 2026-01-02</h2>
<h3>Added</h3>
<ul>
<li>Added support of some variants of <code>ImageBuffer</code> type
form the <code>image</code> crate (<a
href="https://redirect.github.com/Cykooz/fast_image_resize/issues/57">#57</a>).</li>
</ul>
<h2>[5.4.0] - 2025-11-28</h2>
<h3>Added</h3>
<ul>
<li>Added <code>bytemuck</code> feature and implemented some
<code>bytemuck</code> traits for the <code>Pixel</code> type
(<a
href="https://redirect.github.com/Cykooz/fast_image_resize/pull/56">#56</a>).</li>
</ul>
<h2>[5.3.0] - 2025-09-02</h2>
<h3>Added</h3>
<ul>
<li>Added support for multi-thread image resizing using the
<code>ResizeAlg::Nearest</code> algorithm.
(<a
href="https://redirect.github.com/Cykooz/fast_image_resize/issues/54">#54</a>).</li>
</ul>
<h2>[5.2.2] - 2025-08-29</h2>
<h3>Fixed</h3>
<ul>
<li>Fixed a "divide by zero" error in case of using
multithreading to resize images
with particular sizes (<a
href="https://redirect.github.com/Cykooz/fast_image_resize/issues/55">#55</a>).</li>
</ul>
<h2>[5.2.1] - 2025-07-27</h2>
<h3>Changed</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/a563fb6226009171143d81d250db4a823a034895"><code>a563fb6</code></a>
chore: Release</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/dbcef13f9c454db5fd80ad2ae412415d5edd1a8f"><code>dbcef13</code></a>
Improved the note in the changelog.</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/482c7503ab199e01b8a198ca67b6de9ba4739544"><code>482c750</code></a>
Improved the note in the changelog.</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/b075157b74aa733eec2634f23a5544dab8d45348"><code>b075157</code></a>
Improved the note in the changelog.</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/2772f93ace38ef14dd197207d4cdc6452810f2c4"><code>2772f93</code></a>
Release 5.6 was yanked. Prepare to release 6.0.</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/01889ecd0dc2b0dfee674253cbb9ad5a60377d2c"><code>01889ec</code></a>
chore: Release</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/fd203b6a7adeb86b582e739657f8de0d7f473f4f"><code>fd203b6</code></a>
Corrected position of <code>document-features</code> dependency in
Cargo.toml.</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/abf8d8a1e26036e1045f0b897627f84c536398ec"><code>abf8d8a</code></a>
Added <code>no_std</code> keyword to Cargo.toml</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/b2dda5ef3852052f3cd327c39b153e2f9b80d1aa"><code>b2dda5e</code></a>
Added GitHub Action to test of building documentation for docs.rs</li>
<li><a
href="https://github.com/Cykooz/fast_image_resize/commit/8b25261b42d94957778dd15d1b49d3009e52c5db"><code>8b25261</code></a>
Fixed <code>compat</code> module.</li>
<li>Additional commits viewable in <a
href="https://github.com/cykooz/fast_image_resize/compare/v5.4.0...v6.0.0">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
Move https://github.com/DGriffin91/bevy_bistro_scene and
https://github.com/DGriffin91/bevy_caldera_scene into the bevy repo for
allow for easier testing.
This also adds https://github.com/DGriffin91/bevy_mod_mipmap_generator
in the new `large_scene` folder because GPU texture fetch cache locality
is important. This could be eventually available more generally as a
part of bevy. But wanted to get something quick and basic in for now.
Not totally sure what these readme's should look like. I mostly just
copied them over and made a few tweaks.
This PR is meant to just be an initial starting point, it does not
address automatically acquiring the required assets.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>