# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_utils` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_utils` was run, and
no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_internal` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_internal` was run,
and no errors were encountered.
# Objective
Fixes#16783
## Solution
Works around a `cosmic-text` bug or limitation by triggering a re-layout
with the calculated width from the first layout run. See linked issue.
Credit to @ickshonpe for the clever solution.
## Performance
This has a significant performance impact only on unbounded text that
are not `JustifyText::Left`, which is still a bit of a bummer because
text2d performance in 0.15.1 is already not great. But this seems better
than alignment not working.
||many_text2d nfc re|many_text2d nfc re center|
|-|-|-|
|unbounded-layout-no-fix|3.06|3.10|
|unbounded-layout-fix|3.05 ⬜ -0.2%|2.71 🟥 -12.5%|
## Testing
I added a centered text to the `text2d` example.
`cargo run --example text2d`
We should look at other text examples and stress tests. I haven't tested
as thoroughly as I would like, so help testing that this doesn't break
something in UI would be appreciated.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_image` in line with the new restrictions.
## Testing
`cargo clippy --tests --package bevy_image` was run, and no errors were
encountered.
I could not run the above command with `--all-features` due to some
compilation errors with `bevy_core_pipeline` and `bevy_math` - but
hopefully CI catches anything I missed.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
- Fixes#17287
## Solution
- Added a dummy `LocalExecutor` (un)implementation to suppress
irrelevant errors.
- Added explicit `compiler_error!` when _not_ selecting either the
`async_executor` or `edge_executor` features
## Testing
- CI
# Objective
`bevy_image` appears to expect `bevy_math` to have reflection enabled.
If you attempt to build `bevy_image` without another dependency enabling
the `bevy_math/bevy_reflect` feature, then `bevy_image` will fail to
compile.
## Solution
Ideally, `bevy_image` would feature-gate all of its reflection behind a
new feature. However, for the sake of getting compilation fixed
immediately, I'm opting to specify the `bevy_math/bevy_reflect` feature
in `bevy_image`'s `Cargo.toml`.
Perhaps an upcoming PR can remove the forced `bevy_math/bevy_reflect`
feature, in favor of feature-gating `bevy_image`'s reflecton.
## Testing
`cargo clippy --package bevy_image` was ran, and no longer returns the
compilation errors that it did before.
# Objective
Stumbled upon a `from <-> form` transposition while reviewing a PR,
thought it was interesting, and went down a bit of a rabbit hole.
## Solution
Fix em
# Objective
`bevy_remote`'s reflection deserialization basically requires
`ReflectDeserialize` registrations in order to work correctly. In the
context of `bevy` (the library), this means that using `bevy_remote`
without using the `serialize` feature is a footgun, since
`#[reflect(Serialize)]` etc. are gated behind this feature.
The goal of this PR is to avoid this mistake by default.
## Solution
Make the `bevy_remote` feature enable the `serialize` feature, so that
it works as expected.
---
## Migration Guide
The `bevy_remote` feature of `bevy` now enables the `serialize` feature
automatically. If you wish to use `bevy_remote` without enabling the
`serialize` feature for Bevy subcrates, you must import `bevy_remote` on
its own.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_state` in line with the new restrictions.
## Testing
Rust-analyzer did not return any errors once the deny was added.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_scene` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_scene` was run, and
no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_pbr` in line with the new restrictions.
## Testing
`cargo clippy --tests --package bevy_pbr` was run, and no errors were
encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gltf` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_gltf` was run, and
no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_text` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_text` was run, and
no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_transform` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_transform` was run,
and no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_hierarchy` in line with the new restrictions.
## Testing
Rust-analyzer did not discern any errors.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gizmos` in line with the new restrictions.
## Testing
`cargo clippy --tests --all-features --package bevy_gizmos` was run, and
no errors were encountered.
# Objective
Both `set_metrics` and `set_size` **can** trigger text re-layout and
re-shaping, if the values provided are different form what is already in
the `Buffer`.
## Solution
Combine the `set_metrics` and `set_size` calls.
This might be a small optimization in some situations, maybe when both
font size and text bounds change in the same frame, or when spawning new
text.
I did measure a ~500 microsecond improvement in `text_system` for
`many_buttons --respawn`, but that may have just been noise.
# Objective
Rework / build on #17043 to simplify the implementation. #17043 should
be merged first, and the diff from this PR will get much nicer after it
is merged (this PR is net negative LOC).
## Solution
1. Command and EntityCommand have been vastly simplified. No more marker
components. Just one function.
2. Command and EntityCommand are now generic on the return type. This
enables result-less commands to exist, and allows us to statically
distinguish between fallible and infallible commands, which allows us to
skip the "error handling overhead" for cases that don't need it.
3. There are now only two command queue variants: `queue` and
`queue_fallible`. `queue` accepts commands with no return type.
`queue_fallible` accepts commands that return a Result (specifically,
one that returns an error that can convert to
`bevy_ecs::result::Error`).
4. I've added the concept of the "default error handler", which is used
by `queue_fallible`. This is a simple direct call to the `panic()` error
handler by default. Users that want to override this can enable the
`configurable_error_handler` cargo feature, then initialize the
GLOBAL_ERROR_HANDLER value on startup. This is behind a flag because
there might be minor overhead with `OnceLock` and I'm guessing this will
be a niche feature. We can also do perf testing with OnceLock if someone
really wants it to be used unconditionally, but I don't personally feel
the need to do that.
5. I removed the "temporary error handler" on Commands (and all code
associated with it). It added more branching, made Commands bigger /
more expensive to initialize (note that we construct it at high
frequencies / treat it like a pointer type), made the code harder to
follow, and introduced a bunch of additional functions. We instead rely
on the new default error handler used in `queue_fallible` for most
things. In the event that a custom handler is required,
`handle_error_with` can be used.
6. EntityCommand now _only_ supports functions that take
`EntityWorldMut` (and all existing entity commands have been ported).
Removing the marker component from EntityCommand hinged on this change,
but I strongly believe this is for the best anyway, as this sets the
stage for more efficient batched entity commands.
7. I added `EntityWorldMut::resource` and the other variants for more
ergonomic resource access on `EntityWorldMut` (removes the need for
entity.world_scope, which also incurs entity-lookup overhead).
## Open Questions
1. I believe we could merge `queue` and `queue_fallible` into a single
`queue` which accepts both fallible and infallible commands (via the
introduction of a `QueueCommand` trait). Is this desirable?
# Objective
Gamepad / directional navigation needs an example, for both teaching and
testing purposes.
## Solution
- Add a simple grid-based example.
- Fix an intermittent panic caused by a race condition with bevy_a11y
- Clean up small issues noticed in bevy_input_focus

