# Objective
Add a viewport widget.
## Solution
- Add a new `ViewportNode` component to turn a UI node into a viewport.
- Add `viewport_picking` to pass pointer inputs from other pointers to
the viewport's pointer.
- Notably, this is somewhat functionally different from the viewport
widget in [the editor
prototype](https://github.com/bevyengine/bevy_editor_prototypes/pull/110/files#L124),
which just moves the pointer's location onto the render target. Viewport
widgets have their own pointers.
- Care is taken to handle dragging in and out of viewports.
- Add `update_viewport_render_target_size` to update the viewport node's
render target's size if the node size changes.
- Feature gate picking-related viewport items behind
`bevy_ui_picking_backend`.
## Testing
I've been using an example I made to test the widget (and added it as
`viewport_node`):
<details><summary>Code</summary>
```rust
//! A simple scene to demonstrate spawning a viewport widget. The example will demonstrate how to
//! pick entities visible in the widget's view.
use bevy::picking::pointer::PointerInteraction;
use bevy::prelude::*;
use bevy::ui::widget::ViewportNode;
use bevy::{
image::{TextureFormatPixelInfo, Volume},
window::PrimaryWindow,
};
use bevy_render::{
camera::RenderTarget,
render_resource::{
Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
},
};
fn main() {
App::new()
.add_plugins((DefaultPlugins, MeshPickingPlugin))
.add_systems(Startup, test)
.add_systems(Update, draw_mesh_intersections)
.run();
}
#[derive(Component, Reflect, Debug)]
#[reflect(Component)]
struct Shape;
fn test(
mut commands: Commands,
window: Query<&Window, With<PrimaryWindow>>,
mut images: ResMut<Assets<Image>>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Spawn a UI camera
commands.spawn(Camera3d::default());
// Set up an texture for the 3D camera to render to
let window = window.get_single().unwrap();
let window_size = window.physical_size();
let size = Extent3d {
width: window_size.x,
height: window_size.y,
..default()
};
let format = TextureFormat::Bgra8UnormSrgb;
let image = Image {
data: Some(vec![0; size.volume() * format.pixel_size()]),
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
let image_handle = images.add(image);
// Spawn the 3D camera
let camera = commands
.spawn((
Camera3d::default(),
Camera {
// Render this camera before our UI camera
order: -1,
target: RenderTarget::Image(image_handle.clone().into()),
..default()
},
))
.id();
// Spawn something for the 3D camera to look at
commands
.spawn((
Mesh3d(meshes.add(Cuboid::new(5.0, 5.0, 5.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Transform::from_xyz(0.0, 0.0, -10.0),
Shape,
))
// We can observe pointer events on our objects as normal, the
// `bevy::ui::widgets::viewport_picking` system will take care of ensuring our viewport
// clicks pass through
.observe(on_drag_cuboid);
// Spawn our viewport widget
commands
.spawn((
Node {
position_type: PositionType::Absolute,
top: Val::Px(50.0),
left: Val::Px(50.0),
width: Val::Px(200.0),
height: Val::Px(200.0),
border: UiRect::all(Val::Px(5.0)),
..default()
},
BorderColor(Color::WHITE),
ViewportNode::new(camera),
))
.observe(on_drag_viewport);
}
fn on_drag_viewport(drag: Trigger<Pointer<Drag>>, mut node_query: Query<&mut Node>) {
if matches!(drag.button, PointerButton::Secondary) {
let mut node = node_query.get_mut(drag.target()).unwrap();
if let (Val::Px(top), Val::Px(left)) = (node.top, node.left) {
node.left = Val::Px(left + drag.delta.x);
node.top = Val::Px(top + drag.delta.y);
};
}
}
fn on_drag_cuboid(drag: Trigger<Pointer<Drag>>, mut transform_query: Query<&mut Transform>) {
if matches!(drag.button, PointerButton::Primary) {
let mut transform = transform_query.get_mut(drag.target()).unwrap();
transform.rotate_y(drag.delta.x * 0.02);
transform.rotate_x(drag.delta.y * 0.02);
}
}
fn draw_mesh_intersections(
pointers: Query<&PointerInteraction>,
untargetable: Query<Entity, Without<Shape>>,
mut gizmos: Gizmos,
) {
for (point, normal) in pointers
.iter()
.flat_map(|interaction| interaction.iter())
.filter_map(|(entity, hit)| {
if !untargetable.contains(*entity) {
hit.position.zip(hit.normal)
} else {
None
}
})
{
gizmos.arrow(point, point + normal.normalize() * 0.5, Color::WHITE);
}
}
```
</details>
## Showcase
https://github.com/user-attachments/assets/39f44eac-2c2a-4fd9-a606-04171f806dc1
## Open Questions
- <del>Not sure whether the entire widget should be feature gated behind
`bevy_ui_picking_backend` or not? I chose a partial approach since maybe
someone will want to use the widget without any picking being
involved.</del>
- <del>Is `PickSet::Last` the expected set for `viewport_picking`?
Perhaps `PickSet::Input` is more suited.</del>
- <del>Can `dragged_last_frame` be removed in favor of a better dragging
check? Another option that comes to mind is reading `Drag` and `DragEnd`
events, but this seems messier.</del>
---------
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Stop using `ArchetypeComponentId` in the executor. These IDs will grow
even more quickly with relations, and the size may start to degrade
performance.
## Solution
Have systems expose their `FilteredAccessSet<ComponentId>`, and have the
executor use that to determine which systems conflict. This can be
determined statically, so determine all conflicts during initialization
and only perform bit tests when running.
## Testing
I ran many_foxes and didn't see any performance changes. It's probably
worth testing this with a wider range of realistic schedules to see
whether the reduced concurrency has a cost in practice, but I don't know
what sort of test cases to use.
## Migration Guide
The schedule will now prevent systems from running in parallel if there
*could* be an archetype that they conflict on, even if there aren't
actually any. For example, these systems will now conflict even if no
entity has both `Player` and `Enemy` components:
```rust
fn player_system(query: Query<(&mut Transform, &Player)>) {}
fn enemy_system(query: Query<(&mut Transform, &Enemy)>) {}
```
To allow them to run in parallel, use `Without` filters, just as you
would to allow both queries in a single system:
```rust
// Either one of these changes alone would be enough
fn player_system(query: Query<(&mut Transform, &Player), Without<Enemy>>) {}
fn enemy_system(query: Query<(&mut Transform, &Enemy), Without<Player>>) {}
```
# Objective
- When loading a folder with dot files inside, Bevy crashes:
```
thread 'IO Task Pool (1)' panicked at crates/bevy_asset/src/io/mod.rs:260:10:
asset paths must have extensions
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
- those files are common for other tools to store their
settings/metadata
## Solution
- Ignore files starting with a dot when loading folders
# Objective
Prevent using exclusive systems as observers. Allowing them is unsound,
because observers are only expected to have `DeferredWorld` access, and
the observer infrastructure will keep pointers that are invalidated by
the creation of `&mut World`.
See
https://github.com/bevyengine/bevy/actions/runs/14778342801/job/41491517847?pr=19011
for a MIRI failure in a recent PR caused by an exclusive system being
used as an observer in a test.
## Solution
Have `Observer::new` panic if `System::is_exclusive()` is true. Document
that method, and methods that call it, as panicking.
(It should be possible to express this in the type system so that the
calls won't even compile, but I did not want to attempt that.)
## Testing
Added a unit test that calls `World::add_observer` with an exclusive
system.
# Objective
I've been tinkering with ECS insertion/removal lately, and noticed that
sparse sets just... don't interact with `InsertMode` at all. Sure
enough, using `insert_if_new` with a sparse component does the same
thing as `insert`.
# Solution
- Add a check in `BundleInfo::write_components` to drop the new value if
the entity already has the component and `InsertMode` is `Keep`.
- Add necessary methods to sparse set internals to fetch the drop
function.
# Testing
Minimal reproduction:
<details>
<summary>Code</summary>
```
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(PostStartup, component_print)
.run();
}
#[derive(Component)]
#[component(storage = "SparseSet")]
struct SparseComponent(u32);
fn setup(mut commands: Commands) {
let mut entity = commands.spawn_empty();
entity.insert(SparseComponent(1));
entity.insert(SparseComponent(2));
let mut entity = commands.spawn_empty();
entity.insert(SparseComponent(3));
entity.insert_if_new(SparseComponent(4));
}
fn component_print(query: Query<&SparseComponent>) {
for component in &query {
info!("{}", component.0);
}
}
```
</details>
Here it is on Bevy Playground (0.15.3):
https://learnbevy.com/playground?share=2a96a68a81e804d3fdd644a833c1d51f7fa8dd33fc6192fbfd077b082a6b1a41
Output on `main`:
```
2025-05-04T17:50:50.401328Z INFO system{name="fork::component_print"}: fork: 2
2025-05-04T17:50:50.401583Z INFO system{name="fork::component_print"}: fork: 4
```
Output with this PR :
```
2025-05-04T17:51:33.461835Z INFO system{name="fork::component_print"}: fork: 2
2025-05-04T17:51:33.462091Z INFO system{name="fork::component_print"}: fork: 3
```
# Objective
- Contributes to #18978
## Solution
- Disable default features on all dependencies in `bevy_asset` and
explicitly enable ones that are required.
- Remove `compile_error` caused by enabling `file_watcher` without
`multi_threaded` by including `multi_threaded` in `file_watcher`.
## Testing
- CI
---
## Notes
No breaking changes here, just a little cleaning before the more
controversial changes for `no_std` support.
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Fixes#18969
## Solution
Also updated `Aabb3d` implementation for consistency.
## Testing
Added tests for `Aabb2d` and `Aabb3d` to verify correct rotation
behavior for angles greater than 90 degrees.
# Objective
`BTreeSet` doesn't implement `RelationshipSourceCollection`.
## Solution
Implement it.
## Testing
`cargo clippy`
---
## Showcase
You can now use `BTreeSet` in a `RelationshipTarget`
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
Create a `When` system param wrapper for skipping systems that fail
validation.
Currently, the `Single` and `Populated` parameters cause systems to skip
when they fail validation, while the `Res` family causes systems to
error. Generalize this so that any fallible parameter can be used either
to skip a system or to raise an error. A parameter used directly will
always raise an error, and a parameter wrapped in `When<P>` will always
cause the system to be silently skipped.
~~Note that this changes the behavior for `Single` and `Populated`. The
current behavior will be available using `When<Single>` and
`When<Populated>`.~~
Fixes#18516
## Solution
Create a `When` system param wrapper that wraps an inner parameter and
converts all validation errors to `skipped`.
~~Change the behavior of `Single` and `Populated` to fail by default.~~
~~Replace in-engine use of `Single` with `When<Single>`. I updated the
`fallible_systems` example, but not all of the others. The other
examples I looked at appeared to always have one matching entity, and it
seemed more clear to use the simpler type in those cases.~~
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- If using a `NonNilUuid` in Bevy, it's difficult to reflect it.
## Solution
- Adds `NonNilUuid` using `impl_reflect_opaque!`.
## Testing
- Built with no issues found locally.
- Essentially the same as the `Uuid` support except without `Default`.
Co-authored-by: TM Storey <mail@tmstorey.id.au>
# Objective
Add background colors for text.
Fixes#18889
## Solution
New component `TextBackgroundColor`, add it to any UI `Text` or
`TextSpan` entity to add a background color to its text.
New field on `TextLayoutInfo` `section_rects` holds the list of bounding
rects for each text section.
The bounding rects are generated in `TextPipeline::queue_text` during
text layout, `extract_text_background_colors` extracts the colored
background rects for rendering.
Didn't include `Text2d` support because of z-order issues.
The section rects can also be used to implement interactions targeting
individual text sections.
## Testing
Includes a basic example that can be used for testing:
```
cargo run --example text_background_colors
```
---
## Showcase

Using a proportional font with kerning the results aren't so tidy (since
the bounds of adjacent glyphs can overlap) but it still works fine:

---------
Co-authored-by: Olle Lukowski <lukowskiolle@gmail.com>
Co-authored-by: Gilles Henaux <ghx_github_priv@fastmail.com>
Adopted #13869
# Objective
Fixes#9076
## Solution
Using `rodio`'s `try_seek`
## Testing
@ivanstepanovftw added a `seek` system using `AudioSink` to the
`audio_control.rs` example. I got it working with .mp3 files, but rodio
doesn't support seeking for .ogg and .flac files, so I removed it from
the commit (since the assets folder only has .ogg files). Another thing
to note is that `try_seek` fails when using `PlaybackMode::Loop`, as
`rodio::source::buffered::Buffered` doesn't support `try_seek`. I
haven't tested `SpatialAudioSink`.
## Notes
I copied the docs for `try_seek` verbatim from `rodio`, and re-exported
`rodio::source::SeekError`. I'm not completely confident in those
decisions, please let me know if I'm doing anything wrong.
</details>
---------
Co-authored-by: Ivan Stepanov <ivanstepanovftw@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
The default should be `OverflowClipBox::PaddingBox` not
`OverflowClipBox::ContentBox`
`padding-box` is the default in CSS.
## Solution
Set the default to `PaddingBox`.
## Testing
Compare the `overflow` UI example on main vs with this PR. You should
see that on main the outline around the inner node gets clipped. With
this PR by default clipping starts at the inner edge of the border (the
`padding-box`) and the outlines are visible.
Fixes#18934
# Objective
We have methods to:
- Add related entities
- Replace related entities
- Remove specific related entities
We don't have a method the remove all related entities so.
## Solution
Add a method to remove all related entities.
## Testing
A new test case.
# Objective
When implementing `SystemParam` for an object which contains a mutable
reference to World, which cannot be derived due to a required lifetime
parameter, it's necessary to check that there aren't any conflicts.
As far as I know, the is_empty method is the only way provided to check
for no conflicts at all
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/15389.
- Add documentation for RawHandleWrapper::_window field since It's
needed to drop the window at the correct time.
## Solution
- Added documentation to RawHandleWrapper::_window field as same as
WindowWrapper documentation.
## Testing
- No testing needed since it is documentation.
---
# Objective
Subtle, very minor issue. The following code fails to compile on main:
```rs
struct bevy;
#[derive(::bevy::ecs::component::Component)]
struct MyComponent;
```
The derive proc macro is pasting in essentially:
```rs
impl bevy::ecs::component::Component for MyComponent
```
...which normally works, but I've added `struct bevy`, which makes the
proc macro spit out incorrect code.
Very cursed, but to my knowledge has never been encountered in practice.
All the same, it's technically incorrect and should be fixed.
## Solution
The solution is simply to prepend `::` to crate names. Specifically, all
(all?) Bevy's derive macros determine the root crate name using
`BevyManifest`, which does some toml-parsing witchcraft to figure out
whether to qualify names using the umbrella `bevy` crate or individual
`bevy_xxx` crates. I just added a `::` to the spot where we parse the
`syn::Path`. The above example compiles properly after that.
## Testing
- CI should catch any errors since this change should cause compile
errors if for some reason they're being used in a cursed way somewhere
that would make this break something.
## Note
If this does break something for someone, this *really* needs a comment
in `BevyManifest::maybe_get_path` explaining why we can't make this
change.
# Objective
Fixes#18943
## Solution
Reintroduces support for `hashbrown`'s `HashMap` and `HashSet` types.
These were inadvertently removed when `bevy_platform` newtyped the
`hashbrown` types.
Since we removed our `hashbrown` dependency, I gated these impls behind
a `hashbrown` feature. Not entirely sure if this is necessary since we
enabled it for `bevy_reflect` through `bevy_platform` anyways. (Complex
features still confuse me a bit so let me know if I can just remove it!)
I also went ahead and preemptively implemented `TypePath` for `PassHash`
while I was here.
## Testing
You can test that it works by adding the following to a Bevy example
based on this PR (you'll also need to include `hashbrown` of course):
```rust
#[derive(Reflect)]
struct Foo(hashbrown::HashMap<String, String>);
```
Then check it compiles with:
```
cargo check --example hello_world --no-default-features --features=bevy_reflect/hashbrown
```
# Objective
- Fixes#18856.
## Solution
After PR #17633, `Camera::viewport_to_world` method corrects
`viewport_position` passed in that input so that it's offset by camera's
viewport. `Camera::viewport_to_world` is used by `make_ray` function
which in turn also offsets pointer position by viewport position, which
causes picking objects to be shifted by viewport position, and it wasn't
removed in the aforementioned PR. This second offsetting in `make_ray`
was removed.
## Testing
- I tested simple_picking example by applying some horizontal offset to
camera's viewport.
- I tested my application that displayed a single rectangle with picking
on two cameras arranged in a row. When using local bevy with this fix,
both cameras can be used for picking correctly.
- I modified split_screen example: I added observer to ground plane that
changes color on hover, and removed UI as it interfered with picking
both on master and my branch. On master, only top left camera was
triggering the observer, and on my branch all cameras could change
plane's color on hover.
- I added viewport offset to mesh_picking, with my changes it works
correctly, while on master picking ray is shifted.
- Sprite picking with viewport offset doesn't work both on master and on
this branch.
These are the only scenarios I tested. I think other picking functions
that use this function should be tested but I couldn't track more uses
of it.
Co-authored-by: Krzysztof Zywiecki <krzysiu@pop-os.Dlink>
# Objective
Fixes#18857.
## Solution
Add the requested method, and a `try_` variant as well.
## Testing
It compiles, doctests succeed, and is trivial enough that I don't think
it needs a unit test (correct me if I'm wrong though).
# Objective
Fix problems with `FontAtlasSet`:
* `FontAtlasSet` derives `Asset` but `FontAtlasSet`s are not Bevy
assets.
* The doc comments state that `FontAtlasSet`s are assets that are
created automatically when fonts are loaded. They aren't, they are
created as needed during text updates.
## Solution
* Removed the `Asset` derive.
* Rewrote the doc comments.
# Objective
Was copying off `bevy_ui`'s homework writing a picking backend and
noticed the `Has<IsDefaultPickingCamera>` is not used anywhere.
## Testing
Ran a random example.
This shouldn't cause any behavioral changes at all because the
component/archetype access/filter flags should be the same. `Has<X>`
doesn't affect access since it doesn't actually read or write anything,
and it doesn't affect matched archetypes either. Can't think of another
reason any behavior would change.
# Objective
A small typo was found on `bevy_ecs/examples/event.rs`.
I know it's very minor but I'd think fixing it would still help others
in the long run.
## Solution
Fix the typo.
## Testing
I don't think this is necessary.
# Objective
Fixes#18843
## Solution
We need to account for the material being added and removed in the
course of the same frame. We evict the caches first because the entity
will be re-added if it was marked as needing specialization, which
avoids another check on removed components to see if it was "really"
despawned.
# Objective
One to one relationships (added in
https://github.com/bevyengine/bevy/pull/18087) can currently easily be
invalidated by having two entities relate to the same target.
Alternative to #18817 (removing one-to-one relationships)
## Solution
Panic if a RelationshipTarget is already targeted. Thanks @urben1680 for
the idea!
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
There's still a race resulting in blank materials whenever a material of
type A is added on the same frame that a material of type B is removed.
PR #18734 improved the situation, but ultimately didn't fix the race
because of two issues:
1. The `late_sweep_material_instances` system was never scheduled. This
PR fixes the problem by scheduling that system.
2. `early_sweep_material_instances` needs to be called after *every*
material type has been extracted, not just when the material of *that*
type has been extracted. The `chain()` added during the review process
in PR #18734 broke this logic. This PR reverts that and fixes the
ordering by introducing a new `SystemSet` that contains all material
extraction systems.
I also took the opportunity to switch a manual reference to
`AssetId::<StandardMaterial>::invalid()` to the new
`DUMMY_MESH_MATERIAL` constant for clarity.
Because this is a bug that can affect any application that switches
material types in a single frame, I think this should be uplifted to
Bevy 0.16.
This reverts commit ac52cca033.
Fixes#18815
# Objective
#18782 resulted in using `log` macros instead of `tracing` macros (in
the interest of providing no_std support, specifically no_atomic
support). That tradeoff isn't worth it, especially given that tracing is
likely to get no_atomic support.
## Solution
Revert #18782
Fixes#18834.
`EntityWorldMut::remove_children` and `EntityCommands::remove_children`
were removed in the relationships overhaul (#17398) and never got
replaced.
I don't *think* this was intentional (the methods were never mentioned
in the PR or its comments), but I could've missed something.
# Objective
I was wrong about how RPITIT works when I wrote this stuff initially,
and in order to actually give people access to all the traits
implemented by the output (e.g. Debug and so on) it's important to
expose the real output type, even if it makes the trait uglier and less
comprehensible. (☹️)
## Solution
Expose the curve output type of the `CurveWithDerivative` trait and its
double-derivative companion. I also added a bunch of trait derives to
`WithDerivative<T>`, since I think that was just an oversight.
Fixes a small mix-up from #18058, which added bulk relationship
replacement methods.
`EntityCommands::replace_related_with_difference` calls
`EntityWorldMut::replace_children_with_difference` instead of
`EntityWorldMut::replace_related_with_difference`, which means it always
operates on the `ChildOf` relationship instead of the `R: Relationship`
generic it's provided.
`EntityCommands::replace_children_with_difference` takes an `R:
Relationship` generic that it shouldn't, but it accidentally works
correctly on `main` because it calls the above method.
# Objective
After #17967, closures which always panic no longer satisfy various Bevy
traits. Principally, this affects observers, systems and commands.
While this may seem pointless (systems which always panic are kind of
useless), it is distinctly annoying when using the `todo!` macro, or
when writing tests that should panic.
Fixes#18778.
## Solution
- Add failing tests to demonstrate the problem
- Add the trick from
[`never_say_never`](https://docs.rs/never-say-never/latest/never_say_never/)
to name the `!` type on stable Rust
- Write looots of docs explaining what the heck is going on and why
we've done this terrible thing
## To do
Unfortunately I couldn't figure out how to avoid conflicting impls, and
I am out of time for today, the week and uh the week after that.
Vacation! If you feel like finishing this for me, please submit PRs to
my branch and I can review and press the button for it while I'm off.
Unless you're Cart, in which case you have write permissions to my
branch!
- [ ] fix for commands
- [ ] fix for systems
- [ ] fix for observers
- [ ] revert https://github.com/bevyengine/bevy-website/pull/2092/
## Testing
I've added a compile test for these failure cases and a few adjacent
non-failing cases (with explicit return types).
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
The parameter `In` of `call_inner` is completely unconstrained by its
arguments and return type. We are only able to infer it by assuming that
the only associated type equal to `In::Param<'_>` is `In::Param<'_>`
itself. It could just as well be some other associated type which only
normalizes to `In::Param<'_>`. This will change with the next-generation
trait solver and was encountered by a crater run
https://github.com/rust-lang/rust/pull/133502-
cc
https://github.com/rust-lang/trait-system-refactor-initiative/issues/168
I couldn't think of a cleaner alternative here. I first tried to just
provide `In` as an explicit type parameter. This is also kinda ugly as I
need to provide a variable number of them and `${ignore(..)}` is
currently still unstable https://github.com/rust-lang/rust/issues/83527.
Sorry for the inconvenience. Also fun that this function exists to avoid
a separate solver bug in the first place 😅
Fixes#18809Fixes#18823
Meshes despawned in `Last` can still be in visisible entities if they
were visible as of `PostUpdate`. Sanity check that the mesh actually
exists before we specialize. We still want to unconditionally assume
that the entity is in `EntitySpecializationTicks` as its absence from
that cache would likely suggest another bug.
# Objective
Fixes#18808
## Solution
When an asset emits a removed event, mark it as modified in the render
world to ensure any appropriate bookkeeping runs as necessary.
# Objective
The goal of `bevy_platform_support` is to provide a set of platform
agnostic APIs, alongside platform-specific functionality. This is a high
traffic crate (providing things like HashMap and Instant). Especially in
light of https://github.com/bevyengine/bevy/discussions/18799, it
deserves a friendlier / shorter name.
Given that it hasn't had a full release yet, getting this change in
before Bevy 0.16 makes sense.
## Solution
- Rename `bevy_platform_support` to `bevy_platform`.
# Objective
- `bevy_dylib` currently doesn't build independently
```
cargo build -p bevy_dylib
Compiling bevy_dylib v0.16.0-rc.4 (/crates/bevy_dylib)
error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
error: `#[panic_handler]` function required, but not found
error: unwinding panics are not supported without std
|
= help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
= note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
error: could not compile `bevy_dylib` (lib) due to 3 previous errors
```
## Solution
- remove `#![no_std]` from `bevy_dylib`
## Testing
- it builds now
# Objective
- Fixes#18781
## Solution
- Moved `LogPlugin` into its own file gated behind a new `tracing`
feature.
- Used `log` instead of `tracing` where possible.
- Exposed a new `tracing` feature in `bevy` which enables
`bevy_log/tracing`.
- Gated `LogPlugin` from `DefaultPlugins` on `tracing` feature.
## Testing
- CI
---
## Migration Guide
- If you were previously using `bevy_log` with default features
disabled, enable the new `std` and `tracing` features.
- If you were using `bevy` with the default features disabled, enable
the new `tracing` feature.
## Notes
Almost all of the diffs in this PR come from moving `LogPlugin` into its
own file. This just makes the PR less noisy, since the alternative is
excessive `#[cfg(feature = "tracing")]` directives all over the plugin.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Fixes#17591
Looking at the arm downloads page, "r48p0" is a version number that
increments, where rXX is the major version and pX seems to be a patch
version. Take the conservative approach here that we know gpu
preprocessing is working on at least version 48 and presumably higher.
The assumption here is that the driver_info string will be reported
similarly on non-pixel devices.
# Objective
- Piped systems are an edge case that we missed when reworking system
parameter validation.
- Fixes#18755.
## Solution
- Validate the parameters for both systems, ~~combining the errors if
both failed validation~~ by simply using an early out.
- ~~Also fix the same bug for combinator systems while we're here.~~
## Testing
I've added a large number of tests checking the behavior under various
permutations. These are separate tests, rather than one mega test
because a) it's easier to track down bugs that way and b) many of these
are `should_panic` tests, which will halt the evaluation of the rest of
the test!
I've also added a test for exclusive systems being pipeable because we
don't have one and I was very surprised that that works!
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
- The referenced `ScheduleLabel` for `OnPrimaryClosed` and `OnAllClosed`
in `ExitCondition` was incorrect
## Solution
- Changed `Update` to `PostUpdate`
A clippy failure slipped into #18768, although I'm not sure why CI
didn't catch it.
```sh
> cargo clippy --version
clippy 0.1.85 (4eb161250e 2025-03-15)
> cargo run -p ci
...
error: empty line after doc comment
--> crates\bevy_pbr\src\light\mod.rs:105:5
|
105 | / /// The width and height of each of the 6 faces of the cubemap.
106 | |
| |_^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
= note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
= help: if the empty line is unintentional remove it
help: if the documentation should include the empty line include it in the comment
|
106 | ///
|
```
# Objective
- Improve the docs for `PointLightShadowMap` and
`DirectionalLightShadowMap`
## Solution
- Add example for how to use `PointLightShadowMap` and move the
`DirectionalLightShadowMap` example from `DirectionalLight`.
- Match `PointLight` and `DirectionalLight` docs about shadows.
- Describe what `size` means.
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
Fixes#16896Fixes#17737
## Solution
Adds a new render phase, including all the new cold specialization
patterns, for wireframes. There's a *lot* of regrettable duplication
here between 3d/2d.
## Testing
All the examples.
## Migration Guide
- `WireframePlugin` must now be created with
`WireframePlugin::default()`.
Currently, `RenderMaterialInstances` and `RenderMeshMaterialIds` are
very similar render-world resources: the former maps main world meshes
to typed material asset IDs, and the latter maps main world meshes to
untyped material asset IDs. This is needlessly-complex and wasteful, so
this patch unifies the two in favor of a single untyped
`RenderMaterialInstances` resource.
This patch also fixes a subtle issue that could cause mesh materials to
be incorrect if a `MeshMaterial3d<A>` was removed and replaced with a
`MeshMaterial3d<B>` material in the same frame. The problematic pattern
looks like:
1. `extract_mesh_materials<B>` runs and, seeing the
`Changed<MeshMaterial3d<B>>` condition, adds an entry mapping the mesh
to the new material to the untyped `RenderMeshMaterialIds`.
2. `extract_mesh_materials<A>` runs and, seeing that the entity is
present in `RemovedComponents<MeshMaterial3d<A>>`, removes the entry
from `RenderMeshMaterialIds`.
3. The material slot is now empty, and the mesh will show up as whatever
material happens to be in slot 0 in the material data slab.
This commit fixes the issue by splitting out `extract_mesh_materials`
into *three* phases: *extraction*, *early sweeping*, and *late
sweeping*, which run in that order:
1. The *extraction* system, which runs for each material, updates
`RenderMaterialInstances` records whenever `MeshMaterial3d` components
change, and updates a change tick so that the following system will know
not to remove it.
2. The *early sweeping* system, which runs for each material, processes
entities present in `RemovedComponents<MeshMaterial3d>` and removes each
such entity's record from `RenderMeshInstances` only if the extraction
system didn't update it this frame. This system runs after *all*
extraction systems have completed, fixing the race condition.
3. The *late sweeping* system, which runs only once regardless of the
number of materials in the scene, processes entities present in
`RemovedComponents<ViewVisibility>` and, as in the early sweeping phase,
removes each such entity's record from `RenderMeshInstances` only if the
extraction system didn't update it this frame. At the end, the late
sweeping system updates the change tick.
Because this pattern happens relatively frequently, I think this PR
should land for 0.16.
Due to the preprocessor usage in the shader, different combinations of
features could cause the fields of `StandardMaterialBindings` to shift
around. In certain cases, this could cause them to not line up with the
bindings specified in `StandardMaterial`. This resulted in #18104.
This commit fixes the issue by making `StandardMaterialBindings` have a
fixed size. On the CPU side, it uses the
`#[bindless(index_table(range(M..N)))]` feature I added to `AsBindGroup`
in #18025 to do so. Thus this patch has a dependency on #18025.
Closes#18104.
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
This fixes a panic that occurs if one calls
`PipelineCache::get_render_pipeline_state(id)` or
`PipelineCache::get_compute_pipeline_state(id)` with a queued pipeline
id that has not yet been processed by `PipelineCache::process_queue()`.
```
thread 'Compute Task Pool (0)' panicked at [...]/bevy/crates/bevy_render/src/render_resource/pipeline_cache.rs:611:24:
index out of bounds: the len is 0 but the index is 20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
# Objective
Fixes#18550.
Because bin state for unbatchable meshes wasn't being cleared each
frame, the buffer indices for unbatchable meshes would demote from
sparse to dense storage and aggressively leak memory, with all kinds of
weird consequences downstream, namely supplying invalid instance ranges
for render.
## Solution
Clear out the unbatchable mesh bin state when we start a new frame.
PR #17898 disabled bindless support for `ExtendedMaterial`. This commit
adds it back. It also adds a new example, `extended_material_bindless`,
showing how to use it.
# Objective
Fixes#18678
## Solution
Moved the current `with_related` method to `with_relationships` and
added a new `with_related` that uses a bundle.
I'm not entirely sold on the name just yet, if anyone has any ideas let
me know.
## Testing
I wasn't able to test these changes because it crashed my computer every
time I tried (fun). But there don't seem to be any tests that use the
old `with_related` method so it should be fine, hopefully
## Showcase
```rust
commands.spawn_empty()
.with_related::<Relationship>(Name::new("Related thingy"))
.with_relationships(|rel| {
rel.spawn(Name::new("Second related thingy"));
});
```
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Allow viewing and setting the added tick for change detection aware
data, to allow operations like checking if the value has been modified
since first being added, and spoofing that state (i.e. returning the
value to default in place without a remove/insert dance)
## Solution
- Added corresponding functions matching the existing `changed` API:
- `fn added(&self) -> Tick`
- `fn set_added(&mut self)`
- `fn set_last_added(&mut self, last_added: Tick)`
Discussed on discord @
https://canary.discord.com/channels/691052431525675048/749335865876021248/1358718892465193060
## Testing
- Running the bevy test suite by.. making a PR, heck.
- No new tests were introduced due to triviality (i.e. I don't know what
to test about this API, and the corresponding API for `changed` is
similarly lacking tests.)
---------
Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
Fixes#18685
## Solution
* Don't apply the camera translation.
* Calculate the min and max bounds of the accessibility node rect taking
the UI translation relative to its center not the top-left corner.
## Testing
Install [NVDA](https://www.nvaccess.org/). In NVDA set `Preferences ->
Settings -> Vision -> Enable Highlighting`.
Then run bevy's `tab_navigation` example:
```
cargo run --example tab_navigation
```
If everything is working correctly, NVDA should draw a border around the
currently selected tab button:

# Objective
Clarify information in the docs about the bundle removal commands.
## Solution
Added information about how the intersection of components are removed.
# Objective
Add web support to atmosphere by gating dual source blending and using a
macro to determine the target platform.
The main objective of this PR is to ensure that users of Bevy's
atmosphere feature can also run it in a web-based context where WebGPU
support is enabled.
## Solution
- Make use of the `#[cfg(not(target_arch = "wasm32"))]` macro to gate
the dual source blending, as this is not (yet) supported in web
browsers.
- Rename the function `sample_sun_illuminance` to `sample_sun_radiance`
and move calls out of conditionals to ensure the shader compiles and
runs in both native and web-based contexts.
- Moved the multiplication of the transmittance out when calculating the
sun color, because calling the `sample_sun_illuminance` function was
causing issues in web. Overall this results in cleaner code and more
readable.
## Testing
- Tested by building a wasm target and loading it in a web page with
Vite dev server using `mate-h/bevy-webgpu` repo template.
- Tested the native build with `cargo run --example atmosphere` to
ensure it still works with dual source blending.
---
## Showcase
Screenshots show the atmosphere example running in two different
contexts:
<img width="1281" alt="atmosphere-web-showcase"
src="https://github.com/user-attachments/assets/40b1ee91-89ae-41a6-8189-89630d1ca1a6"
/>
---------
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
## Objective
The `MotionBlur` component exposes renderer internals. Users shouldn't
have to deal with this.
```rust
MotionBlur {
shutter_angle: 1.0,
samples: 2,
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding: Default::default(),
},
```
## Solution
The renderer now uses a separate `MotionBlurUniform` struct for its
internals. `MotionBlur` no longer needs padding.
I was a bit unsure about the name `MotionBlurUniform`. Other modules use
a mix of `Uniform` and `Uniforms`.
## Testing
```
cargo run --example motion_blur
```
Tested on Win10/Nvidia across Vulkan, WebGL/Chrome, WebGPU/Chrome.
# Objective
- Fixes#18690
- Closes [#2065](https://github.com/bevyengine/bevy-website/pull/2065)
- Alternative to #18691
The changes to the Hash made in #15801 to the
[BuildHasher](https://doc.rust-lang.org/std/hash/trait.BuildHasher.html)
resulted in serious migration problems and downgraded UX for users of
Bevy's re-exported hashmaps. Once merged, we need to go in and remove
the migration guide added as part of #15801.
## Solution
- Newtype `HashMap` and `HashSet` instead of type aliases
- Added `Deref/Mut` to allow accessing future `hashbrown` methods
without maintenance from Bevy
- Added bidirectional `From` implementations to provide escape hatch for
API incompatibility
- Added inlinable re-exports of all methods directly to Bevy's types.
This ensures `HashMap::new()` works (since the `Deref` implementation
wont cover these kinds of invocations).
## Testing
- CI
---
## Migration Guide
- If you relied on Bevy's `HashMap` and/or `HashSet` types to be
identical to `hashbrown`, consider using `From` and `Into` to convert
between the `hashbrown` and Bevy types as required.
- If you relied on `hashbrown/serde` or `hashbrown/rayon` features, you
may need to enable `bevy_platform_support/serialize` and/or
`bevy_platform_support/rayon` respectively.
---
## Notes
- Did not replicate the Rayon traits, users will need to rely on the
`Deref/Mut` or `From` implementations for those methods.
- Did not re-expose the `unsafe` methods from `hashbrown`. In most cases
users will still have access via `Deref/Mut` anyway.
- I have added `inline` to all methods as they are trivial wrappings of
existing methods.
- I chose to make `HashMap::new` and `HashSet::new` const, which is
different to `hashbrown`. We can do this because we default to a
fixed-state build-hasher. Mild ergonomic win over using
`HashMap::with_hasher(FixedHasher)`.
## Objective
Fix #18714.
## Solution
Make sure `SkinUniforms::prev_buffer` is resized at the same time as
`current_buffer`.
There will be a one frame visual glitch when the buffers are resized,
since `prev_buffer` is incorrectly initialised with the current joint
transforms.
Note that #18074 includes the same fix. I'm assuming this smaller PR
will land first.
## Testing
See repro instructions in #18714. Tested on `animated_mesh`,
`many_foxes`, `custom_skinned_mesh`, Win10/Nvidia with Vulkan,
WebGL/Chrome, WebGPU/Chrome.
# Objective
In `bevy_enhanced_input`, I'm trying to associate `Actions` with a
schedule. I can do this via an associated type on a trait, but there's
no way to construct the associated label except by requiring a `Default`
implementation. However, Bevy labels don't implement `Default`.
## Solution
Add `Default` to all built-in labels. I think it should be useful in
general.
# Objective
This PR exposes the wgpu types necessary to use the result of
`RenderAdapter::get_texture_format_features`:
```rust
use bevy::render::render_resource::TextureFormatFeatureFlags;
// ^ now available
let adapter = world.resource::<RenderAdapter>();
let flags = adapter.get_texture_format_features(TextureFormat::R32Float).flags;
let filtering = flags.contains(TextureFormatFeatureFlags::FILTERABLE);
```
## Solution
- Expose `TextureFormatFeatureFlags`, `TextureFormatFeatures` like other
wgpu types in bevy_render
## Objective
Fix motion blur not working on skinned meshes.
## Solution
`set_mesh_motion_vector_flags` can set
`RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN` after specialization has
already cached the material. This can lead to
`MeshPipelineKey::HAS_PREVIOUS_SKIN` never getting set, disabling motion
blur.
The fix is to make sure `set_mesh_motion_vector_flags` happens before
specialization.
Note that the bug is fixed in a different way by #18074, which includes
other fixes but is a much larger change.
## Testing
Open the `animated_mesh` example and add these components to the
`Camera3d` entity:
```rust
MotionBlur {
shutter_angle: 5.0,
samples: 2,
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding: Default::default(),
},
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
Msaa::Off,
```
Tested on `animated_mesh`, `many_foxes`, `custom_skinned_mesh`,
Win10/Nvidia with Vulkan, WebGL/Chrome, WebGPU/Chrome. Note that testing
`many_foxes` WebGL requires #18715.
# Objective
Fixes#18701
## Solution
Add reflection of `PartialEq` and `Hash` to `AnimationNodeIndex`
## Testing
Added a new `#[test]` with the minimal reproduction posted on #18701.
# Objective
- The `#[deprecated]` attributes supports a `since` field, which
documents in which version an item was deprecated. This field is visible
in `rustdoc`.
- We inconsistently use `since` throughout the project.
For an example of what `since` renders as, take a look at
`ChildOf::get()`:
```rust
/// The parent entity of this child entity.
#[deprecated(since = "0.16.0", note = "Use child_of.parent() instead")]
#[inline]
pub fn get(&self) -> Entity {
self.0
}
```

## Solution
- Add `since = "0.16.0"` to all `#[deprecated]` attributes that do not
already use it.
- Add an example of deprecating a struct with the `since` field in the
migration guide document.
I would appreciate if this could be included in 0.16's release, as its a
low-risk documentation improvement that is valuable for the release, but
I'd understand if this was cut.
## Testing
You can use `cargo doc` to inspect the rendered form of
`#[deprecated(since = "0.16.0", ...)]`.
# Objective
Newest installment of the #16547 series.
In #18319 we introduced `Entity` defaults to accomodate the most common
use case for these types, however that resulted in the switch of the `T`
and `N` generics of `UniqueEntityArray`.
Swapping generics might be somewhat acceptable for `UniqueEntityArray`,
it is not at all acceptable for map and set types, which we would make
generic over `T: EntityEquivalent` in #18408.
Leaving these defaults in place would result in a glaring inconsistency
between these set collections and the others.
Additionally, the current standard in the engine is for "entity" to mean
`Entity`. APIs could be changed to accept `EntityEquivalent`, however
that is a separate and contentious discussion.
## Solution
Name these set collections `UniqueEntityEquivalent*`, and retain the
`UniqueEntity*` name for an alias of the `Entity` case.
While more verbose, this allows for all generics to be in proper order,
full consistency between all set types*, and the "entity" name to be
restricted to `Entity`.
On top of that, `UniqueEntity*` now always have 1 generic less, when
previously this was not enforced for the default case.
*`UniqueEntityIter<I: Iterator<T: EntityEquivalent>>` is the sole
exception to this. Aliases are unable to enforce bounds
(`lazy_type_alias` is needed for this), so for this type, doing this
split would be a mere suggestion, and in no way enforced.
Iterator types are rarely ever named, and this specific one is intended
to be aliased when it sees more use, like we do for the corresponding
set collection iterators.
Furthermore, the `EntityEquivalent` precursor `Borrow<Entity>` was used
exactly because of such iterator bounds!
Because of that, we leave it as is.
While no migration guide for 0.15 users, for those that upgrade from
main:
`UniqueEntityVec<T>` -> `UniqueEntityEquivalentVec<T>`
`UniqueEntitySlice<T>` -> `UniqueEntityEquivalentSlice<T>`
`UniqueEntityArray<N, T>` -> `UniqueEntityEquivalentArray<T, N>`
#18555 improved syntax for required components.
However some code was a bit redundant after the new parsing and struct
initializing would not give proper errors.
This PR fixes that.
---------
Co-authored-by: Tim Overbeek <oorbecktim@Tims-MacBook-Pro.local>
# Objective
Improve the parameter validation error message for
`Event(Reader|Writer|Mutator)`.
System parameters defined using `#[derive(SystemParam)]`, including the
parameters for events, currently propagate the validation errors from
their subparameters. The error includes the type of the failing
parameter, so the resulting error includes the type of the failing
subparameter instead of the derived parameter.
In particular, `EventReader<T>` will report an error from a
`Res<Events<T>>`, even though the user has no parameter of that type!
This is a follow-up to #18593.
## Solution
Have `#[derive]`d system parameters map errors during propagation so
that they report the outer parameter type.
To continue to provide context, add a field to
`SystemParamValidationError` that identifies the subparameter by name,
and is empty for non-`#[derive]`d parameters.
Allow them to override the failure message for individual parameters.
Use this to convert "Resource does not exist" to "Event not initialized"
for `Event(Reader|Writer|Mutator)`.
## Showcase
The validation error for a `EventReader<SomeEvent>` parameter when
`add_event` has not been called changes from:
Before:
```
Parameter `Res<Events<SomeEvent>>` failed validation: Resource does not exist
```
After
```
Parameter `EventReader<SomeEvent>::events` failed validation: Event not initialized
```
Extension of #18409.
I was updating a migration guide for hierarchy commands and realized
`insert_children` wasn't added to `EntityCommands`, only
`EntityWorldMut`.
This adds that and `insert_related` (basically just some
copy-and-pasting).
# Objective
In #17905 we swapped to a named field on `ChildOf` to help resolve
variable naming ambiguity of child vs parent (ex: `child_of.parent`
clearly reads as "I am accessing the parent of the child_of
relationship", whereas `child_of.0` is less clear).
Unfortunately this has the side effect of making initialization less
ideal. `ChildOf { parent }` reads just as well as `ChildOf(parent)`, but
`ChildOf { parent: root }` doesn't read nearly as well as
`ChildOf(root)`.
## Solution
Move back to `ChildOf(pub Entity)` but add a `child_of.parent()`
function and use it for all accesses. The downside here is that users
are no longer "forced" to access the parent field with `parent`
nomenclature, but I think this strikes the right balance.
Take a look at the diff. I think the results provide strong evidence for
this change. Initialization has the benefit of reading much better _and_
of taking up significantly less space, as many lines go from 3 to 1, and
we're cutting out a bunch of syntax in some cases.
Sadly I do think this should land in 0.16 as the cost of doing this
_after_ the relationships migration is high.
# Objective
The `visited: Local<HashSet<Entity>>` system param is meant to track
which entities `update_contexts_recursively` has visited and updated but
when the reparent_nodes_query isn't ordered descending from parent to
child nodes can get marked as visited even though their camera target is
unset and if the camera target is unset then the node won't be rendered.
Fixes#18616
## Solution
Remove the `visited` system param from `update_ui_context_system` and
the associated visited check from `update_contexts_recursively`. It was
redundant anyway since the set_if_neq check is sufficient to track
already updated nodes.
## Testing
The example from #18616 can be used for testing.
# Objective
Provide more useful errors when `World::run_system` and related methods
fail parameter validation.
Let callers determine whether the validation failure would have skipped
or failed the system.
Follow-up to #18541.
## Solution
Add a `SystemParamValidationError` value to the
`RunSystemError::InvalidParams` and
`RegisteredSystemError::InvalidParams` variants. That includes the
complete context of the parameter validation error, including the
`skipped` flag.
fixes#17478
# Objective
- Complete #17558.
- the `insert_children` method was previously removed, and as #17478
points out, needs to be added back.
## Solution
- Add a `OrderedRelationshipSourceCollection`, which allows sorting,
ordering, rearranging, etc of a `RelationshipSourceCollection`.
- Implement `insert_related`
- Implement `insert_children`
- Tidy up some docs while I'm here.
## Testing
@bjoernp116 set up a unit test, and I added a doc test to
`OrderedRelationshipSourceCollection`.
---------
Co-authored-by: bjoernp116 <bjoernpollen@gmail.com>
Co-authored-by: Dmytro Banin <banind@cs.washington.edu>
Co-authored-by: Talin <viridia@gmail.com>
# Objective
#18173 allows components to be queued without being fully registered.
But much of bevy's debug logging contained
`components.get_name(id).unwrap()`. However, this panics when the id is
queued. This PR fixes this, allowing names to be retrieved for debugging
purposes, etc, even while they're still queued.
## Solution
We change `ComponentInfo::descriptor` to be `Arc<ComponentDescriptor>`
instead of not arc'd. This lets us pass the descriptor around (as a name
or otherwise) as needed. The alternative would require some form of
`MappedRwLockReadGuard`, which is unstable, and would be terribly
blocking. Putting it in an arc also signifies that it doesn't change,
which is a nice signal to users. This does mean there's an extra pointer
dereference, but I don't think that's an issue here, as almost all paths
that use this are for debugging purposes or one-time set ups.
## Testing
Existing tests.
## Migration Guide
`Components::get_name` now returns `Option<Cow<'_, str>` instead of
`Option<&str>`. This is because it now returns results for queued
components. If that behavior is not desired, or you know the component
is not queued, you can use
`components.get_info().map(ComponentInfo::name)` instead.
Similarly, `ScheduleGraph::conflicts_to_string` now returns `impl
Iterator<Item = (String, String, Vec<Cow<str>>)>` instead of `impl
Iterator<Item = (String, String, Vec<&str>)>`. Because `Cow<str>` derefs
to `&str`, most use cases can remain unchanged.
---------
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
- Fixes#18617
## Solution
- Added `thread::sleep` to `bevy_platform_support` using a spin-based
fallback.
- Fixed bug in `bevy_platform_support::time::Instant::elapsed`
(comparison was backwards)
- Switched `ScheduleRunnerPlugin` to use
`bevy_platform_support:🧵:sleep` on `std` and `no_std` platforms
(WASM + Browser excluded)
## Testing
- Ran reproduction code from @mockersf in linked issue and confirmed a
consistent 60 counts per `println!`.
---
## Notes
- I chose to add `bevy_platform_support:🧵:sleep` instead of
putting the fix in-line within `ScheduleRunnerPlugin` to keep the
separation of concerns clean. `sleep` is only used in one other location
in Bevy, `bevy_asset`, but I have decided to leave that as-is since
`bevy_asset` isn't `no_std` compatible anyway.
- The bug in `bevy_platform_support::time::Instant::elapsed` wasn't the
cause of this issue, but it did prevent this fix from working so I have
included the it in this PR.
- Lots of nits, formatting, and rephrasing, with the goal of making
things more consistent.
- Fix outdated error handler explanation in `Commands` and
`EntityCommands` docs.
- Expand docs for system-related commands.
- Remove panic notes if the command only panics with the default error
handler.
- Update error handling notes for `try_` variants.
- Hide `prelude` import in most doctest examples, unless the example
uses something that people might not realize is in the prelude (like
`Name`).
- Remove a couple doctest examples that (in my opinion) didn't make
sense.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
# Objective
The `NoIndirectDrawing` wasn't working and was causing the scene not to
be rendered.
## Solution
Check the configured preprocessing mode when adding new batch sets and
mark them as batchable instead of muli-drawable if indirect rendering
has been disabled.
## Testing
`cargo run --example many_cubes -- --no-indirect-drawing`
# Objective
- Fixes#18397
- Supersedes #18474
- Simplifies 0.16 migration
## Solution
- Upgrade to Glam 0.29.3, which has backported the `nostd-libm` feature.
- Expose a similar feature in `bevy_math` and enable it in
`bevy_internal`, allowing `bevy_math`, `bevy_input`, and
`bevy_transform` to be unconditional dependencies again.
## Testing
- CI
---
## Notes
- This includes `libm` as a dependency, but this was already the case in
the common scenario where `rand` or many other features were enabled.
Considering `libm` is an official Rust crate, it's a very low-risk
dependency to unconditionally include.
- For users who do not want `libm` included, simply import Bevy's
subcrates directly, since `bevy_math/nostd-libm` will not be enabled.
- I know we are _very_ late in the RC cycle for 0.16, but this has a
substantial impact on the usability of `bevy` that I consider worth
including.