# Objective
In UI extraction the default UI camera is queried for every UI node. It
only needs to be retrieved once.
## Solution
Query for the default UI camera once before iterating the UI nodes.
```
cargo run --example many_buttons --release --features "trace_tracy"
```
<img width="631" alt="default-camera-extract"
src="https://github.com/user-attachments/assets/db712bce-6a0b-49a7-8e20-654baf588390"
/>
`extract_uinode_background_colors` yellow is this PR, red is main.
Bump version after release
This PR has been auto-generated
---------
Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- Contributes to #11478
## Solution
- Made `bevy_utils::tracing` `doc(hidden)`
- Re-exported `tracing` from `bevy_log` for end-users
- Added `tracing` directly to crates that need it.
## Testing
- CI
---
## Migration Guide
If you were importing `tracing` via `bevy::utils::tracing`, instead use
`bevy::log::tracing`. Note that many items within `tracing` are also
directly re-exported from `bevy::log` as well, so you may only need
`bevy::log` for the most common items (e.g., `warn!`, `trace!`, etc.).
This also applies to the `log_once!` family of macros.
## Notes
- While this doesn't reduce the line-count in `bevy_utils`, it further
decouples the internal crates from `bevy_utils`, making its eventual
removal more feasible in the future.
- I have just imported `tracing` as we do for all dependencies. However,
a workspace dependency may be more appropriate for version management.
Derived `Default` for all public unit structs that already derive from
`Component`. This allows them to be used more easily as required
components.
To avoid clutter in tests/examples, only public components were
affected, but this could easily be expanded to affect all unit
components.
Fixes#17052.
# Objective
The UI debug overlay draws an outline for every UI node even if it is
invisible or clipped.
Disable debug outlines for hidden and clipped nodes by default and add
options to renable them if needed.
## Solution
* Add `show_hidden` and `show_clipped` fields to `UiDebugOptions`:
```rust
/// Show outlines for non-visible UI nodes
pub show_hidden: bool,
/// Show outlines for clipped sections of UI nodes
pub show_clipped: bool,
```
* Only extract debug outlines for hidden and clipped UI nodes if the
respective field in `UiDebugOptions` is set to `true`.
## Testing
Also added some extra features to the `testbed_ui` example that
demonstrate the new options:
cargo run --example testbed_ui --features "bevy_ui_debug"
<img width="641" alt="show-hidden-and-clipped"
src="https://github.com/user-attachments/assets/16a68600-170c-469e-a3c7-f7dae411dc40"
/>
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/16556
- Closes https://github.com/bevyengine/bevy/issues/11807
## Solution
- Simplify custom projections by using a single source of truth -
`Projection`, removing all existing generic systems and types.
- Existing perspective and orthographic structs are no longer components
- I could dissolve these to simplify further, but keeping them around
was the fast way to implement this.
- Instead of generics, introduce a third variant, with a trait object.
- Do an object safety dance with an intermediate trait to allow cloning
boxed camera projections. This is a normal rust polymorphism papercut.
You can do this with a crate but a manual impl is short and sweet.
## Testing
- Added a custom projection example
---
## Showcase
- Custom projections and projection handling has been simplified.
- Projection systems are no longer generic, with the potential for many
different projection components on the same camera.
- Instead `Projection` is now the single source of truth for camera
projections, and is the only projection component.
- Custom projections are still supported, and can be constructed with
`Projection::custom()`.
## Migration Guide
- `PerspectiveProjection` and `OrthographicProjection` are no longer
components. Use `Projection` instead.
- Custom projections should no longer be inserted as a component.
Instead, simply set the custom projection as a value of `Projection`
with `Projection::custom()`.
# Objective
Remove the `atlas_scaling` field from `ExtractedUiItem::Gylphs`.
It's only ever set to `Vec2::ONE`. I don't remember why/if this field
was ever needed, maybe it was useful before the scale factor clean up.
## Migration Guide
The `atlas_scaling` field from `ExtractedUiItem::Gylphs` has been
removed. This shouldn't affect any existing code as it wasn't used for
anything.
# Objective
Fixes#16104
## Solution
I removed all instances of `:?` and put them back one by one where it
caused an error.
I removed some bevy_utils helper functions that were only used in 2
places and don't add value. See: #11478
## Testing
CI should catch the mistakes
## Migration Guide
`bevy::utils::{dbg,info,warn,error}` were removed. Use
`bevy::utils::tracing::{debug,info,warn,error}` instead.
---------
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
# Objective
This PR implements `FromStr` for `Val`, so developers can parse values
like `10px` and `50%`
## Testing
Added tests for this. I think they cover pretty much everything, and
it's a fairly simple unit test.
## Limitations
Currently the following float values are not parsed:
- `inf`, `-inf`, `+infinity`, `NaN`
- `2.5E10`, `2.5e10`, `2.5E-10`
For my use case this is perfectly fine but other developers might want
to support these values
# Objective
Some types like `RenderEntity` and `MainEntity` are just wrappers around
`Entity`, so they should be able to implement
`EntityBorrow`/`TrustedEntityBorrow`. This allows using them with
`EntitySet` functionality.
The `EntityRef` family are more than direct wrappers around `Entity`,
but can still benefit from being unique in a collection.
## Solution
Implement `EntityBorrow` and `TrustedEntityBorrow` for simple `Entity`
newtypes and `EntityRef` types.
These impls are an explicit decision to have the `EntityRef` types
compare like just `Entity`.
`EntityWorldMut` is omitted from this impl, because it explicitly
contains a `&mut World` as well, and we do not ever use more than one at
a time.
Add `EntityBorrow` to the `bevy_ecs` prelude.
## Migration Guide
`NormalizedWindowRef::entity` has been replaced with an
`EntityBorrow::entity` impl.
# Objective
Allow users to enable or disable layout rounding for specific UI nodes
and their descendants.
Fixes#16731
## Solution
New component `LayoutConfig` that can be added to any UiNode entity.
Setting the `use_rounding` field of `LayoutConfig` determines if the
Node and its descendants should be given rounded or unrounded
coordinates.
## Testing
Not tested this extensively but it seems to work and it's not very
complicated.
This really basic test app returns fractional coords:
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, report)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Node {
left: Val::Px(0.1),
width: Val::Px(100.1),
height: Val::Px(100.1),
..Default::default()
},
LayoutConfig { use_rounding: false },
));
}
fn report(node: Query<(Ref<ComputedNode>, &GlobalTransform)>) {
for (c, g) in node.iter() {
if c.is_changed() {
println!("{:#?}", c);
println!("position = {:?}", g.to_scale_rotation_translation().2);
}
}
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
# Objective
When preparing `GpuImage`s, we currently discard the
`depth_or_array_layers` of the `Image`'s size by converting it into a
`UVec2`.
Fixes#16715.
## Solution
Change `GpuImage::size` to `Extent3d`, and just pass that through when
creating `GpuImage`s.
Also copy the `aspect_ratio`, and `size` (now `size_2d` for
disambiguation from the field) functions from `Image` to `GpuImage` for
ease of use with 2D textures.
I originally copied all size-related functions (like `width`, and
`height`), but i think they are unnecessary considering how visible the
`size` field on `GpuImage` is compared to `Image`.
## Testing
Tested via `cargo r -p ci` for everything except docs, when generating
docs it keeps spitting out a ton of
```
error[E0554]: `#![feature]` may not be used on the stable release channel
--> crates/bevy_dylib/src/lib.rs:1:21
|
1 | #![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
```
Not sure why this is happening, but it also happens without my changes,
so it's almost certainly some strange issue specific to my machine.
## Migration Guide
- `GpuImage::size` is now an `Extent3d`. To easily get 2D size, use
`size_2d()`.
Currently, `check_visibility` is parameterized over a query filter that
specifies the type of potentially-visible object. This has the
unfortunate side effect that we need a separate system,
`mark_view_visibility_as_changed_if_necessary`, to trigger view
visibility change detection. That system is quite slow because it must
iterate sequentially over all entities in the scene.
This PR moves the query filter from `check_visibility` to a new
component, `VisibilityClass`. `VisibilityClass` stores a list of type
IDs, each corresponding to one of the query filters we used to use.
Because `check_visibility` is no longer specialized to the query filter
at the type level, Bevy now only needs to invoke it once, leading to
better performance as `check_visibility` can do change detection on the
fly rather than delegating it to a separate system.
This commit also has ergonomic improvements, as there's no need for
applications that want to add their own custom renderable components to
add specializations of the `check_visibility` system to the schedule.
Instead, they only need to ensure that the `ViewVisibility` component is
properly kept up to date. The recommended way to do this, and the way
that's demonstrated in the `custom_phase_item` and
`specialized_mesh_pipeline` examples, is to make `ViewVisibility` a
required component and to add the type ID to it in a component add hook.
This patch does this for `Mesh3d`, `Mesh2d`, `Sprite`, `Light`, and
`Node`, which means that most app code doesn't need to change at all.
Note that, although this patch has a large impact on the performance of
visibility determination, it doesn't actually improve the end-to-end
frame time of `many_cubes`. That's because the render world was already
effectively hiding the latency from
`mark_view_visibility_as_changed_if_necessary`. This patch is, however,
necessary for *further* improvements to `many_cubes` performance.
`many_cubes` trace before:

`many_cubes` trace after:

## Migration Guide
* `check_visibility` no longer takes a `QueryFilter`, and there's no
need to add it manually to your app schedule anymore for custom
rendering items. Instead, entities with custom renderable components
should add the appropriate type IDs to `VisibilityClass`. See
`custom_phase_item` for an example.
# Objective
- Enable modifying node size after layout.
- Gain access to a node's content_size. `UiSurface` is a private type so
content size can't be looked up.
## Solution
- Make `ComputedNode` fields public.
- Add `content_size` to `ComputedNode`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Scroll position uses physical coordinates. This means scrolling may go
faster or slower depending on the scroll factor. Also the scrolled
position will change when the scale factor changes.
## Solution
In `ui_layout_system` convert `max_possible_offset` to logical
coordinates before clamping the scroll position. Then convert the
clamped scroll position to physical coordinates before propagating it to
the node's children.
## Testing
Look at the `scroll` example. On main if you change your display's scale
factor the items displayed by the scrolling lists will change because
`ScrollPosition`'s displacement values don't respect scale factor. With
this PR the displacement will be scaled too, and the won't move.
# Objective
We were waiting for 1.83 to address most of these, due to a bug with
`missing_docs` and `expect`. Relates to, but does not entirely complete,
#15059.
## Solution
- Upgrade to 1.83
- Switch `allow(missing_docs)` to `expect(missing_docs)`
- Remove a few now-unused `allow`s along the way, or convert to `expect`
# Objective
Fixes#16659
## Solution
- I just added all the `#[reflect(Component)]` attributes where
necessary.
## Testing
I wrote a small program that scans the bevy code for all structs and
enums that derive `Component` and `Reflect`, but don't have the
attribute `#[reflect(Component)]`.
I don't know if this testing program should be part of the testing suite
of bevy. It takes a bit of time to scan the whole codebase. In any case,
I've published it [here](https://github.com/anlumo/bevy-reflect-check).
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Destructuring in const code blocks isn't allowed, thus using UIRect in
const code can be a hassle as it initialisation function aren't const.
This Pr makes them const.
## Solution
Removed all destructuring in the UIRect implementation
## Testing
- I've ran a few ui examples to check if i didn't make a mistake,
---
# Objective
Fixes#16771
## Solution
Fixed typo in code.
## Testing
- Did you test these changes? If so, how?
I tested on my own example, that I included in the issue. It was
behaving as I expected.
Here is the screenshot after fix, the screenshot before the fix can be
found in the issue.

# Objective
The doc comments and function namings for `BorderRect` feel imprecise to
me. Particularly the `square` function which is used to define a uniform
`BorderRect` with equal widths on each edge. But this is potentially
confusing since this "square" border could be around an oblong shape.
Using "padding" to refer to the border extents seems undesirable too
since "padding" is typically used to refer to the area between border
and content, not the border itself.
## Solution
* Rename `square` to `all` (this matches the name of the similar method
on `UiRect`).
* Rename `rectangle` to `axes` (this matches the name of the similar
method on `UiRect`).
* Update doc comments.
## Migration Guide
The `square` and `rectangle` functions belonging to `BorderRect` have
been renamed to `all` and `axes`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Register `BoxShadow` type for reflection
## Testing
- Tested that box shadow example compiles and runs
## Additional
- It would be nice to have this in 0.15.1
# Objective
Draw the UI debug overlay using the UI renderer.
Significantly simpler and easier to use than
`bevy_dev_tools::ui_debug_overlay` which uses `bevy_gizmos`.
* Supports multiple windows and UI rendered to texture.
* Draws rounded debug rects for rounded UI nodes.
Fixes#16666
## Solution
Removed the `ui_debug_overlay` module from `bevy_dev_tools`.
Added a `bevy_ui_debug` feature gate.
Draw the UI debug overlay using the UI renderer.
Adds a new module `bevy_ui::render::debug_overlay`.
The debug overlay extraction function queries for the existing UI layout
and then adds a border around each UI node with `u32::MAX / 2` added to
each stack index so it's drawn on top.
There is a `UiDebugOptions` resource that can be used to enable or
disable the debug overlay and set the line width.
## Testing
The `testbed_ui` example has been changed to use the new debug overlay:
```
cargo run --example testbed_ui --features bevy_ui_debug
```
Press Space to toggle the debug overlay on and off.
---
## Showcase
<img width="961" alt="testbed-ui-new-debug"
src="https://github.com/user-attachments/assets/e9523d18-39ae-46a8-adbe-7d3f3ab8e951">
## Migration Guide
The `ui_debug_overlay` module has been removed from `bevy_dev_tools`.
There is a new debug overlay implemented using the `bevy_ui` renderer.
To use it, enable the `bevy_ui_debug` feature and set the `enable` field
of the `UiDebugOptions` resource to `true`.
Updating dependencies; adopted version of #15696. (Supercedes #15696.)
Long answer: hashbrown is no longer using ahash by default, meaning that
we can't use the default-hasher methods with ahasher. So, we have to use
the longer-winded versions instead. This takes the opportunity to also
switch our default hasher as well, but without actually enabling the
default-hasher feature for hashbrown, meaning that we'll be able to
change our hasher more easily at the cost of all of these method calls
being obnoxious forever.
One large change from 0.15 is that `insert_unique_unchecked` is now
`unsafe`, and for cases where unsafe code was denied at the crate level,
I replaced it with `insert`.
## Migration Guide
`bevy_utils` has updated its version of `hashbrown` to 0.15 and now
defaults to `foldhash` instead of `ahash`. This means that if you've
hard-coded your hasher to `bevy_utils::AHasher` or separately used the
`ahash` crate in your code, you may need to switch to `foldhash` to
ensure that everything works like it does in Bevy.
# Objective
- Fixes#16497
- This is my first PR, so I'm still learning to contribute to the
project
## Solution
- Added struct `UnregisterSystemCached` and function
`unregister_system_cached`
- renamed `World::run_system_with_input` to `run_system_with`
- reordered input parameters for `World::run_system_once_with`
## Testing
- Added a crude test which registers a system via
`World::register_system_cached`, and removes it via
`Command::unregister_system_cached`.
## Migration Guide
- Change all occurrences of `World::run_system_with_input` to
`World::run_system_with`.
- swap the order of input parameters for `World::run_system_once_with`
such that the system comes before the input.
---------
Co-authored-by: Paul Mattern <mail@paulmattern.dev>
# Objective
Fixes#16610, related to #16702
## Solution
Upgrade typos and its configuration
## Testing
- Did you test these changes? If so, how? No
- Are there any parts that need more testing? No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know? No
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test? Not applicable
# Objective
Fixes typos in bevy project, following suggestion in
https://github.com/bevyengine/bevy-website/pull/1912#pullrequestreview-2483499337
## Solution
I used https://github.com/crate-ci/typos to find them.
I included only the ones that feel undebatable too me, but I am not in
game engine so maybe some terms are expected.
I left out the following typos:
- `reparametrize` => `reparameterize`: There are a lot of occurences, I
believe this was expected
- `semicircles` => `hemicircles`: 2 occurences, may mean something
specific in geometry
- `invertation` => `inversion`: may mean something specific
- `unparented` => `parentless`: may mean something specific
- `metalness` => `metallicity`: may mean something specific
## Testing
- Did you test these changes? If so, how? I did not test the changes,
most changes are related to raw text. I expect the others to be tested
by the CI.
- Are there any parts that need more testing? I do not think
- How can other people (reviewers) test your changes? Is there anything
specific they need to know? To me there is nothing to test
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
---
## Migration Guide
> This section is optional. If there are no breaking changes, you can
delete this section.
(kept in case I include the `reparameterize` change here)
- If this PR is a breaking change (relative to the last release of
Bevy), describe how a user might need to migrate their code to support
these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable
design choice is not a breaking change.
## Questions
- [x] Should I include the above typos? No
(https://github.com/bevyengine/bevy/pull/16702#issuecomment-2525271152)
- [ ] Should I add `typos` to the CI? (I will check how to configure it
properly)
This project looks awesome, I really enjoy reading the progress made,
thanks to everyone involved.
This commit adds support for *multidraw*, which is a feature that allows
multiple meshes to be drawn in a single drawcall. `wgpu` currently
implements multidraw on Vulkan, so this feature is only enabled there.
Multiple meshes can be drawn at once if they're in the same vertex and
index buffers and are otherwise placed in the same bin. (Thus, for
example, at present the materials and textures must be identical, but
see #16368.) Multidraw is a significant performance improvement during
the draw phase because it reduces the number of rebindings, as well as
the number of drawcalls.
This feature is currently only enabled when GPU culling is used: i.e.
when `GpuCulling` is present on a camera. Therefore, if you run for
example `scene_viewer`, you will not see any performance improvements,
because `scene_viewer` doesn't add the `GpuCulling` component to its
camera.
Additionally, the multidraw feature is only implemented for opaque 3D
meshes and not for shadows or 2D meshes. I plan to make GPU culling the
default and to extend the feature to shadows in the future. Also, in the
future I suspect that polyfilling multidraw on APIs that don't support
it will be fruitful, as even without driver-level support use of
multidraw allows us to avoid expensive `wgpu` rebindings.
# Objective
- Remove `derive_more`'s error derivation and replace it with
`thiserror`
## Solution
- Added `derive_more`'s `error` feature to `deny.toml` to prevent it
sneaking back in.
- Reverted to `thiserror` error derivation
## Notes
Merge conflicts were too numerous to revert the individual changes, so
this reversion was done manually. Please scrutinise carefully during
review.
# Objective
- Required by #16622 due to differing implementations of `System` by
`FunctionSystem` and `ExclusiveFunctionSystem`.
- Optimize the memory usage of instances of `apply_deferred` in system
schedules.
## Solution
By changing `apply_deferred` from being an ordinary system that ends up
as an `ExclusiveFunctionSystem`, and instead into a ZST struct that
implements `System` manually, we save ~320 bytes per instance of
`apply_deferred` in any schedule.
## Testing
- All current tests pass.
---
## Migration Guide
- If you were previously calling the special `apply_deferred` system via
`apply_deferred(world)`, don't.
# Objective
Make documentation of a component's required components more visible by
moving it to the type's docs
## Solution
Change `#[require]` from a derive macro helper to an attribute macro.
Disadvantages:
- this silences any unused code warnings on the component, as it is used
by the macro!
- need to import `require` if not using the ecs prelude (I have not
included this in the migration guilde as Rust tooling already suggests
the fix)
---
## Showcase

---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
# Objective
The `UiBoxShadowSamples` resource should be renamed to
`BoxShadowSamples` so it matches the `BoxShadow` component.
## Migration Guide
`UiBoxShadowSamples` has been renamed to `BoxShadowSamples`
# Objective
Remove the `min` and `max` fields from `LayoutContext`.
It doesn't seem useful to cache these values, it's simpler just to call
`min_element` and `max_element` on the `physical_size`
field.
## Migration Guide
The `min` and `max` fields have been removed from `LayoutContext`. To
retrieve these values call `min_element` and `max_element` on
`LayoutContent::physical_size` instead.
This patch adds the infrastructure necessary for Bevy to support
*bindless resources*, by adding a new `#[bindless]` attribute to
`AsBindGroup`.
Classically, only a single texture (or sampler, or buffer) can be
attached to each shader binding. This means that switching materials
requires breaking a batch and issuing a new drawcall, even if the mesh
is otherwise identical. This adds significant overhead not only in the
driver but also in `wgpu`, as switching bind groups increases the amount
of validation work that `wgpu` must do.
*Bindless resources* are the typical solution to this problem. Instead
of switching bindings between each texture, the renderer instead
supplies a large *array* of all textures in the scene up front, and the
material contains an index into that array. This pattern is repeated for
buffers and samplers as well. The renderer now no longer needs to switch
binding descriptor sets while drawing the scene.
Unfortunately, as things currently stand, this approach won't quite work
for Bevy. Two aspects of `wgpu` conspire to make this ideal approach
unacceptably slow:
1. In the DX12 backend, all binding arrays (bindless resources) must
have a constant size declared in the shader, and all textures in an
array must be bound to actual textures. Changing the size requires a
recompile.
2. Changing even one texture incurs revalidation of all textures, a
process that takes time that's linear in the total size of the binding
array.
This means that declaring a large array of textures big enough to
encompass the entire scene is presently unacceptably slow. For example,
if you declare 4096 textures, then `wgpu` will have to revalidate all
4096 textures if even a single one changes. This process can take
multiple frames.
To work around this problem, this PR groups bindless resources into
small *slabs* and maintains a free list for each. The size of each slab
for the bindless arrays associated with a material is specified via the
`#[bindless(N)]` attribute. For instance, consider the following
declaration:
```rust
#[derive(AsBindGroup)]
#[bindless(16)]
struct MyMaterial {
#[buffer(0)]
color: Vec4,
#[texture(1)]
#[sampler(2)]
diffuse: Handle<Image>,
}
```
The `#[bindless(N)]` attribute specifies that, if bindless arrays are
supported on the current platform, each resource becomes a binding array
of N instances of that resource. So, for `MyMaterial` above, the `color`
attribute is exposed to the shader as `binding_array<vec4<f32>, 16>`,
the `diffuse` texture is exposed to the shader as
`binding_array<texture_2d<f32>, 16>`, and the `diffuse` sampler is
exposed to the shader as `binding_array<sampler, 16>`. Inside the
material's vertex and fragment shaders, the applicable index is
available via the `material_bind_group_slot` field of the `Mesh`
structure. So, for instance, you can access the current color like so:
```wgsl
// `uniform` binding arrays are a non-sequitur, so `uniform` is automatically promoted
// to `storage` in bindless mode.
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
let color = material_color[mesh[in.instance_index].material_bind_group_slot];
...
}
```
Note that portable shader code can't guarantee that the current platform
supports bindless textures. Indeed, bindless mode is only available in
Vulkan and DX12. The `BINDLESS` shader definition is available for your
use to determine whether you're on a bindless platform or not. Thus a
portable version of the shader above would look like:
```wgsl
#ifdef BINDLESS
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
#else // BINDLESS
@group(2) @binding(0) var<uniform> material_color: Color;
#endif // BINDLESS
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
#ifdef BINDLESS
let color = material_color[mesh[in.instance_index].material_bind_group_slot];
#else // BINDLESS
let color = material_color;
#endif // BINDLESS
...
}
```
Importantly, this PR *doesn't* update `StandardMaterial` to be bindless.
So, for example, `scene_viewer` will currently not run any faster. I
intend to update `StandardMaterial` to use bindless mode in a follow-up
patch.
A new example, `shaders/shader_material_bindless`, has been added to
demonstrate how to use this new feature.
Here's a Tracy profile of `submit_graph_commands` of this patch and an
additional patch (not submitted yet) that makes `StandardMaterial` use
bindless. Red is those patches; yellow is `main`. The scene was Bistro
Exterior with a hack that forces all textures to opaque. You can see a
1.47x mean speedup.

## Migration Guide
* `RenderAssets::prepare_asset` now takes an `AssetId` parameter.
* Bin keys now have Bevy-specific material bind group indices instead of
`wgpu` material bind group IDs, as part of the bindless change. Use the
new `MaterialBindGroupAllocator` to map from bind group index to bind
group ID.
# Objective
- Keep Taffy version up to date
Taffy 0.6 doesn't include a huge amount relevant to Bevy. But it does:
- Add the `box_sizing` style
- Expose the computed `margin` in layout
- Traitifies the `Style` struct, which opens up the possibility of using
Bevy's `Style` struct directly (although Bevy currently does some style
resolution at conversion time which would no longer be cached if it was
used directly).
- Have a few bug fixes in the layout algorithms
## Solution
- Upgrade Taffy to `0.6.0`
## Testing
- I've run the `grid` example. All looks good.
- More testing is probably warranted. We have had regressions from Taffy
upgrades before
- Having said that, most of the algorithm changes this cycle were driven
by fixing WPT tests run through the new Servo integration. So they're
possibly less likely than usual to cause regressions.
## Breaking changes
The only "breaking" change is adding a field to `Style`. Probably
doesn't bear mentioning?
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Add support for multiple box shadows on a single `Node`.
## Solution
* Rename `BoxShadow` to `ShadowStyle` and remove its `Component` derive.
* Create a new `BoxShadow` component that newtypes a `Vec<ShadowStyle>`.
* Add a `new` constructor method to `BoxShadow` for single shadows.
* Change `extract_shadows` to iterate through a list of shadows per
node.
Render order is determined implicitly from the order of the shadows
stored in the `BoxShadow` component, back-to-front.
Might be more efficient to use a `SmallVec<[ShadowStyle; 1]>` for the
list of shadows but not sure if the extra friction is worth it.
## Testing
Added a node with four differently coloured shadows to the `box_shadow`
example.
---
## Showcase
```
cargo run --example box_shadow
```
<img width="460" alt="four-shadow"
src="https://github.com/user-attachments/assets/2f728c47-33b4-42e1-96ba-28a774b94b24">
## Migration Guide
Bevy UI now supports multiple shadows per node. A new struct
`ShadowStyle` is used to set the style for each shadow. And the
`BoxShadow` component is changed to a tuple struct wrapping a vector
containing a list of `ShadowStyle`s. To spawn a node with a single
shadow you can use the `new` constructor function:
```rust
commands.spawn((
Node::default(),
BoxShadow::new(
Color::BLACK.with_alpha(0.8),
Val::Percent(offset.x),
Val::Percent(offset.y),
Val::Percent(spread),
Val::Px(blur),
)
));
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- In 0.14, ZIndex and GlobalZIndex where split from a shared enum into
separate components. There have been a few people confused by the
behavior of ZIndex when they really needed GlobalZIndex.
## Solution
- Update ZIndex docs to improve discoverability of GlobalZIndex.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
When using a rect for a ui image, its content size is still equal to the
size of the full image instead of the size of the rect.
## Solution
Use the rect size if it is present.
## Testing
I tested it using all 4 possible combinations of having a rect and
texture atlas or not. See the showcase section.
---
## Showcase
<details>
<summary>Click to view showcase</summary>
```rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
.add_systems(Startup, create_ui)
.run();
}
fn create_ui(
mut commands: Commands,
assets: Res<AssetServer>,
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
mut ui_scale: ResMut<UiScale>,
) {
let texture = assets.load("textures/fantasy_ui_borders/numbered_slices.png");
let layout = TextureAtlasLayout::from_grid(UVec2::splat(16), 3, 3, None, None);
let texture_atlas_layout = texture_atlas_layouts.add(layout);
ui_scale.0 = 2.;
commands.spawn(Camera2d::default());
commands
.spawn(Node {
display: Display::Flex,
align_items: AlignItems::Center,
..default()
})
.with_children(|parent| {
// nothing
parent.spawn(ImageNode::new(texture.clone()));
// with rect
parent.spawn(ImageNode::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)));
// with rect and texture atlas
parent.spawn(
ImageNode::from_atlas_image(
texture.clone(),
TextureAtlas {
layout: texture_atlas_layout.clone(),
index: 1,
},
)
.with_rect(Rect::new(0., 0., 8., 8.)),
);
// with texture atlas
parent.spawn(ImageNode::from_atlas_image(
texture.clone(),
TextureAtlas {
layout: texture_atlas_layout.clone(),
index: 2,
},
));
});
}
```
Before this change:
<img width="529" alt="Screenshot 2024-11-21 at 11 55 45"
src="https://github.com/user-attachments/assets/23196003-08ca-4049-8409-fe349bd5aa54">
After the change:
<img width="400" alt="Screenshot 2024-11-21 at 11 54 54"
src="https://github.com/user-attachments/assets/e2cd6ebf-859c-40a1-9fc4-43bb28b024e5">
</details>
# Objective
- Fixes#16472.
## Solution
- Add flags to `SpritePlugin` and `UiPlugin` to disable their picking
backends.
## Testing
- The change is pretty trivial, so not much to test!
---
## Migration Guide
- `UiPlugin` now contains an extra `add_picking` field if
`bevy_ui_picking_backend` is enabled.
- `SpritePlugin` is no longer a unit struct, and has one field if
`bevy_sprite_picking_backend` is enabled (otherwise no fields).
# Objective
- Fixes#16469.
## Solution
- Make the picking backend features not enabled by default in each
sub-crate.
- Make features in `bevy_internal` to set the backend features
- Make the root `bevy` crate set the features by default.
## Testing
- The mesh and sprite picking examples still work correctly.
# Objective
We switch back and forwards between logical and physical coordinates all
over the place. Systems have to query for cameras and the UiScale when
they shouldn't need to. It's confusing and fragile and new scale factor
bugs get found constantly.
## Solution
* Use physical coordinates whereever possible in `bevy_ui`.
* Store physical coords in `ComputedNode` and tear out all the unneeded
scale factor calculations and queries.
* Add an `inverse_scale_factor` field to `ComputedNode` and set nodes
changed when their scale factor changes.
## Migration Guide
`ComputedNode`'s fields and methods now use physical coordinates.
`ComputedNode` has a new field `inverse_scale_factor`. Multiplying the
physical coordinates by the `inverse_scale_factor` will give the logical
values.
---------
Co-authored-by: atlv <email@atlasdostal.com>