## To do: this PR
- [x] figure out why "enter" isn't doing anything
- [x] change button color on interaction rather than printing
- [x] add on-screen directions
- [x] move to an asymmetric grid to catch bugs
- [x] ~~fix colors not resetting on button press~~ lol this is mostly
just a problem with hacking `Interaction` for this
- [x] swap to using observers + bubbling, rather than `Interaction`
## To do: future work
- when I increase the button size, such that there is no line break, the
text on the buttons is no longer centered :( EDIT: this is
https://github.com/bevyengine/bevy/issues/16783
- add gamepad stick navigation
- add tools to find the nearest populated quadrant to make diagonal
inputs work
- add a `add_edges` method to `DirectionalNavigationMap`
- add a `add_grid` method to `DirectionalNavigationMap`
- make the example's layout more complex and realistic
- add tools to automatically generate this list
- add button shake on failed navigation rather than printing an error
- make Pressed events easier to mock: default fields, PointerId::Focus
## Testing
`cargo run --example directional_navigation`
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
Fixes#16903.
## Solution
- Make sprite picking opt-in by requiring a new `SpritePickingCamera`
component for cameras and usage of a new `Pickable` component for
entities.
- Update the `sprite_picking` example to reflect these changes.
- Some reflection cleanup (I hope that's ok).
## Testing
Ran the `sprite_picking` example
## Open Questions
<del>
<ul>
<li>Is the name `SpritePickable` appropriate?</li>
<li>Should `SpritePickable` be in `bevy_sprite::prelude?</li>
</ul>
</del>
## Migration Guide
The sprite picking backend is now strictly opt-in using the
`SpritePickingCamera` and `Pickable` components. You should add the
`Pickable` component any entities that you want sprite picking to be
enabled for, and mark their respective cameras with
`SpritePickingCamera`.
# Objective
- Shrink `bevy_utils` more.
- Refs #11478
## Solution
- Removes `assert_object_safe` from `bevy_utils` by using a compile time
check instead.
## Testing
- CI.
---
## Migration Guide
`assert_object_safe` is no longer exported by `bevy_utils`. Instead, you
can write a compile time check that your trait is "dyn compatible":
```rust
/// Assert MyTrait is dyn compatible
const _: Option<Box<dyn MyTrait>> = None;
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Many instances of `clippy::too_many_arguments` linting happen to be on
systems - functions which we don't call manually, and thus there's not
much reason to worry about the argument count.
## Solution
Allow `clippy::too_many_arguments` globally, and remove all lint
attributes related to it.
# Objective
Fixed the issue where DragStart was triggered even when there was no
movement
https://github.com/bevyengine/bevy/issues/17230
## Solution
- When position delta is zero, don't trigger DragStart events, DragStart
is not triggered, so DragEnd is not triggered either. Everything is
fine.
## Testing
- tested with the code from the issue
---
## Migration Guide
> Fix the missing part of Drag
https://github.com/bevyengine/bevy/pull/16950
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_time` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
`cargo clippy`, `cargo clippy --package bevy_time` and `cargo test
--package bevy_time` were run, and no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_mesh` in line with the new restrictions.
## Testing
`cargo clippy --tests` and `cargo test --package bevy_mesh` were run,
and no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_winit` in line with the new restrictions.
## Testing
`cargo clippy --tests` was run, and no errors were encountered.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
`extract_shadows` uses the render world entity corresponding to the
extracted camera when it queries the main world for the camera to get
the viewport size for the responsive viewport coords resolution and
fails. This means that viewport coords get resolved based on a viewport
size of zero.
## Solution
Use the main world camera entity.
This also includes suggestions and an example on how to limit the loop
speed.
Fixes#17147.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_log` in line with the new restrictions.
## Testing
`cargo clippy --tests --package bevy_log` was run, and no errors were
encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gilrs` in line with the new restrictions.
## Testing
`cargo clippy --tests --package bevy_gilrs` was run, and no errors were
encountered.
# Objective
I never realized `clippy::type_complexity` was an allowed lint - I've
been assuming it'd generate a warning when performing my linting PRs.
## Solution
Removes any instances of `#[allow(clippy::type_complexity)]` and
`#[expect(clippy::type_complexity)]`
## Testing
`cargo clippy` ran without errors or warnings.
# Objective
In my crusade to give every lint attribute a reason, it appears I got
too complacent and copy-pasted this expect onto non-system functions.
## Solution
Fix up the reason on those non-system functions
## Testing
N/A
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_input` in line with the new restrictions.
## Testing
`cargo clippy --tests --package bevy_input` was run, and no errors were
encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_ui` in line with the new restrictions.
## Testing
`cargo clippy --tests` and `cargo test --package bevy_ui` were run, and
no errors were encountered.
# Objective
Allow tuple structs in the animated_field macro.
- for example `animated_field!(MyTupleStruct::0)`.
Fixes#16736
- This issue was partially fixed in #16747, where support for tuple
structs was added to `AnimatedField::new_unchecked`.
## Solution
Change the designator for `$field` in the macro from `ident` to `tt`.
## Testing
Expanded the doc test on `animated_field!` to include an example with a
tuple struct.
# Objective
The name `DefaultCameraView` is confusing and misleading:
* It isn't the default UI camera, which is either the camera with the
`IsDefaultUiCamera` marker component or, if no such camera is found, the
camera with the highest order which has the primary window as its render
target.
* It doesn't make sense to call it a "default", every active 2d and 3d
camera is given its own `DefaultCameraView`.
* The name doesn't make it clear that it's UI specific component.
## Solution
Rename `DefaultCameraView` to `UiCameraView`, add a doc comment for it
and rename a few other fields and variables.
## Migration Guide
`DefaultCameraView` has been renamed to `UiCameraView`
# Objective
- Commands like `cargo bench -- --save-baseline before` do not work
because the default `libtest` is intercepting Criterion-specific CLI
arguments.
- Fixes#17200.
## Solution
- Disable the default `libtest` benchmark harness for the library crate,
as per [the Criterion
book](https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options).
## Testing
- `cargo bench -p benches -- --save-baseline before`
- You don't need to run the entire benchmarks, just make sure that they
start without any errors. :)
# Objective & Solution
- Update `downcast-rs` to the latest version, 2.
- Disable (new) `sync` feature to improve compatibility with atomically
challenged platforms.
- Remove stub `downcast-rs` alternative code from `bevy_app`
## Testing
- CI
## Notes
The only change from version 1 to version 2 is the addition of a new
`sync` feature, which allows disabling the `DowncastSync` parts of
`downcast-rs`, which require access to `alloc::sync::Arc`, which is not
available on atomically challenged platforms. Since Bevy makes no use of
the functionality provided by the `sync` feature, I've disabled it in
all crates. Further details can be found
[here](https://github.com/marcianx/downcast-rs/pull/22).
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_window` in line with the new restrictions.
## Testing
`cargo clippy --tests` was run, and no errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_ptr` in line with the new restrictions.
## Testing
`cargo clippy --tests` was run, and no errors were encountered.
I was expecting this crate to give more of a fight.
# Objective
- Allow other crates to use `TextureAtlas` and friends without needing
to depend on `bevy_sprite`.
- Specifically, this allows adding `TextureAtlas` support to custom
cursors in https://github.com/bevyengine/bevy/pull/17121 by allowing
`bevy_winit` to depend on `bevy_image` instead of `bevy_sprite` which is
a [non-starter].
[non-starter]:
https://github.com/bevyengine/bevy/pull/17121#discussion_r1904955083
## Solution
- Move `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`,
`TextureAtlasLayout` and `DynamicTextureAtlasBuilder` into `bevy_image`.
- Add a new plugin to `bevy_image` named `TextureAtlasPlugin` which
allows us to register `TextureAtlas` and `TextureAtlasLayout` which was
previously done in `SpritePlugin`. Since `SpritePlugin` did the
registration previously, we just need to make it add
`TextureAtlasPlugin`.
## Testing
- CI builds it.
- I also ran multiple examples which hopefully covered any issues:
```
$ cargo run --example sprite
$ cargo run --example text
$ cargo run --example ui_texture_atlas
$ cargo run --example sprite_animation
$ cargo run --example sprite_sheet
$ cargo run --example sprite_picking
```
---
## Migration Guide
The following types have been moved from `bevy_sprite` to `bevy_image`:
`TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`,
`TextureAtlasLayout` and `DynamicTextureAtlasBuilder`.
If you are using the `bevy` crate, and were importing these types
directly (e.g. before `use bevy::sprite::TextureAtlas`), be sure to
update your import paths (e.g. after `use bevy::image::TextureAtlas`)
If you are using the `bevy` prelude to import these types (e.g. `use
bevy::prelude::*`), you don't need to change anything.
If you are using the `bevy_sprite` subcrate, be sure to add `bevy_image`
as a dependency if you do not already have it, and be sure to update
your import paths.
## Objective
Fixes#2004Fixes#3845Fixes#7118Fixes#10166
## Solution
- The crux of this PR is the new `Command::with_error_handling` method.
This wraps the relevant command in another command that, when applied,
will apply the original command and handle any resulting errors.
- To enable this, `Command::apply` and `EntityCommand::apply` now return
`Result`.
- `Command::with_error_handling` takes as a parameter an error handler
of the form `fn(&mut World, CommandError)`, which it passes the error
to.
- `CommandError` is an enum that can be either `NoSuchEntity(Entity)` or
`CommandFailed(Box<dyn Error>)`.
### Closures
- Closure commands can now optionally return `Result`, which will be
passed to `with_error_handling`.
### Commands
- Fallible commands can be queued with `Commands::queue_fallible` and
`Commands::queue_fallible_with`, which call `with_error_handling` before
queuing them (using `Commands::queue` will queue them without error
handling).
- `Commands::queue_fallible_with` takes an `error_handler` parameter,
which will be used by `with_error_handling` instead of a command's
default.
- The `command` submodule provides unqueued forms of built-in fallible
commands so that you can use them with `queue_fallible_with`.
- There is also an `error_handler` submodule that provides simple error
handlers for convenience.
### Entity Commands
- `EntityCommand` now automatically checks if the entity exists before
executing the command, and returns `NoSuchEntity` if it doesn't.
- Since all entity commands might need to return an error, they are
always queued with error handling.
- `EntityCommands::queue_with` takes an `error_handler` parameter, which
will be used by `with_error_handling` instead of a command's default.
- The `entity_command` submodule provides unqueued forms of built-in
entity commands so that you can use them with `queue_with`.
### Defaults
- In the future, commands should all fail according to the global error
handling setting. That doesn't exist yet though.
- For this PR, commands all fail the way they do on `main`.
- Both now and in the future, the defaults can be overridden by
`Commands::override_error_handler` (or equivalent methods on
`EntityCommands` and `EntityEntryCommands`).
- `override_error_handler` takes an error handler (`fn(&mut World,
CommandError)`) and passes it to every subsequent command queued with
`Commands::queue_fallible` or `EntityCommands::queue`.
- The `_with` variants of the queue methods will still provide an error
handler directly to the command.
- An override can be reset with `reset_error_handler`.
## Future Work
- After a universal error handling mode is added, we can change all
commands to fail that way by default.
- Once we have all commands failing the same way (which would require
either the full removal of `try` variants or just making them useless
while they're deprecated), `queue_fallible_with_default` could be
removed, since its only purpose is to enable commands having different
defaults.
# Objective
The debug features (`DebugPickingPlugin`) from `bevy_mod_picking` were
not upstreamed with the rest of the core changes, this PR reintroduces
it for usage inside `bevy_dev_tools`
## Solution
Vast majority of this code is taken as-is from `bevy_mod_picking` aside
from changes to ensure compilation and code style, as such @aevyrie was
added as the co-author for this change.
### Main changes
* `multiselection` support - the relevant code was explicitly not
included in the process of upstreaming the rest of the package, so it
also has been omitted here.
* `bevy_egui` support - the old package had a preference for using
`bevy_egui` instead of `bevy_ui` if possible, I couldn't see a way to
support this in a core crate, so this has been removed.
Relevant code has been added to the `bevy_dev_tools` crate instead of
`bevy_picking` as it is a better fit and requires a dependency on
`bevy_ui` for drawing debug elements.
### Minor changes
* Changed the debug text size from `60` to `12` as the former was so
large as to be unreadable in the new example.
## Testing
* `cargo run -p ci`
* Added a new example in `dev_tools/picking_debug` and visually verified
the in-window results and the console messages
---------
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Remove some outdated docs from 0.15 that mention a removed function.
## Solution
In `pbr_functions.wgsl`, I think it's fine to just remove the mention.
In `meshlet/asset.rs`, I think it would be nice to still have a note on
how texture samples should be done. Unfortunately, there isn't a nice
abstraction for it any more. Current workaround, for reference:
b386d08d0f/crates/bevy_pbr/src/render/pbr_fragment.wgsl (L184-L208)
For now, I've just removed the mention.
# Objective
- Add the original source for Oklab calculations (a blog from the
creator of Oklab) instead of linking to other Rust crates.
## Solution
- Update the links.
# Objective
- Fixes#12562
- Fixes#12195
## Solution
- Use `spawn_app` instead of `run_app` for web platform in
`winit_runner` as suggested in the
[document](https://docs.rs/winit/latest/winit/platform/web/trait.EventLoopExtWebSys.html#tymethod.spawn_app)
## Testing
- Did you test these changes? If so, how?
Tested on web. Created a react app which renders the bevy WASM app and
returns the disposer to JS. Js will call the disposer on component
unmount to stop the app, the disposer sends a signal to a `signal`
receiver in rust which exits the app like this:
```rust
fn handle_stop_signal(
signal: NonSendMut<StopSignalReceiver>,
window_entities: Query<(Entity, &Window)>,
mut event_writer: EventWriter<WindowCloseRequested>,
) {
if let Ok(_) = signal.try_recv() {
for (entity, _window) in window_entities.iter() {
info!("closing window entity: {:x}", entity.to_bits());
event_writer.send(WindowCloseRequested { window: entity });
}
}
}
```
- 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?
- Are all resources released after stopping the app like this? The WASM
is still loaded, the LogPlugin complains on the logger
re-initialization, but it's a warning anyway.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- Tested the WASM version on web platform and the native version on
MacOS.
---------
Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
# Objective
- Allow users to customize the line height of text.
- Implements #16085
## Solution
- Add a `line_height` field to `TextFont` to feed into `cosmic_text`'s
`Metrics`.
## Testing
- Tested on my own game, and worked exactly as I wanted.
- My game is only 2D, so I only tested `Text2d`. `Text` still needs
tested, but I imagine it'll work fine.
- An example is available
[here](https://code.cartoon-aa.xyz/Cyborus/custom-line-height-example)
---
## Showcase
<details>
<summary>Click to view showcase</summary>
With font:
```rust
TextFont {
font: /* unimportant */,
font_size: 16.0,
line_height: None,
..default()
}
```

With font:
```rust
TextFont {
font: /* unimportant */,
font_size: 16.0,
line_height: Some(16.0),
..default()
}
```

</details>
## Migration Guide
`TextFont` now has a `line_height` field. Any instantiation of
`TextFont` that doesn't have `..default()` will need to add this field.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_render` in line with the new restrictions.
## Testing
`cargo clippy` and `cargo test --package bevy_render` were run, and no
errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_diagnostic` in line with the new restrictions.
## Testing
`cargo clippy` and `cargo test --package bevy_diagnostic` were run, and
no errors were encountered.
# Objective
https://github.com/bevyengine/bevy/pull/16338 forgot to remove this
previously-deprecated item. In fact, it only removed the `#[deprecated]`
attribute attached to it.
## Solution
Removes `bevy_core_pipeline::core_2d::Camera2dBundle`.
## Testing
CI.
I broke the commit history on the other one,
https://github.com/bevyengine/bevy/pull/17160. Woops.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_sprite` in line with the new restrictions.
## Testing
`cargo clippy` and `cargo test --package bevy_sprite` were run, and no
errors were encountered.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_asset` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
`cargo clippy` and `cargo test --package bevy_asset --features
multi_threaded` were run, and no errors were encountered.
# Objective
Cleanup `EntityRef`, `EntityMut`, and `EntityWorldMut` in preparation
for my "Scoped Entity References" PR.
## Solution
- Switched `EntityRef`/`EntityMut` from tuple structs to normal ones.
- Ensured all conversion trait impls use the same `entity` argument
name.
- Replaced some `unsafe` with delegated calls from `EntityMut` to
`EntityRef`
- Added `EntityMut::into_readonly` to make the replacements clearer
- Replaced some `unsafe` with delegated calls from `EntityWorldMut` to
`EntityMut` and `EntityRef`
- Added `EntityWorldMut::into_readonly`, `::as_readonly`,
`::into_mutable`, `::as_mutable` to make the replacements clearer
## Testing
Reusing current tests.
# Objective
There is a large performance regression in the UI systems in 0.15
because the `UiChildren` and `UiRootRootNodes` system params (even with
`ghost_nodes` disabled) are really inefficient compared to regular
queries and can trigger a heap allocation with large numbers of
children.
## Solution
Replace the `UiChildren` and `UiRootRootNodes` system params with
simplified versions when the `ghost_nodes` feature is disabled.
## Testing
yellow this PR, red main
cargo run --example many_buttons --features "trace_tracy" --release
`ui_stack_system`
<img width="494" alt="stack"
src="https://github.com/user-attachments/assets/4a09485f-0ded-4e54-bd47-ffbce869051a"
/>
`ui_layout_system`
<img width="467" alt="unghosted"
src="https://github.com/user-attachments/assets/9d906b20-66b6-4257-9eef-578de1827628"
/>
`update_clipping_system`
<img width="454" alt="clipping"
src="https://github.com/user-attachments/assets/320b50e8-1a1d-423a-95a0-42799ae72fc5"
/>
# Objective
- I want to hide the clock and the battery indicator on iOS
## Solution
- Add the platform specific property `prefers_status_bar_hidden` on
Window creation, and map it to `with_prefers_status_bar_hidden` in
winit.
## Testing
- Tested on iOS
# Objective
the `get` function on [`InstanceInputUniformBuffer`] seems very
error-prone. This PR hopes to fix this.
## Solution
Do a few checks to ensure the index is in bounds and that the `BDI` is
not removed.
Return `Option<BDI>` instead of `BDI`.
## Testing
- Did you test these changes? If so, how?
added a test to verify that the instance buffer works correctly
## Future Work
Performance decreases when using .binary_search(). However this is
likely due to the fact that [`InstanceInputUniformBuffer::get`] for now
is never used, and only get_unchecked.
## Migration Guide
`InstanceInputUniformBuffer::get` now returns `Option<BDI>` instead of
`BDI` to reduce panics. If you require the old functionality of
`InstanceInputUniformBuffer::get` consider using
`InstanceInputUniformBuffer::get_unchecked`.
---------
Co-authored-by: Tim Overbeek <oorbeck@gmail.com>
# Objective
Found more excessive `DefaultUiCamera` queries outside of extraction.
The default UI camera lookup only needs to be done once. Do it first,
not per node.
---------
Co-authored-by: MichiRecRoom <1008889+LikeLakers2@users.noreply.github.com>
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
`cargo clippy` and `cargo test --package bevy_audio` were run, and no
errors were encountered.
Related to https://github.com/bevyengine/bevy/pull/16843
Since `WorldQuery::Fetch` is `Clone`, it can't store mutable references
to resources, so it doesn't make sense to mutably access resources. In
that sense, it is hard to find usecases of mutably accessing resources
and to clearly define, what mutably accessing resources would mean, so
it's been decided to disallow write resource access.
Also changed documentation of safety requirements of
`WorldQuery::init_fetch` and `WorldQuery::fetch` to clearly state to the
caller, what safety invariants they need to uphold.
# Objective
The original fix (bevyengine/bevy#11870) did not actually implement the
described logic. It checked if there were independently multiple loaders
for a given asset type and multiple loaders for a given extension.
However, this did not handle the case where those loaders were not the
same. For example, there could be a loader for type `Foo` and extension
`.foo`. Anther loader could exist for type `Bar` but extension `.bar`.
If a third loader was added for type `Foo` but extension `.bar`, the
warning would have been incorrectly logged.
## Solution
Instead of independently checking to see if there are preexisting
loaders for both the extension and type, look up the indices of the
loaders for the type in question. Then check to see if the loaders
registered for the extensions has any overlap. Only log if there are
loaders that fit this criteria.
## Testing
Ran CI tests. Locally tested the situation describe in the objective
section for the normal `App::init_asset_loader` flow. I think testing
could be done on the pre-registration flow for loaders still. I tested
on Windows, but the changes should not be affected by platform.
# Objective
While directional navigation is helpful for UI in general for
accessibility reasons, it is *especially* valuable for a game engine,
where menus may be navigated primarily or exclusively through the use of
a game controller.
Thumb-stick powered cursor-based navigation can work as a fallback, but
is generally a pretty poor user experience. We can do better!
## Prior art
Within Bevy, https://github.com/nicopap/ui-navigation and
https://github.com/rparrett/bevy-alt-ui-navigation-lite exist to solve
this same problem. This isn't yet a complete replacement for that
ecosystem, but hopefully we'll be there for 0.16.
## Solution
UI navigation is complicated, and the right tradeoffs will vary based on
the project and even the individual scene.
We're starting with something simple and flexible, hooking into the
existing `InputFocus` resource, and storing a manually constructed graph
of entities to explore in a `DirectionalNavigationMap` resource. The
developer experience won't be great (so much wiring to do!), but the
tools are all there for a great user experience.
We could have chosen to represent these linkages via component-flavored
not-quite-relations. This would be useful for inspectors, and would give
us automatic cleanup when the entities were despawned, but seriously
complicates the developer experience when building and checking this
API. For now, we're doing a dumb "entity graph in a resource" thing and
`remove` helpers. Once relations are added, we can re-evaluate.
I've decided to use a `CompassOctant` as our key for the possible paths.
This should give users a reasonable amount of precise control without
being fiddly, and playing reasonably nicely with arrow-key navigation.
This design lets us store the set of entities that we're connected to as
a 8-byte array (yay Entity-niching). In theory, this is maybe nicer than
the double indirection of two hashmaps. but if this ends up being slow
we should create benchmarks.
To make this work more pleasant, I've added a few utilities to the
`CompassOctant` type: converting to and from usize, and adding a helper
to find the 180 degrees opposite direction. These have been mirrored
onto `CompassQuadrant` for consistency: they should be generally useful
for game logic.
## Future work
This is a relatively complex initiative! In the hopes of easing review
and avoiding merge conflicts, I've opted to split this work into
bite-sized chunks.
Before 0.16, I'd like to have:
- An example demonstrating gamepad and tab-based navigation in a
realistic game menu
- Helpers to convert axis-based inputs into compass quadrants / octants
- Tools to check the listed graph desiderata
- A helper to build a graph from a grid of entities
- A tool to automatically build a graph given a supplied UI layout
One day, it would be sweet if:
- We had an example demonstrating how to use focus navigation in a
non-UI scene to cycle between game objects
- Standard actions for tab-style and directional navigation with a
first-party bevy_actions integration
- We had a visual debugging tool to display these navigation graphs for
QC purposes
- There was a built-in way to go "up a level" by cancelling the current
action
- The navigation graph is built completely out of relations
## Testing
- tests for the new `CompassQuadrant` / `CompassOctant` methods
- tests for the new directional navigation module
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# 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.
# Objective
- I'm compiling (parts of) bevy for an embedded platform with no 64bit
atomic and ctrlc handler support. Some compilation errors came up. This
PR contains the fixes for those.
- Fix depth_bias casting in PBR material (Fixes#14169)
- Negative depth_bias values were casted to 0 before this PR
- f32::INFINITY depth_bias value was casted to -1 before this PR
## Solutions
- Restrict 64bit atomic reflection to supported platforms
- Restrict ctrlc handler to supported platforms (linux, windows or macos
instead of "not wasm")
- The depth bias value (f32) is first casted to i32 then u64 in order to
preserve negative values
## Testing
- This version compiles on a platform with no 64bit atomic support, and
no ctrlc support
- CtrlC handler still works on Linux and Windows (I can't test on Macos)
- depth_bias:
```rust
println!("{}",f32::INFINITY as u64 as i32); // Prints: -1 (old implementation)
println!("{}",f32::INFINITY as i32 as u64 as i32); // Prints: 2147483647 (expected, new implementation)
```
Also ran a modified version of 3d_scene example with the following
results:
RED cube depth_bias: -1000.0
BLUE cube depth_bias: 0.0

RED cube depth_bias: -INF
BLUE cube depth_bias: 0.0

RED cube depth_bias: INF (case reported in #14169)
BLUE cube depth_bias: 0.0
(Im not completely sure whats going on with the shadows here, it seems
like depth_bias has some affect to those aswell, if this is
unintentional this issue was not introduced by this PR)

Currently, our batchable binned items are stored in a hash table that
maps bin key, which includes the batch set key, to a list of entities.
Multidraw is handled by sorting the bin keys and accumulating adjacent
bins that can be multidrawn together (i.e. have the same batch set key)
into multidraw commands during `batch_and_prepare_binned_render_phase`.
This is reasonably efficient right now, but it will complicate future
work to retain indirect draw parameters from frame to frame. Consider
what must happen when we have retained indirect draw parameters and the
application adds a bin (i.e. a new mesh) that shares a batch set key
with some pre-existing meshes. (That is, the new mesh can be multidrawn
with the pre-existing meshes.) To be maximally efficient, our goal in
that scenario will be to update *only* the indirect draw parameters for
the batch set (i.e. multidraw command) containing the mesh that was
added, while leaving the others alone. That means that we have to
quickly locate all the bins that belong to the batch set being modified.
In the existing code, we would have to sort the list of bin keys so that
bins that can be multidrawn together become adjacent to one another in
the list. Then we would have to do a binary search through the sorted
list to find the location of the bin that was just added. Next, we would
have to widen our search to adjacent indexes that contain the same batch
set, doing expensive comparisons against the batch set key every time.
Finally, we would reallocate the indirect draw parameters and update the
stored pointers to the indirect draw parameters that the bins store.
By contrast, it'd be dramatically simpler if we simply changed the way
bins are stored to first map from batch set key (i.e. multidraw command)
to the bins (i.e. meshes) within that batch set key, and then from each
individual bin to the mesh instances. That way, the scenario above in
which we add a new mesh will be simpler to handle. First, we will look
up the batch set key corresponding to that mesh in the outer map to find
an inner map corresponding to the single multidraw command that will
draw that batch set. We will know how many meshes the multidraw command
is going to draw by the size of that inner map. Then we simply need to
reallocate the indirect draw parameters and update the pointers to those
parameters within the bins as necessary. There will be no need to do any
binary search or expensive batch set key comparison: only a single hash
lookup and an iteration over the inner map to update the pointers.
This patch implements the above technique. Because we don't have
retained bins yet, this PR provides no performance benefits. However, it
opens the door to maximally efficient updates when only a small number
of meshes change from frame to frame.
The main churn that this patch causes is that the *batch set key* (which
uniquely specifies a multidraw command) and *bin key* (which uniquely
specifies a mesh *within* that multidraw command) are now separate,
instead of the batch set key being embedded *within* the bin key.
In order to isolate potential regressions, I think that at least #16890,
#16836, and #16825 should land before this PR does.
## Migration Guide
* The *batch set key* is now separate from the *bin key* in
`BinnedPhaseItem`. The batch set key is used to collect multidrawable
meshes together. If you aren't using the multidraw feature, you can
safely set the batch set key to `()`.
# Objective
Ensure the deny lint attributes added as a result of #17111 point to the
tracking issue.
## Solution
Change all existing instances of:
```rust
#![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
```
to
```rust
#![deny(
clippy::allow_attributes,
clippy::allow_attributes_without_reason,
reason = "See #17111; To be removed once all crates are in-line with these attributes"
)]
```
## Testing
N/A
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.
Some hardware and driver combos, such as Intel Iris Xe, have low limits
on the numbers of samplers per shader, causing an overflow. With
first-class bindless arrays, `wgpu` should be able to work around this
limitation eventually, but for now we need to disable bindless materials
on those platforms.
This is an alternative to PR #17107 that calculates the precise number
of samplers needed and compares to the hardware sampler limit,
transparently falling back to non-bindless if the limit is exceeded.
Fixes#16988.
# Objective
- Contributes to #11478
- Contributes to #16877
## Solution
- Removed everything except `Instant` from `bevy_utils::time`
## Testing
- CI
---
## Migration Guide
If you relied on any of the following from `bevy_utils::time`:
- `Duration`
- `TryFromFloatSecsError`
Import these directly from `core::time` regardless of platform target
(WASM, mobile, etc.)
If you relied on any of the following from `bevy_utils::time`:
- `SystemTime`
- `SystemTimeError`
Instead import these directly from either `std::time` or `web_time` as
appropriate for your target platform.
## Notes
`Duration` and `TryFromFloatSecsError` are both re-exports from
`core::time` regardless of whether they are used from `web_time` or
`std::time`, so there is no value gained from re-exporting them from
`bevy_utils::time` as well. As for `SystemTime` and `SystemTimeError`,
no Bevy internal crates or examples rely on these types. Since Bevy
doesn't have a `Time<Wall>` resource for interacting with wall-time (and
likely shouldn't need one), I think removing these from `bevy_utils`
entirely and waiting for a use-case to justify inclusion is a reasonable
path forward.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
`cargo clippy`, `cargo clippy --package bevy_dev_tools` and cargo test
--package bevy_dev_tools` were run, and no errors were encountered.
(Except for one warning from bevy_sprite, but I plan to fix that when I
get to bevy_sprite)
# Objective
Optimization for sprite picking
## Solution
Use `radsort` for the sort.
We already have `radsort` in tree for sorting various phase items
(including `Transparent2d` / sprites). It's a stable parallel radix
sort.
## Testing
Tested on an M1 Max.
`cargo run --example sprite_picking`
`cargo run --example bevymark --release --features=trace,trace_tracy --
--waves 100 --per-wave 1000 --benchmark`
<img width="983" alt="image"
src="https://github.com/user-attachments/assets/0f7a8c3a-006b-4323-a2ed-03788918dffa"
/>
# Objective
While checking over https://github.com/bevyengine/bevy/pull/17160, it
occurred to me that rust-analyzer will copy the method signature
exactly, when using tab completion trait methods. This includes provided
trait methods that use underscores to silence the `unused_variables`
lint. This probably isn't good for users, seeing as how they'll have to
remove the underscore if they want to use the parameters.
(I mean, they technically don't have to remove the underscore... but
usually you don't keep a leading underscore on parameters you're using.)
## Solution
Changes `bevy_reflect::RegisterForReflection::__register()` to
`#[expect(unused_variables)]`, and removes the underscores from its
parameter names.
## Testing
N/A
# Objective
- `GetPath` `path` related methods allow an empty string as the
parameter, but this is not included as a test or in documentation. This
PR adds both.
- Fixes#13459
## Solution
- Updates the `bevy_reflect` `GetPath` documentation and unit tests
## Testing
- `cargo run -p ci`
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
Improve DAG building for virtual geometry
## Solution
- Use METIS to group triangles into meshlets which lets us minimize
locked vertices which improves simplification, instead of using meshopt
which prioritizes culling efficiency. Also some other minor tweaks.
- Currently most meshlets have 126 triangles, and not 128. Fixing this
might involve calling METIS recursively ourselves to manually bisect the
graph, not sure. Not going to attempt to fix this in this PR.
## Testing
- Did you test these changes? If so, how?
- Tested on bunny.glb and cliff.glb
- 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?
- Download the new bunny asset, run the meshlet example.
---
## Showcase
New

Old

---------
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
# Objective
- As stated in the linked issue, if a Mesh2D is drawn with elements with
a positive Z value, resulting gizmos get drawn behind instead of in
front of them.
- Fixes#17053
## Solution
- Similar to the change done for the `SpritePipeline` in the relevant
commit (5abc32ceda), this PR changes both
line gizmos to avoid writing to the depth buffer and always pass the
depth test to ensure they are not filtered out.
## Testing
- Tested with the provided snippet in #17053
- I looked over the `2d_gizmos` example, but it seemed like adding more
elements there to demonstrate this might not be the best idea? Looking
for guidance here on if that should be updated or if a new gizmo example
needs to be made.
# Objective
- https://github.com/bevyengine/bevy/issues/17111
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
## Objective
The error `EntityFetchError::NoSuchEntity` has an `UnsafeWorldCell`
inside it, which it uses to call
`Entities::entity_does_not_exist_error_details_message` when being
printed. That method returns a `String` that, if the `track_location`
feature is enabled, contains the location of whoever despawned the
relevant entity.
I initially had to modify this error while working on #17043. The
`UnsafeWorldCell` was causing borrow problems when being returned from a
command, so I tried replacing it with the `String` that the method
returns, since that was the world cell's only purpose.
Unfortunately, `String`s are slow, and it significantly impacted
performance (on top of that PR's performance hit):
<details>
<summary>17043 benchmarks</summary>
### With `String`

### No `String`

</details>
For that PR, I just removed the error details entirely, but I figured
I'd try to find a way to keep them around.
## Solution
- Replace the `String` with a helper struct that holds the location, and
only turn it into a string when someone actually wants to print it.
- Replace the `UnsafeWorldCell` with the aforementioned struct.
- Do the same for `QueryEntityError::NoSuchEntity`.
## Benchmarking
This had some interesting performance impact:
<details>
<summary>This PR vs main</summary>



</details>
## Other work
`QueryEntityError::QueryDoesNotMatch` also has an `UnsafeWorldCell`
inside it. This one would be more complicated to rework while keeping
the same functionality.
## Migration Guide
The errors `EntityFetchError::NoSuchEntity` and
`QueryEntityError::NoSuchEntity` now contain an
`EntityDoesNotExistDetails` struct instead of an `UnsafeWorldCell`. If
you were just printing these, they should work identically.
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
Fixes#17098
It seems that it's not totally obvious how to fix this, but that
reverting might be part of the solution anyway.
Let's get the repo back into a working state.
## Solution
Revert the [recent
optimization](https://github.com/bevyengine/bevy/pull/17078) that broke
"many-to-one main->render world entities" for 2d.
## Testing
`cargo run --example text2d`
`cargo run --example sprite_slice`
# Objective
Fixes#3450
## Solution
Scale the input to account for the range
## Testing
Updated unit tests
## Migration Guide
`GamepadButtonChangedEvent.value` is now linearly rescaled to be from
`0.0..=1.0` (instead of `low..=high`) and
`GamepadAxisChangedEvent.value` is now linearly rescaled to be from
`-1.0..=0.0`/`0.0..=1.0` (accounting for the deadzone).
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_reflect` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
# Objective
Remove the reliance on `#[allow(clippy::excessive_precision)]`.
## Solution
Remove the `#[allow(clippy::excessive_precision)]`, and truncate the
float literals to the value rustc would normally truncate them to.
## Testing
I ran `cargo test -p bevy_color`, and received no errors.
# Objective
Use the latest version of `typos` and fix the typos that it now detects
# Additional Info
By the way, `typos` has a "low priority typo suggestions issue" where we
can throw typos we find that `typos` doesn't catch.
(This link may go stale) https://github.com/crate-ci/typos/issues/1200
# Background
In `no_std` compatible crates, there is often an `std` feature which
will allow access to the standard library. Currently, with the `std`
feature _enabled_, the
[`std::prelude`](https://doc.rust-lang.org/std/prelude/index.html) is
implicitly imported in all modules. With the feature _disabled_, instead
the [`core::prelude`](https://doc.rust-lang.org/core/prelude/index.html)
is implicitly imported. This creates a subtle and pervasive issue where
`alloc` items _may_ be implicitly included (if `std` is enabled), or
must be explicitly included (if `std` is not enabled).
# Objective
- Make the implicit imports for `no_std` crates consistent regardless of
what features are/not enabled.
## Solution
- Replace the `cfg_attr` "double negative" `no_std` attribute with
conditional compilation to _include_ `std` as an external crate.
```rust
// Before
#![cfg_attr(not(feature = "std"), no_std)]
// After
#![no_std]
#[cfg(feature = "std")]
extern crate std;
```
- Fix imports that are currently broken but are only now visible with
the above fix.
## Testing
- CI
## Notes
I had previously used the "double negative" version of `no_std` based on
general consensus that it was "cleaner" within the Rust embedded
community. However, this implicit prelude issue likely was considered
when forming this consensus. I believe the reason why is the items most
affected by this issue are provided by the `alloc` crate, which is
rarely used within embedded but extensively used within Bevy.
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_tasks` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
# Objective
Fix incorrect comment on `IntoSystemSetConfigs::after` likely caused by
copy-paste error. It said "before" instead of "after".
## Solution
Update the comment to the correct text.
## Testing
CI tests pass. This is just updating a comment.
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_math` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_a11y` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_animation` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good
## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_reflect` in line with the new restrictions.
No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.
## Testing
I ran `cargo clippy`, and received no errors.
# 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
Just being fussy but I hate this `.map(|v|
v.is_some()).unwrap_or(false)` stuff.
## Solution
Reduce it using `and_then`.
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
Fix some outdated `bevy_state` documentation examples.
## Solution
- updated some doc examples in `bevy_state` that hadn't been updated
with the API.
- fixed an outdated link in the documentation issue template that
referred to a 404 page instead of the contribution guide.
## Testing
No necessary testing aside from the usual doctests.
---
## Showcase
N/A
## Migration Guide
N/A
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `bevy_reflect` (default)
- `libm`
## Testing
- CI
## Notes
- `bevy_reflect` was previously always enabled, which isn't how most
other crates handle reflection. I've brought this in line with how most
crates gate `bevy_reflect`. This is where the majority of the changes
come from in this PR.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# 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
- As stated in the related issue, this PR is to better align the feature
flag name with what it actually does and the plans for the future.
- Fixes#16852
## Solution
- Simple find / replace
## Testing
- Local run of `cargo run -p ci`
## Migration Guide
The `track_change_detection` feature flag has been renamed to
`track_location` to better reflect its extended capabilities.
# Objective
- Fix sprite rendering performance regression since retained render
world changes
- The retained render world changes moved `ExtractedSprites` from using
the highly-optimised `EntityHasher` with an `Entity` to using
`FixedHasher` with `(Entity, MainEntity)`. This was enough to regress
framerate in bevymark by 25%.
## Solution
- Move the render world entity into a member of `ExtractedSprite` and
change `ExtractedSprites` to use `MainEntityHashMap` for its storage
- Disable sprite picking in bevymark
## Testing
M4 Max. `bevymark --waves 100 --per-wave 1000 --benchmark`. main in
yellow vs PR in red:
<img width="590" alt="Screenshot 2025-01-01 at 16 36 22"
src="https://github.com/user-attachments/assets/1e4ed6ec-3811-4abf-8b30-336153737f89"
/>
20.2% median frame time reduction.
<img width="594" alt="Screenshot 2025-01-01 at 16 38 37"
src="https://github.com/user-attachments/assets/157c2022-cda6-4cf2-bc63-d0bc40528cf0"
/>
49.7% median extract_sprites execution time reduction.
Comparing 0.14.2 yellow vs PR red:
<img width="593" alt="Screenshot 2025-01-01 at 16 40 06"
src="https://github.com/user-attachments/assets/abd59b6f-290a-4eb6-8835-ed110af995f3"
/>
~6.1% median frame time reduction.
---
## Migration Guide
- `ExtractedSprites` is now using `MainEntityHashMap` for storage, which
is keyed on `MainEntity`.
- The render world entity corresponding to an `ExtractedSprite` is now
stored in the `render_entity` member of it.
# 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
Tab navigation can fail in all manner of ways. The current API
recognizes this, but merely logs a warning and returns `None`.
We should supply the actual reason for failure to the caller, so they
can handle it in whatever fashion they please (including logging a
warning!).
Swapping to a Result-oriented pattern is also a bit more idiomatic and
makes the code's control flow easier to follow.
## Solution
- Refactor the `tab_navigation` module to return a `Result` rather than
an `Option` from its key APIs.
- Move the logging to the provided prebuilt observer. This leaves the
default behavior largely unchanged, but allows for better user control.
- Make the case where no tab group was found for the currently focused
entity an error branch, but provide enough information that we can still
recover from it.
## Testing
The `tab_navigation` example continues to function as intended.
# Objective
Resolves#17064
## Solution
- Bevy no longer converts asset file extensions to lowercase before
trying to resolve an asset loader
## Testing
- I adapted the `custom_asset` example (see comment in #17064)
- The changes were tested on Linux
As far as I know, Windows has a case-insensitive file system by default,
so case-sensitive asset file extensions are probably bad practice in a
game. But we should be case-sensitive everywhere or handle asset paths
completely case-insensitive.
Before this PR:
* asset loader extensions are case-sensitive
* asset file names are case-sensitive
* asset file extensions are converted to lowercase ⚡
Now everything should be case-sensitive
# Objective
Following #16876, `bevy_input_focus` works with more than just keyboard
inputs! The docs should reflect that.
## Solution
Fix a few missed mentions in the documentation.
Also add a brief reference to navigation frameworks within the module
docs to help give more breadcrumbs.
# Objective
- Support more ergonomic conditional updates for types that can be
modified by `clone_into`.
## Solution
- Use `ToOwned::clone_into` to copy a reference provided by the caller
in `Mut::clone_from_if_neq`.
## Testing
- See doc tests.
# Objective
- #16589 added an enum to switch between fallible and infallible system.
This branching should be unnecessary if we wrap infallible systems in a
function to return `Ok(())`.
## Solution
- Create a wrapper system for `System<(), ()>`s that returns `Ok` on the
call to `run` and `run_unsafe`. The wrapper should compile out, but I
haven't checked.
- I removed the `impl IntoSystemConfigs for BoxedSystem<(), ()>` as I
couldn't figure out a way to keep the impl without double boxing.
## Testing
- ran `many_foxes` example to check if it still runs.
## Migration Guide
- `IntoSystemConfigs` has been removed for `BoxedSystem<(), ()>`. Either
use `InfallibleSystemWrapper` before boxing or make your system return
`bevy::ecs::prelude::Result`.
# Objective
It is not obvious that one would know these:
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": [
"bevy_animation::AnimationPlayer",
"bevy_animation::AnimationTarget",
"bevy_animation::graph::AnimationGraphHandle",
"bevy_animation::transition::AnimationTransitions",
"bevy_audio::audio::PlaybackSettings",
"bevy_audio::audio::SpatialListener",
"bevy_core_pipeline::bloom::settings::Bloom",
"bevy_core_pipeline::contrast_adaptive_sharpening::ContrastAdaptiveSharpening",
**... snipping for brevity ...**
"bevy_ui::ui_node::Node",
"bevy_ui::ui_node::Outline",
"bevy_ui::ui_node::ScrollPosition",
"bevy_ui::ui_node::TargetCamera",
"bevy_ui::ui_node::UiAntiAlias",
"bevy_ui::ui_node::ZIndex",
"bevy_ui::widget::button::Button",
"bevy_window::monitor::Monitor",
"bevy_window:🪟:PrimaryWindow",
"bevy_window:🪟:Window",
"bevy_winit::cursor::CursorIcon",
"server::Cube"
]
}
```
Especially if you for example, are reading the GH examples because:

If you for example expand these things, due to the number of places bevy
re-exports things you'll find it difficult to find the true path of
something.
i.e you'd probably be forgiven for writing a query (using the
`client.rs` example):
```sh
$ cargo run --example client -- bevy_pbr::mesh_material::MeshMaterial3d | jq
{
"error": {
"code": -23402,
"message": "Unknown component type: `bevy_pbr::mesh_material::MeshMaterial3d`"
},
"id": 1,
"jsonrpc": "2.0"
}
```
which is where
8d9a00f548/crates/bevy_pbr/src/mesh_material.rs (L41)
would lead you to believe it is...
I've worked with bevy a lot, so it's no issue for me, but for others...
?
## Solution
- Add some more docs, including a sample request (`json` and `rust`)
## Testing
N/A
---
## Showcase
N/A
---------
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
- Make working with immutable components more ergonomic
- Assist #16662
## Solution
Added `modify_component` to `World` and `EntityWorldMut`. This method
"removes" a component from an entity, gives a mutable reference to it to
a provided closure, and then "re-inserts" the component back onto the
entity. This replacement triggers the `OnReplace` and `OnInsert` hooks,
but does _not_ cause an archetype move, as the removal is purely
simulated.
## Testing
- Added doc-tests and a unit test.
---
## Showcase
```rust
use bevy_ecs::prelude::*;
/// An immutable component.
#[derive(Component, PartialEq, Eq, Debug)]
#[component(immutable)]
struct Foo(bool);
let mut world = World::default();
let mut entity = world.spawn(Foo(false));
assert_eq!(entity.get::<Foo>(), Some(&Foo(false)));
// Before the closure is executed, the `OnReplace` hooks/observers are triggered
entity.modify_component(|foo: &mut Foo| {
foo.0 = true;
});
// After the closure is executed, `OnInsert` hooks/observers are triggered
assert_eq!(entity.get::<Foo>(), Some(&Foo(true)));
```
## Notes
- If the component is not available on the entity, the closure and hooks
aren't executed, and `None` is returned. I chose this as an alternative
to returning an error or panicking, but I'm open to changing that based
on feedback.
- This relies on `unsafe`, in particular for accessing the `Archetype`
to trigger hooks. All the unsafe operations are contained within
`DeferredWorld::modify_component`, and I would appreciate that this
function is given special attention to ensure soundness.
- The `OnAdd` hook can never be triggered by this method, since the
component must already be inserted. I have chosen to not trigger
`OnRemove`, as I believe it makes sense that this method is purely a
replacement operation, not an actual removal/insertion.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Malek <50841145+MalekiRe@users.noreply.github.com>
# Objective
- Made certain methods public for advanced use cases. Methods that
returns mutable references are marked as unsafe due to the possibility
of violating internal lifetime constraint assumptions.
- Fixes an issue introduced by #15184
# Objective
- Resolve several warnings encountered when compiling for `no_std`
around `dead_code`
- Fix compatibility with `wasm32-unknown-unknown` when using `no_std`
(identified by Sachymetsu on
[Discord](https://discord.com/channels/691052431525675048/692572690833473578/1323365426901549097))
## Solution
- Removed some unused imports
- Added `allow(dead_code)` for certain private items when compiling on
`no_std`
- Fixed `bevy_app` and `bevy_tasks` compatibility with WASM when
compiling without `std` by appropriately importing `Box` and feature
gating panic unwinding
## Testing
- CI
# Objective
Some sort calls and `Ord` impls are unnecessarily complex.
## Solution
Rewrite the "match on cmp, if equal do another cmp" as either a
comparison on tuples, or `Ordering::then_with`, depending on whether the
compare keys need construction.
`sort_by` -> `sort_by_key` when symmetrical. Do the same for
`min_by`/`max_by`.
Note that `total_cmp` can only work with `sort_by`, and not on tuples.
When sorting collected query results that contain
`Entity`/`MainEntity`/`RenderEntity` in their `QueryData`, with that
`Entity` in the sort key:
stable -> unstable sort (all queried entities are unique)
If key construction is not simple, switch to `sort_by_cached_key` when
possible.
Sorts that are only performed to discover the maximal element are
replaced by `max_by_key`.
Dedicated comparison functions and structs are removed where simple.
Derive `PartialOrd`/`Ord` when useful.
Misc. closure style inconsistencies.
## Testing
- Existing tests.
# Objective
In `prepare_sprite_image_bind_groups` the `batch_image_changed`
condition is checked twice but the second if-block seems unnecessary.
# Solution
Queue new `SpriteBatch`es inside the first if-block and remove the
second if-block.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `alloc` (default)
- `bevy_reflect` (default)
- `libm`
## Testing
- CI
## Notes
- `alloc` feature added to allow using this crate in `no_alloc`
environments.
- `bevy_reflect` was previously always enabled when `bevy-support` was
enabled, which isn't how most other crates handle reflection. I've
brought this in line with how most crates gate `bevy_reflect`.
# Objective
Fixes#17024
## Solution
## Testing
By adding
```
if let Some(mut cmd) = commands.get_entity( *equipment_link_node ){
cmd.insert(Visibility::Inherited); // a hack for now
}
```
in my build after .set_parent() , this fixes the issue. This is why i
think that this change will fix the issue. Unfortunately i was not able
to test the Changed (parent ) , this actual code change, because no
matter how i 'patch', it breaks my project. I got super close but still
had 23 errors due to Reflect being angry.
---
# Objective
Make working with `PluginGroupBuilder` less panicky.
Fixes#17001
## Solution
Expand the `PluginGroupBuilder` api with fallible add methods + a
contains method.
Also reorder the `PluginGroupBuilder` tests because before should come
before after.
## Testing
Ran the `PluginGroupBuilder` tests which call into all the newly added
methods.
This commit makes the following changes:
* `IndirectParametersBuffer` has been changed from a `BufferVec` to a
`RawBufferVec`. This won about 20us or so on Bistro by avoiding `encase`
overhead.
* The methods on the `GetFullBatchData` trait no longer have the
`entity` parameter, as it was unused.
* `PreprocessWorkItem`, which specifies a transform-and-cull operation,
now supplies the mesh instance uniform output index directly instead of
having the shader look it up from the indirect draw parameters.
Accordingly, the responsibility of writing the output index to the
indirect draw parameters has been moved from the CPU to the GPU. This is
in preparation for retained indirect instance draw commands, where the
mesh instance uniform output index may change from frame to frame, while
the indirect instance draw commands will be cached. We won't want the
CPU to have to upload the same indirect draw parameters again and again
if a batch didn't change from frame to frame.
* `batch_and_prepare_binned_render_phase` and
`batch_and_prepare_sorted_render_phase` now allocate indirect draw
commands for an entire batch set at a time when possible, instead of one
batch at a time. This change will allow us to retain the indirect draw
commands for whole batch sets.
* `GetFullBatchData::get_batch_indirect_parameters_index` has been
replaced with `GetFullBatchData::write_batch_indirect_parameters`, which
takes an offset and writes into it instead of allocating. This is
necessary in order to use the optimization mentioned in the previous
point.
* At the WGSL level, `IndirectParameters` has been factored out into
`mesh_preprocess_types.wgsl`. This is because we'll need a new compute
shader that zeroes out the instance counts in preparation for a new
frame. That shader will need to access `IndirectParameters`, so it was
moved to a separate file.
* Bins are no longer raw vectors but are instances of a separate type,
`RenderBin`. This is so that the bin can eventually contain its retained
batches.
OK, so this is tricky. Every frame, `delete_old_work_item_buffers`
deletes the mesh preprocessing index buffers (a.k.a. work item buffers)
for views that don't have `ViewTarget`s. This was always wrong for
shadow map views, as shadow maps only have `ExtractedView` components,
not `ViewTarget`s. However, before #16836, the problem was masked,
because uploading the mesh preprocessing index buffers for shadow views
had already completed by the time `delete_old_work_item_buffers` ran.
But PR #16836 moved `delete_old_work_item_buffers` from the
`ManageViews` phase to `PrepareResources`, which runs before
`write_batched_instance_buffers` uploads the work item buffers to the
GPU.
This itself isn't wrong, but it exposed the bug, because now it's
possible for work item buffers to get deleted before they're uploaded in
`write_batched_instance_buffers`. This is actually intermittent! It's
possible for the old work item buffers to get deleted, and then
*recreated* in `batch_and_prepare_binned_render_phase`, which runs
during `PrepareResources` as well, and under that system ordering, there
will be no problem other than a little inefficiency arising from
recreating the buffers every frame. But, if
`delete_old_work_item_buffers` runs *after*
`batch_and_prepare_render_phase`, then the work item buffers
corresponding to shadow views will get deleted, and then the shadows
will disappear.
The fact that this is racy is what made it look like #16922 solved the
issue. In fact, it didn't: it just perturbed the ordering on the build
bots enough that the issue stopped appearing. However, on my system, the
shadows still don't appear with #16922.
This commit solves the problem by making `delete_old_work_item_buffers`
look at `ExtractedView`s, not `ViewTarget`s, preventing work item
buffers corresponding to live shadow map views from being deleted.
# Objective
Fix alignment calculations in our rendering code.
Fixes#16992
The `gpu_readback::align_byte_size` function incorrectly rounds aligned
values to the next alignment.
If we assume the alignment to be 256 (because that's what wgpu says it
its) the function would align 0 to 256, 256 to 512, etc...
## Solution
Forward the `gpu_readback::align_byte_size` to
`RenderDevice::align_copy_bytes_per_row` so we don't implement the same
method twice.
Simplify `RenderDevice::align_copy_bytes_per_row`.
## Testing
Ran the code provided in #16992 to see if the issue has been solved +
added a test to check if `align_copy_bytes_per_row` returns the correct
values.
# Objective
`EntityMutExcept` can currently be cloned, which can easily violate
aliasing rules.
## Solution
- Remove the `Clone` impl for `EntityMutExcept`
- Also manually derived `Clone` impl for `EntityRefExcept` so that `B:
Clone` isn't required, and also impl'd `Copy`
## Testing
Compile failure tests would be good for this, but I'm not exactly sure
how to set that up.
## Migration Guide
- `EntityMutExcept` can no-longer be cloned, as this violates Rust's
memory safety rules.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `portable-atomic`
- `critical-section`
## Testing
- CI
## Notes
- `portable-atomic`, and `critical-section` are shortcuts to enable the
relevant features in dependencies, making the usage of this crate on
atomically challenged platforms possible and simpler.
- This PR is blocked until #17027 is merged (as it depends on fixes for
the `once!` macro). Once merged, the change-count for this PR should
reduce.
# Objective
Give users a quick example on how to control logging so they can filter
out library logs while reading their own
This is intended to fix issue #15957.
## Solution
Added some examples
## Testing
I created project and tested the examples work
###
This is purely a documentation change.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Andres O. Vela <andresovela@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
# Objective
- Improves platform compatibility for `bevy_utils`
## Solution
- Added `portable-atomic` to allow using the `once!` macro on more
platforms (e.g., Raspberry Pi Pico)
## Testing
- CI
## Notes
- This change should be entirely hidden thanks to the use of
`doc(hidden)`. Enabling the new `portable-atomic` feature just allows
using the `once!` macro on platforms which previously could not.
- I took the liberty of updating the feature documentation to be more in
line with how I've documented features in `bevy_ecs`/`bevy_app`/etc. for
their `no_std` updates.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `smol_str` (default)
- `portable-atomic`
- `critical-section`
- `libm`
- Fixed an existing issue where `bevy_reflect` wasn't properly feature
gated.
## Testing
- CI
## Notes
- There were some minor issues with `bevy_math` and `bevy_ecs` noticed
in this PR which I have also resolved here. I can split these out if
desired, but I've left them here for now as they're very small changes
and I don't consider this PR itself to be very controversial.
- `libm`, `portable-atomic`, and `critical-section` are shortcuts to
enable the relevant features in dependencies, making the usage of this
crate on atomically challenged platforms possible and simpler.
- `smol_str` is gated as it doesn't support atomically challenged
platforms (e.g., Raspberry Pi Pico). I have an issue and a
[PR](https://github.com/rust-analyzer/smol_str/pull/91) to discuss this
upstream.
## Objective
Commands were previously limited to structs that implemented `Command`.
Now there are blanket implementations for closures, which (in my
opinion) are generally preferable.
Internal commands within `commands/mod.rs` have been switched from
structs to closures, but there are a number of internal commands in
other areas of the engine that still use structs. I'd like to tidy these
up by moving their implementations to methods on
`World`/`EntityWorldMut` and changing `Commands` to use those methods
through closures.
This PR handles the following:
- `TriggerEvent` and `EmitDynamicTrigger` double as commands and helper
structs, and can just be moved to `World` methods.
- Four structs that enabled insertion/removal of components via
reflection. This functionality shouldn't be exclusive to commands, and
can be added to `EntityWorldMut`.
- Five structs that mostly just wrapped `World` methods, and can be
replaced with closures that do the same thing.
## Solution
- __Observer Triggers__ (`observer/trigger_event.rs` and
`observer/mod.rs`)
- Moved the internals of `TriggerEvent` to the `World` methods that used
it.
- Replaced `EmitDynamicTrigger` with two `World` methods:
- `trigger_targets_dynamic`
- `trigger_targets_dynamic_ref`
- `TriggerTargets` was now the only thing in
`observer/trigger_event.rs`, so it's been moved to `observer/mod.rs` and
`trigger_event.rs` was deleted.
- __Reflection Insert/Remove__ (`reflect/entity_commands.rs`)
- Replaced the following `Command` impls with equivalent methods on
`EntityWorldMut`:
- `InsertReflect` -> `insert_reflect`
- `InsertReflectWithRegistry` -> `insert_reflect_with_registry`
- `RemoveReflect` -> `remove_reflect`
- `RemoveReflectWithRegistry` -> `remove_reflect_with_registry`
- __System Registration__ (`system/system_registry.rs`)
- The following `Command` impls just wrapped a `World` method and have
been replaced with closures:
- `RunSystemWith`
- `UnregisterSystem`
- `RunSystemCachedWith`
- `UnregisterSystemCached`
- `RegisterSystem` called a helper function that basically worked as a
constructor for `RegisteredSystem` and made sure it came with a marker
component. That helper function has been replaced with
`RegisteredSystem::new` and a `#[require]`.
## Possible Addition
The extension trait that adds the reflection commands,
`ReflectCommandExt`, isn't strictly necessary; we could just `impl
EntityCommands`. We could even move them to the same files as the main
impls and put it behind a `#[cfg]`.
The PR that added it [had a similar
conversation](https://github.com/bevyengine/bevy/pull/8895#discussion_r1234713671)
and decided to stick with the trait, but we could revisit it here if so
desired.
# Objective
The rust-versions are out of date.
Fixes#17008
## Solution
Update the values
Cherry-picked from #17006 in case it is controversial
## Testing
Validated locally and in #17006
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#16683
## Solution
Make all fields ine `RawHandleWrapper` private.
## Testing
- CI
- `cargo clippy`
- The lightmaps example
---
## Migration Guide
The `window_handle` and `dispay_handle` fields on `RawHandleWrapper` are
no longer public. Use the newly added getters and setters to manipulate
them instead.
# Objective
Fixes#16879
## Solution
Moved the construction of the root path of the assets folder out of
`FileWatcher::new()` and into `source.rs`, as the path is checked there
with `path.exists()` and fails in certain configurations eg., virtual
workspaces.
## Testing
Applied fix to a private fork and tested against both standard project
setups and virtual workspaces. Works without issue on both. Have tested
under macOS and Arch Linux.
---------
Co-authored-by: JP Stringham <jp@bloomdigital.to>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Related to https://github.com/bevyengine/bevy/issues/11478
## Solution
- Moved `futures.rs`, `ConditionalSend` `ConditionalSendFuture` and
`BoxedFuture` from `bevy_utils` to `bevy_tasks`.
## Testing
- CI checks
## Migration Guide
- Several modules were moved from `bevy_utils` into `bevy_tasks`:
- Replace `bevy_utils::futures` imports with `bevy_tasks::futures`.
- Replace `bevy_utils::ConditionalSend` with
`bevy_tasks::ConditionalSend`.
- Replace `bevy_utils::ConditionalSendFuture` with
`bevy_tasks::ConditionalSendFuture`.
- Replace `bevy_utils::BoxedFuture` with `bevy_tasks::BoxedFuture`.
# Objective
The way `Curve` presently achieves dyn-compatibility involves shoving
`Self: Sized` bounds on a bunch of methods to forbid them from appearing
in vtables. (This is called *explicit non-dispatchability*.) The `Curve`
trait probably also just has way too many methods on its own.
In the past, using extension traits instead to achieve similar
functionality has been discussed. The upshot is that this would allow
the "core" of the curve trait, on which all the automatic methods rely,
to live in a very simple dyn-compatible trait, while other functionality
is implemented by extensions. For instance, `dyn Curve<T>` cannot use
the `Sized` methods, but `Box<dyn Curve<T>>` is `Sized`, hence would
automatically implement the extension trait, containing the methods
which are currently non-dispatchable.
Other motivations for this include modularity and code organization: the
`Curve` trait itself has grown quite large with the addition of numerous
adaptors, and refactoring it to demonstrate the separation of
functionality that is already present makes a lot of sense. Furthermore,
resampling behavior in particular is dependent on special traits that
may be mimicked or analogized in user-space, and creating extension
traits to achieve similar behavior in user-space is something we ought
to encourage by example.
## Solution
`Curve` now contains only `domain` and the `sample` methods.
`CurveExt` has been created, and it contains all adaptors, along with
the other sampling convenience methods (`samples`, `sample_iter`, etc.).
It is implemented for all `C` where `C: Curve<T> + Sized`.
`CurveResampleExt` has been created, and it contains all resampling
methods. It is implemented for all `C` where `C: Curve<T> + ?Sized`.
## Testing
It compiles and `cargo doc` succeeds.
---
## Future work
- Consider writing extension traits for resampling curves in related
domains (e.g. resampling for `Curve<T>` where `T: Animatable` into an
`AnimatableKeyframeCurve`).
- `CurveExt` might be further broken down to separate the adaptor and
sampling methods.
---
## Migration Guide
`Curve` has been refactored so that much of its functionality is now in
extension traits. Adaptors such as `map`, `reparametrize`, `reverse`,
and so on now require importing `CurveExt`, while the resampling methods
`resample_*` require importing `CurveResampleExt`. Both of these new
traits are exported through `bevy::math::curve` and through
`bevy::math::prelude`.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
## Testing
- CI
## Notes
- There was a minor issue with `bevy_reflect`'s `smallvec` feature
noticed in this PR which I have also resolved here. I can split this out
if desired, but I've left it here for now as it's a very small change
and I don't consider this PR itself to be very controversial.
# 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
- First step for #16718
- #16589 introduced an api that can only ignore errors, which is risky
## Solution
- Panic instead of just ignoring the errors
## Testing
- Changed the `fallible_systems` example to return an error
```
Encountered an error in system `fallible_systems::setup`: TooManyVertices { subdivisions: 300, number_of_resulting_points: 906012 }
Encountered a panic in system `fallible_systems::setup`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```
# Objective
ensure that `animate_targets` runs **before**
`bevy_render::mesh::inherit_weights` to address the one-frame delay
Fixes#16554
## Solution
switch ordering constraints from `after` to `before`
## Testing
ran bevy_animation tests and the animated_fox example on MacOS
# Objective
Resolve#16745
## Solution
Provide a way to map `AppTypeRegistry` types into a JSON Schema that can
be used in other applications. I took code from
https://github.com/kaosat-dev/Blenvy as a starting point, cleaned up and
adapter more for `bevy_remote` needs. Based on feedback and needs it
could be improved, I could add some filtering options, etc.
## Testing
- I was comparing results with the ones from code in `blenvy`
- There is added unit test, could be added more
- I was testing it in my game with this code:
```rust
fn types_to_file(world: &mut World) {
use bevy_remote::builtin_methods::export_registry_types;
let Ok(Ok(types_schema)) = world.run_system_cached_with(export_registry_types, None) else {
return;
};
let registry_save_path = std::path::Path::new("assets").join("registry.json");
let writer =
std::fs::File::create(registry_save_path).expect("should have created schema file");
serde_json::to_writer_pretty(writer, &types_schema).expect("Failed to save types to file");
}
```
It can be run by adding it at startup
```rust
app.add_systems(Startup, types_to_file);
```
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
A previous PR, #14599, attempted to enable lightmaps in deferred mode,
but it still used the `OpaqueNoLightmap3dBinKey`, which meant that it
would be broken if multiple lightmaps were used. This commit fixes that
issue, and allows bindless lightmaps to work with deferred rendering as
well.
# Objective
- Running example `load_gltf` when not using bindless gives this error
```
ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: no definition in scope for identifier: 'slot'
┌─ crates/bevy_pbr/src/render/pbr_fragment.wgsl:153:13
│
153 │ slot,
│ ^^^^ unknown identifier
│
= no definition in scope for identifier: 'slot'
```
- since https://github.com/bevyengine/bevy/pull/16825
## Solution
- Set `slot` to the expected value when not mindless
- Also use it for `uv_b`
## Testing
- Run example `load_gltf` on a Mac or in wasm
# Objective
Fixes#16850
## Solution
Add a new function `SubApp::take_extract()`, similar to
`Option::take()`, which allows stealing the currently installed extract
function of a sub-app, with the intent to replace it with a custom one
calling the original one via `set_extract()`.
This pattern enables registering a custom "world sync" function similar
to the existing one `entity_sync_system()`, to run custom world sync
logic with mutable access to both the main and render worlds.
## Testing
`cargo r -p ci` currently doesn't build locally, event after upgrading
rustc to latest and doing a `cargo update`.
# Objective
Make it so that users can ease between tuples of easeable values.
## Solution
Use `variadics_please`'s `all_tuples_enumerated` macro to generate code
that creates these trait implementations. For two elements, the result
looks like this:
```rust
impl<T0: Ease, T1: Ease> Ease for (T0, T1) {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
let curve_tuple = (
<T0 as Ease>::interpolating_curve_unbounded(start.0, end.0),
<T1 as Ease>::interpolating_curve_unbounded(start.1, end.1),
);
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
(
curve_tuple.0.sample_unchecked(t),
curve_tuple.1.sample_unchecked(t),
)
})
}
}
```
## Testing
It compiles, and I futzed about with some manual examples, which seem to
work as expected.
---
## Showcase
Easing curves now support easing tuples of values that can themselves be
eased. For example:
```rust
// Easing between two `(Vec3, Quat)` values:
let easing_curve = EasingCurve::new(
(vec3(0.0, 0.0, 0.0), Quat::from_rotation_z(-FRAC_PI_2)),
(vec3(1.0, 1.0, 1.0), Quat::from_rotation_z(FRAC_PI_2)),
EaseFunction::ExponentialInOut
);
```
# Objective
Almost all of the `*InOut` easing functions are not actually smooth
(`SineInOut` is the one exception).
Because they're defined piecewise, they jump from accelerating upwards
to accelerating downwards, causing infinite jerk at t=½.
## Solution
This PR adds the well-known
[smoothstep](https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml),
as well as its higher-degree version
[smootherstep](https://en.wikipedia.org/wiki/Smoothstep#Variations), as
easing functions.
Mathematically, these are the classic [Hermite
interpolation](https://en.wikipedia.org/wiki/Hermite_interpolation)
results:
- for smoothstep, the cubic with velocity zero at both ends
- for smootherstep, the quintic with velocity zero *and acceleration
zero* at both ends
And because they're simple polynomials, there's no branching and thus
they don't have the acceleration jump in the middle.
I also added some more information and cross-linking to the
documentation for these and some of the other easing functions, to help
clarify why one might want to use these over other existing ones. In
particular, I suspect that if people are willing to pay for a quintic
they might prefer `SmootherStep` to `QuinticInOut`.
For consistency with how everything else has triples, I added
`Smooth(er)Step{In,Out}` as well, in case people want to run the `In`
and `Out` versions separately for some reason. Qualitatively they're not
hugely different from `Quadratic{In,Out}` or `Cubic{In,Out}`, though, so
could be removed if you'd rather. They're low cost to keep, though, and
convenient for testing.
## Testing
These are simple polynomials, so their coefficients can be read directly
from the Horner's method implementation and compared to the reference
materials. The tests from #16910 were updated to also test these 6 new
easing functions, ensuring basic behaviour, plus one was updated to
better check that the InOut versions of things match their rescaled In
and Out versions.
Even small changes like
```diff
- (((2.5 + (-1.875 + 0.375*t) * t) * t) * t) * t
+ (((2.5 + (-1.85 + 0.375*t) * t) * t) * t) * t
```
are caught by multiple tests this way.
If you want to confirm them visually, here are the 6 new ones graphed:
<https://www.desmos.com/calculator/2d3ofujhry>

---
## Migration Guide
This version of bevy marks `EaseFunction` as `#[non_exhaustive]` to that
future changes to add more easing functions will be non-breaking. If you
were exhaustively matching that enum -- which you probably weren't --
you'll need to add a catch-all (`_ =>`) arm to cover unknown easing
functions.
# Objective
With the introduction of bevy_input_focus, the uses of "focus" in
bevy_picking are quite confusing and make searching hard.
Users will intuitively think these concepts are related, but they
actually aren't.
## Solution
Rename / rephrase all uses of "focus" in bevy_picking to refer to
"hover", since this is ultimately related to creating the `HoverMap`.
## Migration Guide
Various terms related to "focus" in `bevy_picking` have been renamed to
refer to "hover" to avoid confusion with `bevy_input_focus`. In
particular:
- The `update_focus` system has been renamed to `generate_hovermap`
- `PickSet::Focus` and `PostFocus` have been renamed to `Hover` and
`PostHover`
- The `bevy_picking::focus` module has been renamed to
`bevy_picking::hover`
- The `is_focus_enabled` field on `PickingPlugin` has been renamed to
`is_hover_enabled`
- The `focus_should_run` run condition has been renamed to
`hover_should_run`
# Objective
`SubApps` is visible within the documentation for `bevy_app`. However,
no way of accessing the `SubApps` field in `App` is currently available.
## Solution
Expose two new functions, `App::sub_apps()` and `App::sub_apps_mut()`,
which give immutable and mutable access to `SubApps` respectively.
The other solution is to hide `SubApps`, which I submitted as a PR at
<https://github.com/bevyengine/bevy/pull/16953>.
## Testing
Because of the simplicity of the changes, I only tested by compiling
`bevy_app` - which compiled successfully.
Note: `SubApps`, and its corresponding field on `App`, are not used
outside of `bevy_app` - which means that compiling the other crates is
not necessary.
# Objective
- Fixes#16571
## Solution
- When position delta is zero, don't trigger `Drag` or `DragOver` events
## Testing
- tested with the code from the issue
# Objective
- Fixes#16563
- Make sure bevy_image is available when needed
## Solution
- Add a new feature for `bevy_image`
- Also enable the `bevy_image` feature in `bevy_internal` for all
features that use `bevy_image` themselves
# Objective
bevy_reflect is a big part of bevy_math's dependency footprint, and is
often not useful when using bevy_math standalone (as I often do). The
goal with this PR is to avoid pulling in those dependencies by default
without compromising the usability of bevy_math types within Bevy
proper.
## Solution
`bevy_reflect` has been removed from default features of `bevy_math`.
However, the feature is enabled by `bevy_internal`, so that
`bevy_reflect` is enabled when `bevy_math` is used through `bevy`.
Philosophically, if there were a feature flag toggling reflection on
`bevy` globally, then whether `bevy_math` enabled `bevy_reflect` itself
would depend on that, but that doesn't exist for the time being.
## Testing
It compiles :)
## Migration Guide
`bevy_reflect` has been made a non-default feature of `bevy_math`. (It
is still enabled when `bevy_math` is used through `bevy`.) You may need
to enable this feature if you are using `bevy_math` on its own and
desire for the types it exports to implement `Reflect` and other
reflection traits.
## Objective
I believe these started as structs, back when that was how commands had
to be implemented. Now they just hide implementation details.
## Solution
Remove the helper functions and move each implementation into its
respective method, except for the ones that actually reduce code
duplication.
This PR simply exposes Bevy PBR's
`TONEMAPPING_LUT_TEXTURE_BINDING_INDEX` and
`TONEMAPPING_LUT_SAMPLER_BINDING_INDEX`.
# Objective
Alongside #16932, this is the last required change to be able to replace
Bevy's built-in deferred lighting pass with a custom one based on the
original logic.
Fixes a crash when using deferred rendering but disabling the default
deferred lighting plugin.
# The Issue
The `ScreenSpaceReflectionsPlugin` references
`NodePbr::DeferredLightingPass`, which hasn't been added when
`PbrPlugin::add_default_deferred_lighting_plugin` is `false`.
This yields the following crash:
```
thread 'main' panicked at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/graph.rs:155:26:
InvalidNode(DeferredLightingPass)
stack backtrace:
0: rust_begin_unwind
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
2: bevy_render::render_graph::graph::RenderGraph::add_node_edges
at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/graph.rs:155:26
3: <bevy_app::sub_app::SubApp as bevy_render::render_graph::app::RenderGraphApp>::add_render_graph_edges
at /Users/marius/Documents/dev/bevy/crates/bevy_render/src/render_graph/app.rs:66:13
4: <bevy_pbr::ssr::ScreenSpaceReflectionsPlugin as bevy_app::plugin::Plugin>::finish
at /Users/marius/Documents/dev/bevy/crates/bevy_pbr/src/ssr/mod.rs:234:9
5: bevy_app::app::App::finish
at /Users/marius/Documents/dev/bevy/crates/bevy_app/src/app.rs:255:13
6: bevy_winit::state::winit_runner
at /Users/marius/Documents/dev/bevy/crates/bevy_winit/src/state.rs:859:9
7: core::ops::function::FnOnce::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
8: core::ops::function::FnOnce::call_once{{vtable.shim}}
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
9: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2454:9
10: bevy_app::app::App::run
at /Users/marius/Documents/dev/bevy/crates/bevy_app/src/app.rs:184:9
11: bevy_deferred_test::main
at ./src/main.rs:9:5
12: core::ops::function::FnOnce::call_once
at /Users/marius/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
```
### Minimal reproduction example:
```rust
use bevy::core_pipeline::prepass::{DeferredPrepass, DepthPrepass};
use bevy::pbr::{DefaultOpaqueRendererMethod, PbrPlugin, ScreenSpaceReflections};
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(PbrPlugin {
add_default_deferred_lighting_plugin: false,
..default()
}))
.add_systems(Startup, setup)
.insert_resource(DefaultOpaqueRendererMethod::deferred())
.run();
}
/// set up a camera
fn setup(
mut commands: Commands
) {
// camera
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
DepthPrepass,
DeferredPrepass,
ScreenSpaceReflections::default(),
));
}
```
# The Fix
When no node under the default lighting node's label exists, this label
isn't added to the SSR's graph node edges. It's good to keep the
SSRPlugin enabled, this way, users can plug in their own lighting
system, which I have successfully done on top of this PR.
# Workarounds
A current workaround for this issue is to re-use Bevy's
`NodePbr::DeferredLightingPass` as the label for your own custom
lighting pass node.
# Objective
Now that `variadics_please` has a 1.1 release, we can re-implement the
original solution.
## Solution
Copy-paste the code from the [original
PR](https://github.com/bevyengine/bevy/pull/15931) branch :)
# 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.
And add a bunch of tests to show that all the monotonic easing functions
have roughly the expected shape.
# Objective
The `EaseFunction::Exponential*` variants aren't actually smooth as
currently implemented, because they jump by about 1‰ at the
start/end/both.
- Fixes#16676
- Subsumes #16675
## Solution
This PR slightly tweaks the shifting and scaling of all three variants
to ensure they hit (0, 0) and (1, 1) exactly while gradually
transitioning between them.
Graph demonstration of the new easing function definitions:
<https://www.desmos.com/calculator/qoc5raus2z>

(Yes, they look completely identical to the previous ones at that scale.
[Here's a zoomed-in
comparison](https://www.desmos.com/calculator/ken6nk89of) between the
old and the new if you prefer.)
The approach taken was to keep the core 2¹⁰ᵗ shape, but to [ask
WolframAlpha](https://www.wolframalpha.com/input?i=solve+over+the+reals%3A+pow%282%2C+10-A%29+-+pow%282%2C+-A%29%3D+1)
what scaling factor to use such that f(1)-f(0)=1, then shift the curve
down so that goes from zero to one instead of ¹/₁₀₂₃ to ¹⁰²⁴/₁₀₂₃.
## Testing
I've included in this PR a bunch of general tests for all monotonic
easing functions to ensure they hit (0, 0) to (1, 1), that the InOut
functions hit (½, ½), and that they have the expected convexity.
You can also see by inspection that the difference is small. The change
for `exponential_in` is from `exp2(10 * t - 10)` to `exp2(10 * t -
9.99859…) - 0.0009775171…`.
The problem for `exponential_in(0)` is also simple to see without a
calculator: 2⁻¹⁰ is obviously not zero, but with the new definition
`exp2(-LOG2_1023) - FRAC_1_1023` => `1/(exp2(LOG2_1023)) - FRAC_1_1023`
=> `FRAC_1_1023 - FRAC_1_1023` => `0`.
---
## Migration Guide
This release of bevy slightly tweaked the definitions of
`EaseFunction::ExponentialIn`, `EaseFunction::ExponentialOut`, and
`EaseFunction::ExponentialInOut`. The previous definitions had small
discontinuities, while the new ones are slightly rescaled to be
continuous. For the output values that changed, that change was less
than 0.001, so visually you might not even notice the difference.
However, if you depended on them for determinism, you'll need to define
your own curves with the previous definitions.
---------
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
# 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
Fixes: #16578
## Solution
This is a patch fix, proper fix requires a breaking change.
Added `Panic` enum variant and using is as the system meta default.
Warn once behavior can be enabled same way disabling panic (originally
disabling wans) is.
To fix an issue with the current architecture, where **all** combinator
system params get checked together,
combinator systems only check params of the first system.
This will result in old, panicking behavior on subsequent systems and
will be fixed in 0.16.
## Testing
Ran unit tests and `fallible_params` example.
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Revert the retry queue for stuck meshlet groups that couldn't simplify
added in https://github.com/bevyengine/bevy/pull/15886.
It was a hack that didn't really work, that was intended to help solve
meshlets getting stuck and never getting simplified further. The actual
solution is a new DAG building algorithm that I have coming in a
followup PR. With that PR, there will be no need for the retry queue, as
meshlets will rarely ever get stuck (I checked, the code never gets
called). I split this off into it's own PR for easier reviewing.
Meshlet IDs during building are back to being relative to the overall
list of meshlets across all LODs, instead of starting at 0 for the first
meshlet in the simplification queue for the current LOD, regardless of
how many meshlets there are in the asset total.
Not going to bother to regenerate the bunny asset for this PR.
# Objective
- To fix a tiny bug in `bevy_ecs::storage::Tables` that, in one case,
means it accidentally allocates an additional "empty" `Table`, resulting
in two "empty" `Table`s:
- The one pre-allocated empty table at index 0 whose index is designed
to match up with `TableId::empty()`
- One extra empty table, at some non-0 index, that does not match up
with `TableId::empty()`.
- This PR aims to prevent this extraneous `Table`, ensuring that
entities with no components in table-storage reliably have their
archetype's table ID be equal to `TableId::empty()`.
## Solution
### Background
The issue occurs because:
- `Tables` contains:
- `tables: Vec<Table>` - The set of all `Table`s allocated in the world.
- `table_ids: HashMap<Box<[ComponentId]>, TableId>` - An index to
rapidly lookup the `Table` in `tables` by a set of `ComponentId`s.
- When `Tables` is constructed it pre-populates the `tables` `Vec` with
an empty `Table`.
- This ensures that the first entry (index 0) is always the `Table` for
entities with no components in table storage.
- In particular, `TableId::empty()` is a utility that returns a
`TableId` of `0`.
- However, the `table_ids` map is not initialised to associate an empty
`[ComponentId]` with `TableId` `0`.
- This means, the first time a structural change tries to access a
`Table` for an archetype with 0 table components:
- `Tables::get_id_or_insert` is used to retrieve the target `Table`
- The function attempts to lookup the entry in the `table_ids` `HashMap`
whose key is the empty `ComponentId` set
- The empty `Table` created at startup won't be found, because it was
never inserted into `table_ids`
- It will instead create a new table, insert it into the `HashMap`
(preventing further instances of this issue), and return it.
### Changes
- I considered simply initialising the `table_ids` `HashMap` to know
about the pre-allocated `Table`
- However, I ended up using the proposed solution discussed on Discord
[#ecs-dev](https://discord.com/channels/691052431525675048/749335865876021248/1320430933152759958):
- Make `Tables::get_id_or_insert` simply early-exit if the requested
`component_ids` was empty.
- This avoids unnecessarily hashing the empty slice and looking it up in
the `HashMap`.
- The `table_ids` `HashMap` is not exposed outside this struct, and is
only used within `get_id_or_insert`, so it seems wasteful to defensively
populate it with the empty `Table`.
## Testing
This is my first Bevy contribution, so I don't really know the processes
that well. That said:
- I have introduced a little test that exercises the original issue and
shows that it is now resolved.
- I have run the `bevy_ecs` tests locally, so I have reasonable
confidence I haven't broken that.
- I haven't run any further test suites, mostly as when I tried to run
test suites for the whole project it filled my entire SSD with >600GB of
target directory output 😱😱😱
This commit fixes the following regressions:
1. Transmission-specific calls to shader lighting functions didn't pass
the `enable_diffuse` parameter, breaking the `transmission` example.
2. The combination of bindless `StandardMaterial` and bindless lightmaps
caused us to blow past the 128 texture limit on M1/M2 chips in some
cases, in particular the `depth_of_field` example.
https://github.com/gfx-rs/wgpu/issues/3334 should fix this, but in the
meantime this patch reduces the number of bindless lightmaps from 16 to
4 in order to stay under the limit.
3. The renderer was crashing on startup on Adreno 610 chips. This PR
simply disables bindless on Adreno 610 and lower.
# Objective
- Our benchmarks and `compile_fail` tests lag behind the rest of the
engine because they are not in the Cargo workspace, so not checked by
CI.
- Fixes#16801, please see it for further context!
## Solution
- Add benchmarks and `compile_fail` tests to the Cargo workspace.
- Fix any leftover formatting issues and documentation.
## Testing
- I think CI should catch most things!
## Questions
<details>
<summary>Outdated issue I was having with function reflection being
optional</summary>
The `reflection_types` example is failing in Rust-Analyzer for me, but
not a normal check.
```rust
error[E0004]: non-exhaustive patterns: `ReflectRef::Function(_)` not covered
--> examples/reflection/reflection_types.rs:81:11
|
81 | match value.reflect_ref() {
| ^^^^^^^^^^^^^^^^^^^ pattern `ReflectRef::Function(_)` not covered
|
note: `ReflectRef<'_>` defined here
--> /Users/bdeep/dev/bevy/bevy/crates/bevy_reflect/src/kind.rs:178:1
|
178 | pub enum ReflectRef<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^
...
188 | Function(&'a dyn Function),
| -------- not covered
= note: the matched value is of type `ReflectRef<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
126 ~ ReflectRef::Opaque(_) => {},
127 + ReflectRef::Function(_) => todo!()
|
```
I think it is because the following line is feature-gated:
cc0f6a8db4/examples/reflection/reflection_types.rs (L117-L122)
My theory for why this is happening is because the benchmarks enabled
`bevy_reflect`'s `function` feature, which gets merged with the rest of
the features when RA checks the workspace, but the `#[cfg(...)]` gate in
the example isn't detecting it:
cc0f6a8db4/benches/Cargo.toml (L19)
Any thoughts on how to fix this? It's not blocking, since the example
still compiles as normal, but it's just RA and the command `cargo check
--workspace --all-targets` appears to fail.
</summary>
# Objective
`EntityHashMap` and `EntityHashSet` iterators do not implement
`EntitySetIterator`.
## Solution
Make them newtypes instead of aliases. The methods that create the
iterators can then produce their own newtypes that carry the `Hasher`
generic and implement `EntitySetIterator`. Functionality remains the
same otherwise.
There are some other small benefits, f.e. the removal of `with_hasher`
associated functions, and the ability to implement more traits
ourselves.
`MainEntityHashMap` and `MainEntityHashSet` are currently left as the
previous type aliases, because supporting general `TrustedEntityBorrow`
hashing is more complex. However, it can also be done.
## Testing
Pre-existing `EntityHashMap` tests.
## Migration Guide
Users of `with_hasher` and `with_capacity_and_hasher` on
`EntityHashMap`/`Set` must now use `new` and `with_capacity`
respectively.
If the non-newtyped versions are required, they can be obtained via
`Deref`, `DerefMut` or `into_inner` calls.
# Objective
- Fixes#16892
## Solution
- Removed `TypeRegistryPlugin` (`Name` is now automatically registered
with a default `App`)
- Moved `TaskPoolPlugin` to `bevy_app`
- Moved `FrameCountPlugin` to `bevy_diagnostic`
- Deleted now-empty `bevy_core`
## Testing
- CI
## Migration Guide
- `TypeRegistryPlugin` no longer exists. If you can't use a default
`App` but still need `Name` registered, do so manually with
`app.register_type::<Name>()`.
- References to `TaskPoolPlugin` and associated types will need to
import it from `bevy_app` instead of `bevy_core`
- References to `FrameCountPlugin` and associated types will need to
import it from `bevy_diagnostic` instead of `bevy_core`
## Notes
This strategy was agreed upon by Cart and several other members in
[Discord](https://discord.com/channels/691052431525675048/692572690833473578/1319137218312278077).
# Objective
- Contributes to #16892
## Solution
- Moved `Name` and `NameOrEntity` into `bevy_ecs::name`, and added them
to the prelude.
## Testing
- CI
## Migration Guide
If you were importing `Name` or `NameOrEntity` from `bevy_core`, instead
import from `bevy_ecs::name`.
---------
Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
# Objective
The `SetInputFocus` trait is not very useful: we're just setting a
resource's value.
This is a very common and simple pattern, so we should expose it
directly to users rather than creating confusing indirection.
## Solution
Remove the `SetInputFocus` trait and migrate existing uses to just
modify the `InputFocus` resource. The helper methods on that type make
this nicer than before :)
P.S. This is non-breaking as bevy_input_focus has not yet shipped.
## Testing
Code compiles! CI will check the existing unit tests.
# Objective
The docs for InputFocusVisible could do a better job explaining how the
resource is intended to be used.
## Solution
Add more detail and do an editing pass. Link to the `IsFocused` trait
for breadcrumbs too.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `bevy_tasks` (default)
- `downcast ` (default)
- `portable-atomic`
- `critical-section`
- `downcast` and `bevy_tasks` are now optional dependencies for
`bevy_app`.
## Testing
- CI
- Personal UEFI and Raspberry Pi Pico demo applications compile and run
against this branch
## Draft Release Notes
Bevy's application framework now supports `no_std` platforms.
Following up on `bevy_ecs` gaining `no_std` support, `bevy_app` extends
the functionality available on these targets to include the powerful
`App` and `Plugin` abstractions. With this, library authors now have the
option of making their plugins `no_std` compatible, or even offering
plugins specifically to improve Bevy on certain embedded platforms!
To start making a `no_std` compatible plugin, simply disable default
features when including `bevy_app`:
```toml
[dependencies]
bevy_app = { version = "0.16", default-features = false }
```
We encourage library authors to do this anyway, as it can also help with
compile times and binary size on all platforms.
Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!
## Notes
- `downcast-rs` is optional as it isn't compatible with
`portable-atomic`. I will investigate making a PR upstream to add
support for this functionality, as it should be very straightforward.
- In line with the `bevy_ecs` no-std-ification, I've added documentation
to all features, and grouped them as well.
- ~~Creating this PR in draft while CI runs and so I can polish before
review.~~
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Fixes#16873
## Solution
- Added `GizmoLineStyle::Dashed {gap_scale, line_scale}`
- The `gap_scale` and `line_scale` describe the lengths of the gaps and
visible line-segments in terms of line-widths. For example, if
`gap_scale == 1.0` and `line_scale == 3.0` the gaps are square and the
the visible segments are three line-widths long.
- The new `GizmoLineStyle` can be used both in 3D and 2D and with both
perspective and orthographic cameras.
- Updated the `2d_gizmos` and `3d_gizmos` examples to include the new
line-style.
- Display a warning, when using negative `gap_scale` or `line_scale`.
- Notably, `Hash` and `Eq` are manually implemented for `GizmoLineStyle`
since both are not implemented for `f32` which prevents deriving these
traits for `GizmoLineStyle`.
## Testing
- The results can be verified visually
---
## Showcase
The following images depict dashed lines with `gap_scale == 3.0` and
`line_scale == 5.0` in perspective 3D and orthographic 2D.


---------
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
# Objective
`bevy_input_focus` needs some love before we ship it to users. There's a
few missing helper methods, the docs could be improved, and `AutoFocus`
should be more generally available.
## Solution
The changes here are broken down by commit, and should generally be
uncontroversial. The ones to focus on during review are:
- Make navigate take a & InputFocus argument: this makes the intended
pattern clearer to users
- Remove TabGroup requirement from `AutoFocus`: I want auto-focusing
even with gamepad-style focus navigation!
- Handle case where tab group is None more gracefully: I think we can
try harder to provide something usable, and shouldn't just fail to
navigate
## Testing
The `tab_navigation` example continues to work.
# Objective
#16132 introduced entity cloning functionality, and while it works and
is useful, it can be made faster. This is the promised follow-up to
improve performance.
## Solution
**PREFACE**: This is my first time writing `unsafe` in rust and I have
only vague idea about what I'm doing. I would encourage reviewers to
scrutinize `unsafe` parts in particular.
The solution is to clone component data to an intermediate buffer and
use `EntityWorldMut::insert_by_ids` to insert components without
additional archetype moves.
To facilitate this, `EntityCloner::clone_entity` now reads all
components of the source entity and provides clone handlers with the
ability to read component data straight from component storage using
`read_source_component` and write to an intermediate buffer using
`write_target_component`. `ComponentId` is used to check that requested
type corresponds to the type available on source entity.
Reflect-based handler is a little trickier to pull of: we only have
`&dyn Reflect` and no direct access to the underlying data.
`ReflectFromPtr` can be used to get `&dyn Reflect` from concrete
component data, but to write it we need to create a clone of the
underlying data using `Reflect`. For this reason only components that
have `ReflectDefault` or `ReflectFromReflect` or `ReflectFromWorld` can
be cloned, all other components will be skipped. The good news is that
this is actually only a temporary limitation: once #13432 lands we will
be able to clone component without requiring one of these `type data`s.
This PR also introduces `entity_cloning` benchmark to better compare
changes between the PR and main, you can see the results in the
**showcase** section.
## Testing
- All previous tests passing
- Added test for fast reflect clone path (temporary, will be removed
after reflection-based cloning lands)
- Ran miri
## Showcase
Here's a table demonstrating the improvement:
| **benchmark** | **main, avg** | **PR, avg** | **change, avg** |
| ----------------------- | ------------- | ----------- |
--------------- |
| many components reflect | 18.505 µs | 2.1351 µs | -89.095% |
| hierarchy wide reflect* | 22.778 ms | 4.1875 ms | -81.616% |
| hierarchy tall reflect* | 107.24 µs | 26.322 µs | -77.141% |
| hierarchy many reflect | 78.533 ms | 9.7415 ms | -87.596% |
| many components clone | 1.3633 µs | 758.17 ns | -45.937% |
| hierarchy wide clone* | 2.7716 ms | 3.3411 ms | +20.546% |
| hierarchy tall clone* | 17.646 µs | 20.190 µs | +17.379% |
| hierarchy many clone | 5.8779 ms | 4.2650 ms | -27.439% |
*: these benchmarks have entities with only 1 component
## Considerations
Once #10154 is resolved a large part of the functionality in this PR
will probably become obsolete. It might still be a little bit faster
than using command batching, but the complexity might not be worth it.
## Migration Guide
- `&EntityCloner` in component clone handlers is changed to `&mut
ComponentCloneCtx` to better separate data.
- Changed `EntityCloneHandler` from enum to struct and added convenience
functions to add default clone and reflect handler more easily.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
Simplify the code by using `macro_rules` instead of a proc macro where
possible.
## Solution
Replace `impl_param_set` proc macro with a `macro_rules` macro.
# Objective
The new `bevy_input_focus` crates has a tool to bubble input events up
the entity hierarchy, ending with the window, based on the currently
focused entity. Right now though, this only works for keyboard events!
Both `bevy_ui` buttons and `bevy_egui` should hook into this system
(primarily for contextual hotkeys), and we would like to drive
`leafwing_input_manager` via these events, to help resolve longstanding
pain around "absorbing" / "consuming" inputs based on focus. In order to
make that work properly though, we need gamepad support!
## Solution
The logic backing this has been changed to be generic for any cloneable
event types, and the machinery to make use of this externally has been
made `pub`.
Within the engine itself, I've added support for gamepad button and
scroll events, but nothing else. Mouse button / touch bubbling is
handled via bevy_picking, and mouse / gamepad motion doesn't really make
sense to bubble.
## Testing
The `tab_navigation` example continues to work, and CI is green.
## Future Work
I would like to add more complex UI examples to stress test this, but
not here please.
We should take advantage of the bubbled mouse scrolling when defining
scrolled widgets.
# Objective
In current Bevy, it is very inconvenient to mutably retrieve a
user-provided list of entities more than one element at a time.
If the list contains any duplicate entities, we risk mutable aliasing.
Users of `Query::iter_many_mut` do not have access to `Iterator` trait,
and thus miss out on common functionality, for instance collecting their
`QueryManyIter`.
We can circumvent this issue with validation, however that entails
checking every entity against all others for inequality, or utilizing an
`EntityHashSet`. Even if an entity list remains unchanged, this
validation is/would have to be redone every time we wish to fetch with
the list.
This presents a lot of wasted work, as we often trivially know an entity
list to be unique f.e.: `QueryIter` will fetch every `Entity` once and
only once.
As more things become entities – assets, components, queries – this
issue will become more pronounced.
`get_many`/`many`/`iter_many`/`par_iter_many`-like functionality is all
affected.
## Solution
The solution this PR proposes is to introduce functionality built around
a new trait: `EntitySet`.
The goal is to preserve the property of "uniqueness" in a list wherever
possible, and then rely on it as a bound within new `*_many_unique`
methods to avoid the need for validation.
This is achieved using `Iterator`:
`EntitySet` is blanket implemented for any `T` that implements
`IntoIterator<IntoIter: EntitySetIterator>`.
`EntitySetIterator` is the unsafe trait that actually guarantees an
iterator to be "unique" via its safety contract.
We define an "Iterator over unique entities" as: "No two entities
returned by the iterator may compare equal."
For iterators that cannot return more than 1 element, this is trivially
true.
Whether an iterator can satisfy this is up to the `EntitySetIterator`
implementor to ensure, hence the unsafe.
However, this is not yet a complete solution. Looking at the signature
of `iter_many`, we find that `IntoIterator::Item` is not `Entity`, but
is instead bounded by the `Borrow<Entity>` trait. That is because
iteration without consuming the collection will often yield us
references, not owned items.
`Borrow<Entity>` presents an issue: The `Borrow` docs state that `x = y`
should equal `x.borrow() = y.borrow()`, but unsafe cannot rely on this
for soundness. We run into similar problems with other trait
implementations of any `Borrow<Entity>` type: `PartialEq`, `Eq`,
`PartialOrd`, `Ord`, `Hash`, `Clone`, `Borrow`, and `BorrowMut`.
This PR solves this with the unsafe `TrustedEntityBorrow` trait:
Any implementor promises that the behavior of the aforementioned traits
matches that of the underlying entity.
While `Borrow<Entity>` was the inspiration, we use our own counterpart
trait `EntityBorrow` as the supertrait to `TrustedEntityBorrow`, so we
can circumvent the limitations of the existing `Borrow<T>` blanket
impls.
All together, these traits allow us to implement `*_many_unique`
functionality with a lone `EntitySet` bound.
`EntitySetIterator` is implemented for all the std iterators and
iterator adapters that guarantee or preserve uniqueness, so we can
filter, skip, take, step, reverse, ... our unique entity iterators
without worry!
Sadly, current `HashSet` iterators do not carry the necessary type
information with them to determine whether the source `HashSet` produces
logic errors; A malicious `Hasher` could compromise a `HashSet`.
`HashSet` iteration is generally discouraged in the first place, so we
also exclude the set operation iterators, even though they do carry the
`Hasher` type parameter.
`BTreeSet` implements `EntitySet` without any problems.
If an iterator type cannot guarantee uniqueness at compile time, then a
user can still attach `EntitySetIterator` to an individual instance of
that type via `UniqueEntityIter::from_iterator_unchecked`.
With this, custom types can use `UniqueEntityIter<I>` as their
`IntoIterator::IntoIter` type, if necessary.
This PR is focused on the base concept, and expansions on it are left
for follow-up PRs. See "Potential Future Work" below.
## Testing
Doctests on `iter_many_unique`/`iter_many_unique_mut` + 2 tests in
entity_set.rs.
## Showcase
```rust
// Before:
fn system(player_list: Res<SomeUniquePlayerList>, players: Query<&mut Player>) {
let value = 0;
while let Some(player) = players.iter_many_mut(player_list).fetch_next() {
value += mem::take(player.value_mut())
}
}
// After:
fn system(player_list: Res<SomeUniquePlayerList>, players: Query<&mut Player>) {
let value = players
.iter_many_unique_mut(player_list)
.map(|player| mem::take(player.value_mut()))
.sum();
}
```
## Changelog
- added `EntityBorrow`, `TrustedEntityBorrow`, `EntitySet` and
`EntitySetIterator` traits
- added `iter_many_unique`, `iter_many_unique_mut`,
`iter_many_unique_unsafe` methods on `Query`
- added `iter_many_unique`, `iter_many_unique_mut`,
`iter_many_unique_manual` and `iter_many_unique_unchecked_manual`
methods on `QueryState`
- added corresponding `QueryManyUniqueIter`
- added `UniqueEntityIter`
## Migration Guide
Any custom type used as a `Borrow<Entity>` entity list item for an
`iter_many` method now has to implement `EntityBorrow` instead. Any type
that implements `Borrow<Entity>` can trivially implement `EntityBorrow`.
## Potential Future Work
- `ToEntitySet` trait for converting any entity iterator into an
`EntitySetIterator`
- `EntityIndexSet/Map` to tie in hashing with `EntitySet`
- add `EntityIndexSetSlice/MapSlice`
- requires: `EntityIndexSet/Map`
- Implementing `par_iter_many_unique_mut` for parallel mutable iteration
- requires: `par_iter_many`
- allow collecting into `UniqueEntityVec` to store entity sets
- add `UniqueEntitySlice`s
- Doesn't require, but should be done after: `UniqueEntityVec`
- add `UniqueEntityArray`s
- Doesn't require, but should be done after: `UniqueEntitySlice`
- `get_many_unique`/`many_unique` methods
- requires: `UniqueEntityArray`
- `World::entity_unique` to match `World::entity` methods
- Doesn't require, but makes sense after:
`get_many_unique`/`many_unique`
- implement `TrustedEntityBorrow` for the `EntityRef` family
- Doesn't require, but makes sense after: `UniqueEntityVec`
# Objective
I am suspicious of the command / world helpers for input focus, since
they just provide a trivial helper for setting a resource value.
## Solution
Document that there's nothing magic about them. These can live another
day, but I would also remove them completely if y'all convince me it's
the right choice.
# Objective
Bevy now has first-class input focus handling! We should use this for
accessibility purpose via accesskit too.
## Solution
- Removed bevy_a11y::Focus.
- Replaced all usages of Focus with InputFocus
- Changed the dependency tree so bevy_a11y relies on bevy_input_focus
- Moved initialization of the focus (starts with the primary window)
from bevy_window to bevy_input_focus to avoid circular dependencies (and
it's cleaner)
## Testing
TODO
## Migration Guide
`bevy_a11y::Focus` has been replaced with `bevy_input_focus::Focus`.
# Objective
Allow handling of dead keys on some keyboard layouts.
In some cases, dead keys were impossible to get using the
`KeyboardInput` event. This information is already present in the
underlying winit `KeyEvent`, but it wasn't exposed.
## Solution
Expose the `text` field from winit's `KeyEvent` in `KeyboardInput`.
This logic is inspired egui's implementation here:
adfc0bebfc/crates/egui-winit/src/lib.rs (L790-L807)
## Testing
This is a new field, so it shouldn't break any existing functionality. I
tested that this change works by running the modified `text_input`
example on different keyboard layouts.
## Example
Using a Portuguese/ABNT2 keyboard layout on windows and pressing
<kbd>\~</kbd> followed by
<kbd>a</kbd>/<kbd>Space</kbd>/<kbd>d</kbd>/<kbd>\~</kbd> now generates
the following events:
```
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: KeyA, logical_key: Character("ã"), state: Pressed, text: Some("ã"), repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Space, logical_key: Space, state: Pressed, text: Some("~"), repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: KeyD, logical_key: Character("d"), state: Pressed, text: Some("~d"), repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: Some("~~"), repeat: false, window: 0v1#4294967296 }
```
The logic for getting an input is pretty simple: check if `text` is
`Some`. If it is, this is actual input text, otherwise it isn't.
There's a small caveat: certain keys generate control characters in the
input text, which needs to be filtered out:
```
KeyboardInput { key_code: Escape, logical_key: Escape, state: Pressed, text: Some("\u{1b}"), repeat: false, window: 0v1#4294967296 }
```
I've updated the text_input example to include egui's solution to this,
which works well.
## Migration Guide
The `KeyboardInput` event now has a new `text` field.
# Objective
- Contributes to #15460
## Solution
- Added the following features:
- `std` (default)
- `async_executor` (default)
- `edge_executor`
- `critical-section`
- `portable-atomic`
- Gated `tracing` in `bevy_utils` to allow compilation on certain
platforms
- Switched from `tracing` to `log` for simple message logging within
`bevy_ecs`. Note that `tracing` supports capturing from `log` so this
should be an uncontroversial change.
- Fixed imports and added feature gates as required
- Made `bevy_tasks` optional within `bevy_ecs`. Turns out it's only
needed for parallel operations which are already gated behind
`multi_threaded` anyway.
## Testing
- Added to `compile-check-no-std` CI command
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section,portable-atomic --target
thumbv6m-none-eabi`
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section`
- `cargo check -p bevy_ecs --no-default-features`
## Draft Release Notes
Bevy's core ECS now supports `no_std` platforms.
In prior versions of Bevy, it was not possible to work with embedded or
niche platforms due to our reliance on the standard library, `std`. This
has blocked a number of novel use-cases for Bevy, such as an embedded
database for IoT devices, or for creating games on retro consoles.
With this release, `bevy_ecs` no longer requires `std`. To use Bevy on a
`no_std` platform, you must disable default features and enable the new
`edge_executor` and `critical-section` features. You may also need to
enable `portable-atomic` and `critical-section` if your platform does
not natively support all atomic types and operations used by Bevy.
```toml
[dependencies]
bevy_ecs = { version = "0.16", default-features = false, features = [
# Required for platforms with incomplete atomics (e.g., Raspberry Pi Pico)
"portable-atomic",
"critical-section",
# Optional
"bevy_reflect",
"serialize",
"bevy_debug_stepping",
"edge_executor"
] }
```
Currently, this has been tested on bare-metal x86 and the Raspberry Pi
Pico. If you have trouble using `bevy_ecs` on a particular platform,
please reach out either through a GitHub issue or in the `no_std`
working group on the Bevy Discord server.
Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!
## Notes
- Creating PR in draft to ensure CI is passing before requesting
reviews.
- This implementation has no support for multithreading in `no_std`,
especially due to `NonSend` being unsound if allowed in multithreading.
The reason is we cannot check the `ThreadId` in `no_std`, so we have no
mechanism to at-runtime determine if access is sound.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Vic <59878206+Victoronz@users.noreply.github.com>
# Objective
I have something of a niche use case. I have a camera rendering pixel
art with a scale factor set, and another camera that renders to an
off-screen texture which is supposed to match the main camera exactly.
However, when computing camera target info, Bevy [hardcodes a scale
factor of
1.0](116c2b02fe/crates/bevy_render/src/camera/camera.rs (L828))
for image targets which means that my main camera and my image target
camera get different `OrthographicProjections` calculated.
## Solution
This PR adds an `ImageRenderTarget` struct which allows scale factors to
be specified.
## Testing
I tested the affected examples on macOS and they still work. This is an
additive change and should not break any existing code, apart from what
is trivially fixable by following compiler error messages.
---
## Migration Guide
`RenderTarget::Image` now takes an `ImageRenderTarget` instead of a
`Handle<Image>`. You can call `handle.into()` to construct an
`ImageRenderTarget` using the same settings as before.
# 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()`.
# Objective
Example error message beforehand:
```
error[B0001]: Query<&mut Data, ()> in system bevytest::main::{{closure}} accesses component(s)Data in a way that conflicts with a previous…
```
# Objective
Implement a new `AssetChanged` query filter that allows users to query
for entities whose related assets may have changed.
- Closes https://github.com/bevyengine/bevy/issues/5069
- Unblocks #16420. Currently, `cold-specialization`, a key rendering
optimization for unlocking ancillary benefits of the retained render
world, is blocked on being unable detect all scenarios in which an
entity's mesh/material changes using events and observers. An
`AssetChanged` filter will drastically simplify our implementation and
be more robust to future changes.
Originally implemented by @nicopap in #5080.
## Solution
- Adds a new `AssetChanged` query filter that initializes a
`AssetChanges<A>` resource that tracks changed assets and ticks in
`asset_events`.
- ~Reverts #13343 and changes the api of `get_state` to accept `impl
Into<UnsafeWorldCell<'w>>` to allow accessing the `AssetChanges<A>`
resource.~
- Adds a `AsAssetId` trait used for newtype handle wrappers (e.g.
`Mesh3d`) that allows associating a component with the underlying
`Asset` it represents.
## Testing
- Tests are added for `AssetChanged`.
- TBD on performance. We are going to add this `Mesh3d` and
`MeshMaterial3d` (etc) in the renderer. Long term wins in render
performance this unblocks should swamp tracking overhead for any
realistic workload.
## Migration Guide
- The `asset_events` system is no longer public. Users should order
their systems relative to the `AssetEvents` system set.
---------
Co-authored-by: Nicola Papale <nico@nicopap.ch>
Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
- Cleanup deprecated code
## Solution
- Removed `#[deprecated]` items which were marked as such in 0.15 or
prior versions.
## Migration Guide
- The following deprecated items were removed: `Events::get_reader`,
`Events::get_reader_current`, `ManualEventReader`,
`Condition::and_then`, `Condition::or_else`, `World::,many_entities`,
`World::many_entities_mut`, `World::get_many_entities`,
`World::get_many_entities_dynamic`, `World::get_many_entities_mut`,
`World::get_many_entities_dynamic_mut`,
`World::get_many_entities_from_set_mut`
# Objective
Expand `track_change_detection` feature to also track entity spawns and
despawns. Use this to create better error messages.
# Solution
Adds `Entities::entity_get_spawned_or_despawned_by` as well as `{all
entity reference types}::spawned_by`.
This also removes the deprecated `get_many_entities_mut` & co (and
therefore can't land in 0.15) because we don't yet have no Polonius.
## Testing
Added a test that checks that the locations get updated and these
updates are ordered correctly vs hooks & observers.
---
## Showcase
Access location:
```rust
let mut world = World::new();
let entity = world.spawn_empty().id();
println!("spawned by: {}", world.entity(entity).spawned_by());
```
```
spawned by: src/main.rs:5:24
```
Error message (with `track_change_detection`):
```rust
world.despawn(entity);
world.entity(entity);
```
```
thread 'main' panicked at src/main.rs:11:11:
Entity 0v1#4294967296 was despawned by src/main.rs:10:11
```
and without:
```
thread 'main' panicked at src/main.rs:11:11:
Entity 0v1#4294967296 does not exist (enable `track_change_detection` feature for more details)
```
Similar error messages now also exists for `Query::get`,
`World::entity_mut`, `EntityCommands` creation and everything that
causes `B0003`, e.g.
```
error[B0003]: Could not insert a bundle (of type `MaterialMeshBundle<StandardMaterial>`) for entity Entity { index: 7, generation: 1 }, which was despawned by src/main.rs:10:11. See: https://bevyengine.org/learn/errors/#b0003
```
---------
Co-authored-by: kurk070ff <108901106+kurk070ff@users.noreply.github.com>
Co-authored-by: Freya Pines <freya@MacBookAir.lan>
Co-authored-by: Freya Pines <freya@Freyas-MacBook-Air.local>
Co-authored-by: Matty Weatherley <weatherleymatthew@gmail.com>
The only thing that was preventing `extract_meshes_for_gpu_building` and
`extract_mesh_materials` from running in parallel was the
`ResMut<RenderMeshMaterialIds>`. This lookup can be safely moved to the
`collect_meshes_for_gpu_building` phase, which runs after the extraction
phase.
This results in a small win on `many_cubes`. `extract_mesh_materials` is
currently nonretained, so it's still slow, but running it in parallel is
an easy win.
Before:

After:

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
When calling any of the `sort` methods on a `QueryManyIter` with mutable
data, `collect_inner()` must be called before fetching items. Remove the
need for that call.
## Solution
Have the `sort` methods `collect()` the entity list into a `Vec` before
returning.
# Objective
Allow resources to be accessed soundly by `QueryData` and `QueryFilter`
implementations.
This mostly works today, and is used in `bevy-trait-query` and will be
used by #16810. The problem is that the access is not made visible to
the executor, so it would be possible for a system with resource access
in a query to run concurrently with a system that accesses the resource
with `ResMut`, resulting in Undefined Behavior.
## Solution
Define calling `add_resource_read` or `add_resource_write` in
`WorldQuery::update_component_access` to be a supported way to declare
resource access in a query.
Modify `QueryState::new_with_access` to check for resource access and
report it in `archetype_component_acccess`.
Modify `FilteredAccess::is_compatible` to consider resource access
conflicting even on queries with disjoint filters.
# 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
This PR continues the work of `bevy_input_focus` by adding a pluggable
tab navigation framework.
As part of this work, `FocusKeyboardEvent` now propagates to the window
after exhausting all ancestors.
## Testing
Unit tests and manual tests.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This PR adds support for *mixed lighting* to Bevy, whereby some parts of
the scene are lightmapped, while others take part in real-time lighting.
(Here *real-time lighting* means lighting at runtime via the PBR shader,
as opposed to precomputed light using lightmaps.) It does so by adding a
new field, `affects_lightmapped_meshes` to `IrradianceVolume` and
`AmbientLight`, and a corresponding field
`affects_lightmapped_mesh_diffuse` to `DirectionalLight`, `PointLight`,
`SpotLight`, and `EnvironmentMapLight`. By default, this value is set to
true; when set to false, the light contributes nothing to the diffuse
irradiance component to meshes with lightmaps.
Note that specular light is unaffected. This is because the correct way
to bake specular lighting is *directional lightmaps*, which we have no
support for yet.
There are two general ways I expect this field to be used:
1. When diffuse indirect light is baked into lightmaps, irradiance
volumes and reflection probes shouldn't contribute any diffuse light to
the static geometry that has a lightmap. That's because the baking tool
should have already accounted for it, and in a higher-quality fashion,
as lightmaps typically offer a higher effective texture resolution than
the light probe does.
2. When direct diffuse light is baked into a lightmap, punctual lights
shouldn't contribute any diffuse light to static geometry with a
lightmap, to avoid double-counting. It may seem odd to bake *direct*
light into a lightmap, as opposed to indirect light. But there is a use
case: in a scene with many lights, avoiding light leaks requires shadow
mapping, which quickly becomes prohibitive when many lights are
involved. Baking lightmaps allows light leaks to be eliminated on static
geometry.
A new example, `mixed_lighting`, has been added. It demonstrates a sofa
(model from the [glTF Sample Assets]) that has been lightmapped offline
using [Bakery]. It has four modes:
1. In *baked* mode, all objects are locked in place, and all the diffuse
direct and indirect light has been calculated ahead of time. Note that
the bottom of the sphere has a red tint from the sofa, illustrating that
the baking tool captured indirect light for it.
2. In *mixed direct* mode, lightmaps capturing diffuse direct and
indirect light have been pre-calculated for the static objects, but the
dynamic sphere has real-time lighting. Note that, because the diffuse
lighting has been entirely pre-calculated for the scenery, the dynamic
sphere casts no shadow. In a real app, you would typically use real-time
lighting for the most important light so that dynamic objects can shadow
the scenery and relegate baked lighting to the less important lights for
which shadows aren't as important. Also note that there is no red tint
on the sphere, because there is no global illumination applied to it. In
an actual game, you could fix this problem by supplementing the
lightmapped objects with an irradiance volume.
3. In *mixed indirect* mode, all direct light is calculated in
real-time, and the static objects have pre-calculated indirect lighting.
This corresponds to the mode that most applications are expected to use.
Because direct light on the scenery is computed dynamically, shadows are
fully supported. As in mixed direct mode, there is no global
illumination on the sphere; in a real application, irradiance volumes
could be used to supplement the lightmaps.
4. In *real-time* mode, no lightmaps are used at all, and all punctual
lights are rendered in real-time. No global illumination exists.
In the example, you can click around to move the sphere, unless you're
in baked mode, in which case the sphere must be locked in place to be
lit correctly.
## Showcase
Baked mode:

Mixed direct mode:

Mixed indirect mode (default):

Real-time mode:

## Migration guide
* The `AmbientLight` resource, the `IrradianceVolume` component, and the
`EnvironmentMapLight` component now have `affects_lightmapped_meshes`
fields. If you don't need to use that field (for example, if you aren't
using lightmaps), you can safely set the field to true.
* `DirectionalLight`, `PointLight`, and `SpotLight` now have
`affects_lightmapped_mesh_diffuse` fields. If you don't need to use that
field (for example, if you aren't using lightmaps), you can safely set
the field to true.
[glTF Sample Assets]:
https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main
[Bakery]:
https://geom.io/bakery/wiki/index.php?title=Bakery_-_GPU_Lightmapper
# Objective
- Wgpu barrier tracking is expensive. Making buffers read-only makes
ideally lets wgpu skip worrying about barriers, although in wgpu 23 it
apparently won't yet.
## Solution
- Remove COPY_DST usage from AsBindGroup uniform buffers to allow future
wgpu versions to make this cheaper.
- AsBindGroup never updates buffers, so there's no need for COPY_DST. We
always recreate all buffers and the bind group every time data changes,
which yeah is also expensive.
## Testing
- Ran the animated materials example with/without bindless enabled. No
crashes.
This commit allows Bevy to bind 16 lightmaps at a time, if the current
platform supports bindless textures. Naturally, if bindless textures
aren't supported, Bevy falls back to binding only a single lightmap at a
time. As lightmaps are usually heavily atlased, I doubt many scenes will
use more than 16 lightmap textures.
This has little performance impact now, but it's desirable for us to
reap the benefits of multidraw and bindless textures on scenes that use
lightmaps. Otherwise, we might have to break batches in order to switch
those lightmaps.
Additionally, this PR slightly reduces the cost of binning because it
makes the lightmap index in `Opaque3dBinKey` 32 bits instead of an
`AssetId`.
## Migration Guide
* The `Opaque3dBinKey::lightmap_image` field is now
`Opaque3dBinKey::lightmap_slab`, which is a lightweight identifier for
an entire binding array of lightmaps.
# 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
`PartialReflect::serializable` is unused in the codebase and should be
removed.
I believe it originally was used to handle serializing certain types but
that's no longer the case.
## Solution
Remove `PartialReflect::serializable`.
## Testing
You can check locally using:
```
cargo check -p bevy_reflect --all-features
```
---
## Migration Guide
`PartialReflect::serializable` has been removed. If you were using this
to pass on serialization information, use `ReflectSerialize` instead or
create custom type data to generate the `Serializable`.
# 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
Thanks to @eugineerd's work on entity cloning (#16132), we now have a
robust way to copy components between entities. We can extend this to
implement some useful functionality that would have been more
complicated before.
Closes#15350.
## Solution
`EntityCloneBuilder` now automatically includes required components
alongside any component added/removed from the component filter.
Added the following methods to `EntityCloneBuilder`:
- `move_components`
- `without_required_components`
Added the following methods to `EntityWorldMut` and `EntityCommands`:
- `clone_with`
- `clone_components`
- `move_components`
Also added `clone_and_spawn` and `clone_and_spawn_with` to
`EntityWorldMut` (`EntityCommands` already had them).
## Showcase
```
assert_eq!(world.entity(entity_a).get::<B>(), Some(&B));
assert_eq!(world.entity(entity_b).get::<B>(), None);
world.entity_mut(entity_a).clone_components::<B>(entity_b);
assert_eq!(world.entity(entity_a).get::<B>(), Some(&B));
assert_eq!(world.entity(entity_b).get::<B>(), Some(&B));
assert_eq!(world.entity(entity_a).get::<C>(), Some(&C(5)));
assert_eq!(world.entity(entity_b).get::<C>(), None);
world.entity_mut(entity_a).move_components::<C>(entity_b);
assert_eq!(world.entity(entity_a).get::<C>(), None);
assert_eq!(world.entity(entity_b).get::<C>(), Some(&C(5)));
```
# Objective
- Prework for reviving #9582.
## Solution
- Move the two types to volume.rs and made it compile.
- Also `#[reflect(Debug)]` on `Volume` while I'm here.
## Testing
- Ran example locally.
- Rely on CI.
# Objective
- #16813 added the ability to mute sinks and added a new method
`toggle_mute()`.
- Leaving `toggle()` as is creates inconsistency and a bit of confusion
about what is being toggled.
## Solution
- Rename `toggle()` to `toggle_playback()`.
- The choice to use the `_playback` suffix was easy because the method
comment was already telling us what is being toggled: `Toggles playback
of the sink.`
- [Raised in Discord] and got the OK from Alice.
[Raised in Discord]:
https://discord.com/channels/691052431525675048/749430447326625812/1318000355824504905
## Testing
- I ran the example and also updated the instruction text to make it
clear `Space` is toggling the playback not just pausing.
- I added a unit test for `toggle_playback()` because why not.
---
## Showcase
Example instructions:
<img width="292" alt="image"
src="https://github.com/user-attachments/assets/585c36c6-c4d7-428b-acbe-a92f3a37b460"
/>
## Migration Guide
- `AudioSinkPlayback`'s `toggle` method has been renamed to
`toggle_playback`. This was done to create consistency with the
`toggle_mute` method added in
https://github.com/bevyengine/bevy/pull/16813. Change instances of
`toggle` to `toggle_playback`. E.g.:
Before:
```rust
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle();
}
}
```
After:
```rust
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink>) {
if keyboard_input.just_pressed(KeyCode::Space) {
sink.toggle_playback();
}
}
```
# 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
- Allow users to mute audio.
```rust
fn mute(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut sink: Single<&mut AudioSink, With<MyMusic>>,
) {
if keyboard_input.just_pressed(KeyCode::KeyM) {
sink.toggle_mute();
}
}
```
- I want to be able to press, say, `M` and mute all my audio. I want
this for dev, but I'm sure it's a useful player setting as well.
- Muting is different to pausing—I don't want to pause my sounds, I want
them to keep playing but with no volume. For example if I have
background music playing which is made up of 5 tracks, I want to be able
to temporarily mute my background music, and if I unmute at, say, track
4, I want to play track 4 rather than have had everything paused and
still be on the first track.
- I want to be able to continue to control the volume of my audio even
when muted. Like in the example, if I have muted my audio but I use the
volume up/down controls, I want Bevy to remember those volume changes so
that when I unmute, the volume corresponds to that.
## Solution
- Add methods to audio to allow muting, unmuting and toggling muting.
- To preserve the user's intended volume, each sink needs to keep track
of a "managed volume".
- I checked `rodio` and I don't see any built in support for doing this,
so I added it to `bevy_audio`.
- I'm interested to hear if this is a good idea or a bad idea. To me,
this API looks nice and looks usable, but I'm aware it involves some
changes to the existing API and now also requires mutable access in some
places compared to before.
- I'm also aware of work on *Better Audio*, but I'm hoping that if this
change isn't too wild it might be a useful addition considering we don't
really know when we'll eventually get better audio.
## Testing
- Update and run the example: `cargo run --example audio_control`
- Run the example: `cargo run --example soundtrack`
- Update and run the example: `cargo run --example spatial_audio_3d`
- Add unit tests.
---
## Showcase
See 2 changed examples that show how you can mute an audio sink and a
spatial audio sink.
## Migration Guide
- The `AudioSinkPlayback` trait now has 4 new methods to allow you to
mute audio sinks: `is_muted`, `mute`, `unmute` and `toggle_mute`. You
can use these methods on `bevy_audio`'s `AudioSink` and
`SpatialAudioSink` components to manage the sink's mute state.
- `AudioSinkPlayback`'s `set_volume` method now takes a mutable
reference instead of an immutable one. Update your code which calls
`set_volume` on `AudioSink` and `SpatialAudioSink` components to take a
mutable reference. E.g.:
Before:
```rust
fn increase_volume(sink: Single<&AudioSink>) {
sink.set_volume(sink.volume() + 0.1);
}
```
After:
```rust
fn increase_volume(mut sink: Single<&mut AudioSink>) {
let current_volume = sink.volume();
sink.set_volume(current_volume + 0.1);
}
```
- The `PlaybackSettings` component now has a `muted` field which you can
use to spawn your audio in a muted state. `PlaybackSettings` also now
has a helper method `muted` which you can use when building the
component. E.g.:
```rust
commands.spawn((
// ...
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP.with_spatial(true).muted(),
));
```
---------
Co-authored-by: Nathan Graule <solarliner@gmail.com>
I forgot to set `BINDLESS_SLOT_COUNT` in `ExtendedMaterial`'s
implementation of `AsBindGroup`, so it didn't actually become bindless.
In fact, it would usually crash with a shader/bind group layout
mismatch, because some parts of Bevy's renderer thought that the
resulting material was bindless while other parts didn't. This commit
corrects the situation.
I had to make `BINDLESS_SLOT_COUNT` a function instead of a constant
because the `ExtendedMaterial` version needs some logic. Unfortunately,
trait methods can't be `const fn`s, so it has to be a runtime function.
# 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
- Minor consistency improvement in proc macro code.
- Remove `get_path_direct` since it was only used once anyways and
doesn't add much.
## Solution
- Possibly a minor performance improvement since the `Cargo.toml` wont
be parsed as often.
## Testing
- I don't think it breaks anything.
- This is my first time working on bevy itself. Is there a script to do
a quick verify of my pr?
## Other PR
Similar to #7536 but has no extra dependencies.
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- Describe the objective or issue this PR addresses.
- If you're fixing a specific issue, say "Fixes #X".
## Solution
- Describe the solution used to achieve the objective above.
## Testing
- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
---
## Showcase
> This section is optional. If this PR does not include a visual change
or does not add a new feature, you can delete this section.
- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR adds a new feature or public API, consider adding a brief
pseudo-code snippet of it in action
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
- If you want, you could even include a before/after comparison!
- If the Migration Guide adequately covers the changes, you can delete
this section
While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:
<details>
<summary>Click to view showcase</summary>
```rust
println!("My super cool code.");
```
</details>
## Migration Guide
> This section is optional. If there are no breaking changes, you can
delete this section.
- 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.
# Objective
- Writing an API, and I want to allow users to pass in extra data
alongside the API provided input, and tuples are the most natural
extension in this case.
- Bring `SystemInput` up to par with `SystemParam` for tuple support.
## Solution
- Added impls for tuples up to 8 elements. If you need a 9-arity tuple
or more, write your own `SystemInput` type (it's incredibly simple to
do).
## Testing
- Added a test demonstrating this.
---
## Showcase
Tuples of arbitrary`SystemInput`s are now supported:
```rust
fn by_value((In(a), In(b)): (In<usize>, In<usize>)) -> usize {
a + b
}
fn by_mut((InMut(a), In(b)): (InMut<usize>, In<usize>)) {
*a += b;
}
let mut world = World::new();
let mut by_value = IntoSystem::into_system(by_value);
let mut by_mut = IntoSystem::into_system(by_mut);
by_value.initialize(&mut world);
by_mut.initialize(&mut world);
assert_eq!(by_value.run((12, 24), &mut world), 36);
let mut a = 10;
let b = 5;
by_mut.run((&mut a, b), &mut world);
assert_eq!(*a, 15);
```
# Objective
- Allow skiping components that don't have ComponentId yet instead of
failing `bevy/query` request.
## Solution
- Describe the solution used to achieve the objective above.
## Testing
My naive approach boils down to:
- bevy/list to get list of all components.
- bevy/query with empty components and has fields and a option that
contains result of the bevy/list.
Before that change I end up with bunch of `Component xxx isn't used in
the world` because some of the components wasn't spawned at any moment
yet in the game. Now it should work.
## Migration Guide
- `BrpQueryParams` now has `strict` boolean field. It serfs as a flag to
fail when encountering an invalid component rather than skipping it.
Defaults to false.
# Objective
Fixes#15485.
## Solution
Deletes the field! The `meta` field had no way to access or mutate it.
## Testing
- It builds!
---
## Migration Guide
- `ErasedAssetLoader` now takes a borrow to `AssetMetaDyn` instead of a
`Box`.
- `LoadedAsset::new_with_dependencies` no longer requires a `meta`
argument.
- `LoadContext::finish` no longer requires a `meta` argument.
# Objective
- `PointerInteraction` components should be updated before sending
picking events. Otherwise they will be stale when event observers run.
- Allow inserting logic before picking events but after
`PointerInteraction` components have been updated.
## Solution
- Reorder systems in `PickSet::Focus`.
This patch replaces the undocumented `NoGpuCulling` component with a new
component, `NoIndirectDrawing`, effectively turning indirect drawing on
by default. Indirect mode is needed for the recently-landed multidraw
feature (#16427). Since multidraw is such a win for performance, when
that feature is supported the small performance tax that indirect mode
incurs is virtually always worth paying.
To ensure that custom drawing code such as that in the
`custom_shader_instancing` example continues to function, this commit
additionally makes GPU culling take the `NoFrustumCulling` component
into account.
This PR is an alternative to #16670 that doesn't break the
`custom_shader_instancing` example. **PR #16755 should land first in
order to avoid breaking deferred rendering, as multidraw currently
breaks it**.
## Migration Guide
* Indirect drawing (GPU culling) is now enabled by default, so the
`GpuCulling` component is no longer available. To disable indirect mode,
which may be useful with custom render nodes, add the new
`NoIndirectDrawing` component to your camera.
## Objective
Some structs and methods in the ECS internals have names that don't
describe their purpose very well, and sometimes don't have docs either.
Also, the function `remove_bundle_from_archetype` is a counterpart to
`BundleInfo::add_bundle_to_archetype`, but isn't a method and is in a
different file.
## Solution
- Renamed the following structs and added docs:
| Before | After |
|----------------------|------------------------------|
| `AddBundle` | `ArchetypeAfterBundleInsert` |
| `InsertBundleResult` | `ArchetypeMoveType` |
- Renamed the following methods:
| Before | After |
|---------------------------------------|----------------------------------------------|
| `Edges::get_add_bundle` | `Edges::get_archetype_after_bundle_insert` |
| `Edges::insert_add_bundle` |
`Edges::cache_archetype_after_bundle_insert` |
| `Edges::get_remove_bundle` |
`Edges::get_archetype_after_bundle_remove` |
| `Edges::insert_remove_bundle` |
`Edges::cache_archetype_after_bundle_remove` |
| `Edges::get_take_bundle` | `Edges::get_archetype_after_bundle_take` |
| `Edges::insert_take_bundle` |
`Edges::cache_archetype_after_bundle_take` |
- Moved `remove_bundle_from_archetype` from `world/entity_ref.rs` to
`BundleInfo`. I left the function in entity_ref in the first commit for
comparison, look there for the diff of comments and whatnot.
- Tidied up docs:
- General grammar and spacing.
- Made the usage of "insert" and "add" more consistent.
- Removed references to information that isn't there.
- Renamed `BundleInfo::add_bundle_to_archetype` to
`BundleInfo::insert_bundle_into_archetype` for consistency.
# Objective
I was curious to use the newly created `bevy_input_focus`, but I found
some issues with it
- It was only implementing traits for `World`.
- Lack of tests
- `is_focus_within` logic was incorrect.
## Solution
This PR includes some improvements to the `bevy_input_focus` crate:
- Add new `IsFocusedHelper` that doesn't require access to `&World`. It
implements `IsFocused`
- Remove `IsFocused` impl for `DeferredWorld`. Since it already
implements `Deref<Target=World>` it was just duplication of code.
- impl `SetInputFocus` for `Commands`. There was no way to use
`SetFocusCommand` directly. This allows it.
- The `is_focus_within` logic has been fixed to check descendants.
Previously it was checking if any of the ancestors had focus which is
not correct according to the documentation.
- Added a bunch of unit tests to verify the logic of the crate.
## Testing
- Did you test these changes? If so, how? Yes, running newly added unit
tests.
---
# Objective
Fixes#16776
## Solution
- reflect `&'static Location` as an opaque type
- I've added this to `impls/std.rs` because other core types are there
too. Maybe they should be split out into a `core.rs` in another PR.
- add source location to `EventId` (behind the
`tracking_change_detection` feature flag)
## Testing
---
## Showcase
```rust
fn apply_damage_to_health(
mut dmg_events: EventReader<DealDamage>,
) {
for (event, event_id) in dmg_events.read_with_id() {
info!(
"Applying {} damage, triggered by {}",
event.amount, event_id.caller
);
…
```
```
2024-12-12T01:21:50.126827Z INFO event: Applying 9 damage, triggered by examples/ecs/event.rs:47:16
```
## Migration Guide
- If you manually construct a `SendEvent`, use `SendEvent::new()`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# 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>