Commit Graph

6824 Commits

Author SHA1 Message Date
aloucks
8dc1a7cd81 Fix UpdateMode::Reactive behavior on Windows (#18493)
# Objective

The fix in #17488 forced Windows to always behave as if it were in
`UpdateMode::Continuous`.

CC https://github.com/bevyengine/bevy/pull/17991

## Solution

Removed the unconditional `redraw_requested = true` and added a check
for `Reactive` in `about_to_wait`.

## Testing

- Verified that the `low_power` example worked as expected with all
`UpdateMode` options.
- Verified that animation continued in both `eased_motion ` and
`low_power` examples when in `Continuous` update mode while:
  - Resizing the Window
  - Moving the window via clicking and dragging the title bar
- Verified that `window_settings` example still worked as expected.
- Verified that `monitor_info` example still worked as expected.
2025-03-25 23:01:22 +01:00
Eagster
b1c1aac1b3 Ensure spawning related entities in an OnAdd observer downstream of a World::spawn in a Command does not cause a crash (#18545)
# Objective

fixes #18452.

## Solution

Spawning used to flush commands only, but those commands can reserve
entities. Now, spawning flushes everything, including reserved entities.
I checked, and this was the only place where `flush_commands` is used
instead of `flush` by mistake.

## Testing

I simplified the MRE from #18452 into its own test, which fails on main,
but passes on this branch.
2025-03-25 22:59:05 +01:00
Sorseg
30a022feae Make RayMap map public (#18544)
Migration guide:
# Objective

Currently there seems to be no way to enable picking through
render-to-texture cameras

## Solution

This PR allows casting rays from the game code quite easily.

## Testing

- I've tested these in my game and it seems to work
- I haven't tested edge cases

--- 

## Showcase

<details>
  <summary>Click to view showcase</summary>

```rust

fn cast_rays_from_additional_camera(
    cameras: Query<(&GlobalTransform, &Camera, Entity), With<RenderToTextureCamera>>,
    mut rays: ResMut<RayMap>,
    pointers: Query<(&PointerId, &PointerLocation)>,
) {
    for (camera_global_transform, camera, camera_entity) in &cameras {
        for (pointer_id, pointer_loc) in &pointers {
            let Some(viewport_pos) = pointer_loc.location() else {
                continue;
            };
            // if camera result is transformed in any way, the reverse transformation
            // should be applied somewhere here
            let ray = camera
                .viewport_to_world(camera_global_transform, viewport_pos.position)
                .ok();
            if let Some(r) = ray {
                rays.map.insert(RayId::new(camera_entity, *pointer_id), r);
            }
        }
    }
}

```

</details>

## Migration Guide
The `bevy_picking::backend::ray::RayMap::map` method is removed as
redundant,
In systems using `Res<RayMap>` replace `ray_map.map()` with
`&ray_map.map`
2025-03-25 22:59:05 +01:00
IceSentry
af9fd4e939 Move non-generic parts of the PrepassPipeline to internal field (#18322)
# Objective

- The prepass pipeline has a generic bound on the specialize function
but 95% of it doesn't need it

## Solution

- Move most of the fields to an internal struct and use a separate
specialize function for those fields

## Testing

- Ran the 3d_scene and it worked like before

---

## Migration Guide

If you were using a field of the `PrepassPipeline`, most of them have
now been move to `PrepassPipeline::internal`.

## Notes

Here's the cargo bloat size comparison (from this tool
https://github.com/bevyengine/bevy/discussions/14864):

```
before:
    (
        "<bevy_pbr::prepass::PrepassPipeline<M> as bevy_render::render_resource::pipeline_specializer::SpecializedMeshPipeline>::specialize",
        25416,
        0.05582993,
    ),

after:
    (
        "<bevy_pbr::prepass::PrepassPipeline<M> as bevy_render::render_resource::pipeline_specializer::SpecializedMeshPipeline>::specialize",
        2496,
        0.005490916,
    ),
    (
        "bevy_pbr::prepass::PrepassPipelineInternal::specialize",
        11444,
        0.025175499,
    ),
```

The size for the specialize function that is generic is now much
smaller, so users won't need to recompile it for every material.
2025-03-25 22:59:04 +01:00
IQuick 143
a021ed1ce8 Fix mesh_picking not working due to mixing vertex and triangle indices. (#18533)
# Objective

- #18495 

## Solution

- The code in the PR #18232 accidentally used a vertex index as a
triangle index, causing the wrong triangle to be used for normal
computation and if the triangle went out of bounds, it would skip the
ray-hit.
- Don't do that.

## Testing

- Run `cargo run --example mesh_picking`
2025-03-25 22:59:04 +01:00
François Mockers
38743a8ff1 don't flip sprites twice (#18535)
# Objective

- After #17041, sprite flipping doesn't work

## Solution

- Sprite flipping is applied twice:

b6ccc2a2a0/crates/bevy_sprite/src/render/mod.rs (L766-L773)

b6ccc2a2a0/crates/bevy_sprite/src/render/mod.rs (L792-L799)
- Keep one
2025-03-25 22:59:04 +01:00
Zachary Harrold
398350906c Fix bevy_math/transform/input Improper Inclusion (#18526)
# Objective

Enabling `serialize`, `critical-section`, or `async-executor` would
improperly enable `bevy_math`, `bevy_input`, and/or `bevy_transform`.
This was caused by those crates previously being required but are now
optional (gated behind `std` and/or `libm`).

## Solution

- Added `?` to features not intended to enable those crates

## Testing

- CI
2025-03-25 22:59:04 +01:00
HugoPeters1024
df26bc3387 bugfix(frustra of point lights were not recalculated when a camera changes) (#18519)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/11682

## Solution

- https://github.com/bevyengine/bevy/pull/4086 introduced an
optimization to not do redundant calculations, but did not take into
account changes to the resource `global_lights`. I believe that my patch
includes the optimization benefit but adds the required nuance to fix
said bug.

## Testing

The example originally given by
[@kirillsurkov](https://github.com/kirillsurkov) and then updated by me
to bevy 15.3 here:
https://github.com/bevyengine/bevy/issues/11682#issuecomment-2746287416
will not have shadows without this patch:

```rust
use bevy::prelude::*;

#[derive(Resource)]
struct State {
    x: f32,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, update)
        .insert_resource(State { x: -40.0 })
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn((
        Mesh3d(meshes.add(Circle::new(4.0))),
        MeshMaterial3d(materials.add(Color::WHITE)),
    ));
    commands.spawn((
        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
        MeshMaterial3d(materials.add(Color::linear_rgb(0.0, 1.0, 0.0))),
    ));
    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));
    commands.spawn(Camera3d::default());
}

fn update(mut state: ResMut<State>, mut camera: Query<&mut Transform, With<Camera3d>>) {
    let mut camera = camera.single_mut().unwrap();

    let t = Vec3::new(state.x, 0.0, 10.0);
    camera.translation = t;
    camera.look_at(t - Vec3::Z, Vec3::Y);

    state.x = 0.0;
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2025-03-25 22:59:04 +01:00
Joona Aalto
bdf6f3d5f1 Add no_std compatible ceil method (#18498)
# Objective


[`f32::ceil`](https://doc.rust-lang.org/std/primitive.f32.html#method.ceil)
is not available in `core`. We have `floor` in `bevy_math::ops`, but no
equivalent for `floor`.

## Solution

Add `ops::ceil` for `no_std` compatibility.
2025-03-25 22:59:04 +01:00
Alice Cecile
6caa1782d6 Define system param validation on a per-system parameter basis (#18504)
# Objective

When introduced, `Single` was intended to simply be silently skipped,
allowing for graceful and efficient handling of systems during invalid
game states (such as when the player is dead).

However, this also caused missing resources to *also* be silently
skipped, leading to confusing and very hard to debug failures. In
0.15.1, this behavior was reverted to a panic, making missing resources
easier to debug, but largely making `Single` (and `Populated`)
worthless, as they would panic during expected game states.

Ultimately, the consensus is that this behavior should differ on a
per-system-param basis. However, there was no sensible way to *do* that
before this PR.

## Solution

Swap `SystemParam::validate_param` from a `bool` to:

```rust
/// The outcome of system / system param validation,
/// used by system executors to determine what to do with a system.
pub enum ValidationOutcome {
    /// All system parameters were validated successfully and the system can be run.
    Valid,
    /// At least one system parameter failed validation, and an error must be handled.
    /// By default, this will result in1 a panic. See [crate::error] for more information.
    ///
    /// This is the default behavior, and is suitable for system params that should *always* be valid,
    /// either because sensible fallback behavior exists (like [`Query`] or because
    /// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).
    Invalid,
    /// At least one system parameter failed validation, but the system should be skipped due to [`ValidationBehavior::Skip`].
    /// This is suitable for system params that are intended to only operate in certain application states, such as [`Single`].
    Skipped,
}
```
Then, inside of each `SystemParam` implementation, return either Valid,
Invalid or Skipped.

Currently, only `Single`, `Option<Single>` and `Populated` use the
`Skipped` behavior. Other params (like resources) retain their current
failing

## Testing

Messed around with the fallible_params example. Added a pair of tests:
one for panicking when resources are missing, and another for properly
skipping `Single` and `Populated` system params.

## To do

- [x] get https://github.com/bevyengine/bevy/pull/18454 merged
- [x] fix the todo!() in the macro-powered tuple implementation (please
help 🥺)
- [x] test
- [x] write a migration guide
- [x] update the example comments

## Migration Guide

Various system and system parameter validation methods
(`SystemParam::validate_param`, `System::validate_param` and
`System::validate_param_unsafe`) now return and accept a
`ValidationOutcome` enum, rather than a `bool`. The previous `true`
values map to `ValidationOutcome::Valid`, while `false` maps to
`ValidationOutcome::Invalid`.

However, if you wrote a custom schedule executor, you should now respect
the new `ValidationOutcome::Skipped` parameter, skipping any systems
whose validation was skipped. By contrast, `ValidationOutcome::Invalid`
systems should also be skipped, but you should call the
`default_error_handler` on them first, which by default will result in a
panic.

If you are implementing a custom `SystemParam`, you should consider
whether failing system param validation is an error or an expected
state, and choose between `Invalid` and `Skipped` accordingly. In Bevy
itself, `Single` and `Populated` now once again skip the system when
their conditions are not met. This is the 0.15.0 behavior, but stands in
contrast to the 0.15.1 behavior, where they would panic.

---------

Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Dmytro Banin <banind@cs.washington.edu>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-03-25 22:59:04 +01:00
Alice Cecile
7a748e6f0a Make system param validation rely on the unified ECS error handling via the GLOBAL_ERROR_HANDLER (#18454)
There are two related problems here:

1. Users should be able to change the fallback behavior of *all*
ECS-based errors in their application by setting the
`GLOBAL_ERROR_HANDLER`. See #18351 for earlier work in this vein.
2. The existing solution (#15500) for customizing this behavior is high
on boilerplate, not global and adds a great deal of complexity.

The consensus is that the default behavior when a parameter fails
validation should be set based on the kind of system parameter in
question: `Single` / `Populated` should silently skip the system, but
`Res` should panic. Setting this behavior at the system level is a
bandaid that makes getting to that ideal behavior more painful, and can
mask real failures (if a resource is missing but you've ignored a system
to make the Single stop panicking you're going to have a bad day).

I've removed the existing `ParamWarnPolicy`-based configuration, and
wired up the `GLOBAL_ERROR_HANDLER`/`default_error_handler` to the
various schedule executors to properly plumb through errors .

Additionally, I've done a small cleanup pass on the corresponding
example.

I've run the `fallible_params` example, with both the default and a
custom global error handler. The former panics (as expected), and the
latter spams the error console with warnings 🥲

1. Currently, failed system param validation will result in endless
console spam. Do you want me to implement a solution for warn_once-style
debouncing somehow?
2. Currently, the error reporting for failed system param validation is
very limited: all we get is that a system param failed validation and
the name of the system. Do you want me to implement improved error
reporting by bubbling up errors in this PR?
3. There is broad consensus that the default behavior for failed system
param validation should be set on a per-system param basis. Would you
like me to implement that in this PR?

My gut instinct is that we absolutely want to solve 2 and 3, but it will
be much easier to do that work (and review it) if we split the PRs
apart.

`ParamWarnPolicy` and the `WithParamWarnPolicy` have been removed
completely. Failures during system param validation are now handled via
the `GLOBAL_ERROR_HANDLER`: please see the `bevy_ecs::error` module docs
for more information.

---------

Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
2025-03-25 22:59:01 +01:00
Erick Z
e7fd0d5241 Don't panic on temporary files in file watcher (#18462)
# Objective

Fixes #18461

Apparently `RustRover` creates a temporary file with a tilde like
`load_scene_example.scn.ron~` and at the moment of calling
`.canonicalize()` the file does not exists anymore.

## Solution

Not call `.unwrap()` and return `None` fixes the issue. 

## Testing

- `cargo ci`: OK
- Tested the `scene` example with `file_watcher` feature and it works as
expected.

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-03-25 22:45:41 +01:00
Greeble
7e45e8635c Reduce dependencies on bevy_render by preferring bevy_mesh imports (#18437)
Reduce dependencies on `bevy_render` by preferring `bevy_mesh` imports
over `bevy_render` re-exports.

```diff
- use bevy_render::mesh::Mesh;
+ use bevy_mesh::Mesh;
```

This is intended to help with #18423 (render crate restructure). Affects
`bevy_gltf`, `bevy_animation` and `bevy_picking`.

As part of #18423, I'm assuming there'll be a push to make crates less
dependent on the big render crates. This PR seemed like a small and safe
step along that path - it only changes imports and makes the `bevy_mesh`
crate dependency explicit in `Cargo.toml`. Any remaining dependencies on
`bevy_render` are true dependencies.

```
cargo run --example testbed_3d
cargo run --example mesh_picking
```
2025-03-25 22:45:39 +01:00
Kristoffer Søholm
183dfc1b5f Update bincode to 2.0 (#18396)
# Objective

Update bincode

## Solution

Fix compilation for #18352 by reading the [migration
guide](https://github.com/bincode-org/bincode/blob/trunk/docs/migration_guide.md)

Also fixes an unused import warning I got when running the tests for
bevy_reflect.
2025-03-25 22:44:01 +01:00
Martín Maita
c16a884ccb Update accesskit and accesskit_winit requirements (#18285)
# Objective

- Fixes #18225

## Solution

-  Updated `accesskit` version requirement from 0.17 to 0.18
-  Updated `accesskit_winit` version requirement from 0.23 to 0.25

## Testing

- Ran CI checks locally.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 22:44:01 +01:00
JMS55
0702f3652d Record bloom render commands in parallel (#18330)
Closes https://github.com/bevyengine/bevy/issues/18304.

Requesting that someone more experienced with tracy test performance on
a larger scene please!
2025-03-25 22:44:01 +01:00
Joshua Maleszewski
a88f2fec42 AssetServer out of bounds protection (#18088)
Addresses Issue #18073

---------

Co-authored-by: Threadzless <threadzless@gmail.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2025-03-25 22:44:01 +01:00
ickshonpe
da305da07b ExtractedSprites slice buffer (#17041)
Instead of extracting an individual sprite per glyph of a text spawn or
slice of a nine-patched sprite, add a buffer to store the extracted
slice geometry.

Fixes #16972

* New struct `ExtractedSlice` to hold sprite slice size, position and
atlas info (for text each glyph is a slice).
* New resource `ExtractedSlices` that wraps the `ExtractedSlice` buffer.
This is a separate resource so it can be used without sprites (with a
text material, for example).
* New enum `ExtractedSpriteKind` with variants `Single` and `Slices`.
`Single` represents a single sprite, `Slices` contains a range into the
`ExtractedSlice` buffer.
* Only queue a single `ExtractedSprite` for sets of glyphs or slices and
push the geometry for each individual slice or glyph into the
`ExtractedSlice` buffer.
* Modify `ComputedTextureSlices` to return an `ExtractedSlice` iterator
instead of `ExtractedSprites`.
* Modify `extract_text2d_sprite` to only queue new `ExtractedSprite`s on
font changes and otherwise push slices.

I don't like the name `ExtractedSpriteKind` much, it's a bit redundant
and too haskellish. But although it's exported, it's not something users
will interact with most of the time so don't want to overthink it.

yellow = this pr, red = main

```cargo run --example many_glyphs --release --features "trace_tracy" -- --no-ui```

<img width="454" alt="many-glyphs" src="https://github.com/user-attachments/assets/711b52c9-2d4d-43c7-b154-e81a69c94dce" />

```cargo run --example many_text2d --release --features "trace_tracy"```
<img width="415" alt="many-text2d"
src="https://github.com/user-attachments/assets/5ea2480a-52e0-4cd0-9f12-07405cf6b8fa"
/>

* `ExtractedSprite` has a new `kind: ExtractedSpriteKind` field with
variants `Single` and `Slices`.
- `Single` represents a single sprite. `ExtractedSprite`'s `anchor`,
`rect`, `scaling_mode` and `custom_size` fields have been moved into
`Single`.
- `Slices` contains a range that indexes into a new resource
`ExtractedSlices`. Slices are used to draw elements composed from
multiple sprites such as text or nine-patched borders.
* `ComputedTextureSlices::extract_sprites` has been renamed to
`extract_slices`. Its `transform` and `original_entity` parameters have
been removed.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2025-03-25 22:43:58 +01:00
Zachary Harrold
ca3a5c0c6e Switch from OnceCell to LazyLock in bevy_tasks (#18506)
Remove `critical-section` from required dependencies, allowing linking
without any features.

- Switched from `OnceCell` to `LazyLock`
- Removed `std` feature from `bevy_dylib` (proof that it works)

- CI
2025-03-25 22:41:01 +01:00
Zachary Harrold
ff189cf4ef Address Lints in bevy_reflect (#18479)
# Objective

On Windows there are several unaddressed lints raised by clippy.

## Solution

Addressed them!

## Testing

- CI on Windows & Ubuntu
2025-03-25 22:40:33 +01:00
François Mockers
75ad8bda40 enable x11 by default in bevy_winit (#18475)
- building bevy_winit on linux fails with
```
error: The platform you're compiling for is not supported by winit
  --> /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/winit-0.30.9/src/platform_impl/mod.rs:78:1
   |
78 | compile_error!("The platform you're compiling for is not supported by winit");
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
- this blocks publishing Bevy from linux during the verification step

- Enable `x11` by default when building bevy_winit, and disable default
features of bevy_winit in bevy_internal
- This doesn't change anything when depending on Bevy
2025-03-25 22:40:31 +01:00
darth levi
bffd333465 register ComputedNodeTarget (#18503)
I had no reference to `ComputedNodeTarget` in my project. After updating
to bevy 0.16.0-rc1 i got a compile error complaining about this.
2025-03-25 22:39:04 +01:00
François Mockers
07eaedc620 fix error and lints when building for wasm32 (#18500)
# Objective

- Some crates don't compile or have clippy warnings when building for
wasm32

## Solution

- bevy_asset: unused lifetime
- bevy_gltf: the error is not too large in wasm32
- bevy_remote: fails to compile as feature http is also gated on wasm32
- bevy_winit: unused import `error`
2025-03-24 00:14:22 +01:00
Zachary Harrold
7db0d83c19 Address lints in bevy_asset (#18502)
# Objective

`cargo clippy -p bevy_asset` warns on a pair of lints on my Windows 10
development machine (return from let binding).

## Solution

Addressed them!

## Testing

- CI
2025-03-24 00:14:22 +01:00
Ida "Iyes
0f52a2816d Regression fix: Reintroduce sorting/reordering methods on Children (#18476)
# Objective

Bevy 0.15 used to have methods on `Children` for sorting and reordering
them. This is very important, because in certain situations, the order
of children matters. For example, in the context of UI nodes.

These methods are missing/omitted/forgotten in the current version,
after the Relationships rework.

Without them, it is impossible for me to upgrade `iyes_perf_ui` to Bevy
0.16.

## Solution

Reintroduce the methods. This PR simply copy-pastes them from Bevy 0.15.
2025-03-24 00:14:22 +01:00
Viktor Gustavsson
6b40ae545d Fix clippy::unnecessary-literal-unwrap in bevy_time (#18485)
# Objective

- Compiling `bevy_time` without the `std`-feature results in a
`clippy::unnecessary-literal-unwrap`.

## Solution

- Fix lint error

## Testing

- CI
---
2025-03-24 00:14:22 +01:00
Zachary Harrold
fbb42df826 Remove bevy_input_focus from bevy_a11y (#18483)
- Compiling `bevy_a11y` without default features fails because you need
to select a floating point backed. But you actually don't need it, this
requirement is from an unused linkage to `bevy_input_focus`

- Remove link

- CI

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-03-24 00:14:14 +01:00
Zachary Harrold
55564744b2 Ensure dds enables bevy_core_pipeline/dds in bevy_anti_aliasing (#18484)
- Compile failure with `bevy_anti_aliasing` due to `dds` feature not
enabling `bevy_core_pipeline/dds`, causing a public API desync.

- Ensured feature is enabled

- CI
2025-03-24 00:11:37 +01:00
Zachary Harrold
36dcb9b89d Properly gate imports in bevy_scene (#18482)
# Objective

- Some imports are only used with certain features.

## Solution

- Gate them!

## Testing

- CI
2025-03-24 00:09:30 +01:00
Zachary Harrold
cfcb55d778 Fix clippy::let_and_return in bevy_ecs (#18481)
# Objective

- `clippy::let_and_return` fails in `bevy_ecs`

## Solution

- Fixed it!

## Testing

- CI
2025-03-24 00:09:30 +01:00
Zachary Harrold
04a0a74157 Address lints in bevy_platform_support (#18477)
# Objective

@mockersf noticed there were some failing lints in
`bevy_platform_support`.

## Solution

Addressed the lints!

## Testing

- CI
2025-03-24 00:09:30 +01:00
Zachary Harrold
39b1ffc905 Properly gate functionality on http in bevy_remote (#18478)
# Objective

Noticed that `bevy_remote` fails to compile without default features.

## Solution

Adjusted offending method to avoid reliance on `http` module when it is
disabled.

## Testing

- CI
- `cargo clippy -p bevy_remote --no-default-features`
2025-03-24 00:09:30 +01:00
Brezak
9f74c0c046 Fix clippy warning about unnecessary return in single_threaded_taks_pool.rs (#18472)
# Objective

Every time I run `cargo clippy -p bevy_ecs` it pops up and it's
distracting.

## Solution

Removed unnecessary returns. The blocks themselves are necessary or the
`#[cfg(...)]` doesn't apply properly

## Testing

`cargo clippy -p bevy_ecs` + ci build tests
2025-03-24 00:09:30 +01:00
Carter Anderson
1db1119819 Replace VisitEntities with MapEntities (#18432)
# Objective

There are currently too many disparate ways to handle entity mapping,
especially after #17687. We now have MapEntities, VisitEntities,
VisitEntitiesMut, Component::visit_entities,
Component::visit_entities_mut.

Our only known use case at the moment for these is entity mapping. This
means we have significant consolidation potential.

Additionally, VisitEntitiesMut cannot be implemented for map-style
collections like HashSets, as you cant "just" mutate a `&mut Entity`.
Our current approach to Component mapping requires VisitEntitiesMut,
meaning this category of entity collection isn't mappable. `MapEntities`
is more generally applicable. Additionally, the _existence_ of the
blanket From impl on VisitEntitiesMut blocks us from implementing
MapEntities for HashSets (or any types we don't own), because the owner
could always add a conflicting impl in the future.

## Solution

Use `MapEntities` everywhere and remove all "visit entities" usages.

* Add `Component::map_entities`
* Remove `Component::visit_entities`, `Component::visit_entities_mut`,
`VisitEntities`, and `VisitEntitiesMut`
* Support deriving `Component::map_entities` in `#[derive(Coomponent)]`
* Add `#[derive(MapEntities)]`, and share logic with the
`Component::map_entities` derive.
* Add `ComponentCloneCtx::queue_deferred`, which is command-like logic
that runs immediately after normal clones. Reframe `FromWorld` fallback
logic in the "reflect clone" impl to use it. This cuts out a lot of
unnecessary work and I think justifies the existence of a pseudo-command
interface (given how niche, yet performance sensitive this is).

Note that we no longer auto-impl entity mapping for ` IntoIterator<Item
= &'a Entity>` types, as this would block our ability to implement cases
like `HashMap`. This means the onus is on us (or type authors) to add
explicit support for types that should be mappable.

Also note that the Component-related changes do not require a migration
guide as there hasn't been a release with them yet.

## Migration Guide

If you were previously implementing `VisitEntities` or
`VisitEntitiesMut` (likely via a derive), instead use `MapEntities`.
Those were almost certainly used in the context of Bevy Scenes or
reflection via `ReflectMapEntities`. If you have a case that uses
`VisitEntities` or `VisitEntitiesMut` directly, where `MapEntities` is
not a viable replacement, please let us know!

```rust
// before
#[derive(VisitEntities, VisitEntitiesMut)]
struct Inventory {
  items: Vec<Entity>,
  #[visit_entities(ignore)]
  label: String,
}

// after
#[derive(MapEntities)]
struct Inventory {
  #[entities]
  items: Vec<Entity>,
  label: String,
}
```
2025-03-24 00:09:29 +01:00
Wuketuke
baca78b565 Required components accept const values (#16720) (#18309)
# Objective

Const values should be more ergonomic to insert, since this is too
verbose
``` rust
#[derive(Component)]
#[require(
    LockedAxes(||LockedAxes::ROTATION_LOCKED),
)]
pub struct CharacterController;
```
instead, users can now abbreviate that nonsense like this
``` rust
#[derive(Component)]
#[require(
    LockedAxes = ROTATION_LOCKED),
)]
pub struct CharacterController;
```
it also works for enum labels.
I chose to omit the type, since were trying to reduce typing here. The
alternative would have been this:
```rust
#[require(
    LockedAxes = LockedAxes::ROTATION_LOCKED),
)]
```
This of course has its disadvantages, since the const has to be
associated, but the old closure method is still possible, so I dont
think its a problem.
- Fixes #16720

## Testing

I added one new test in the docs, which also explain the new change. I
also saw that the docs for the required components on line 165 was
missing an assertion, so I added it back in

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-24 00:09:29 +01:00
Brezak
0f446d49a1 Add more methods to RelationshipSourceCollection (#18421)
# Objective

While working on #18058 I realized I could use
`RelationshipTargetCollection::new`, so I added it.

## Solution

- Add `RelationshipTargetCollection::new`
- Add `RelationshipTargetCollection::reserve`. Could generally be useful
when doing micro-optimizations.
- Add `RelationshipTargetCollection::shrink_to_fit`. Rust collections
generally don't shrink when removing elements. Might be a good idea to
call this once in a while.

## Testing

`cargo clippy`

---

## Showcase

`RelationshipSourceCollection` now implements `new`, `reserve` and
`shrink_to_fit` to give greater control over how much memory it
consumes.

## Migration Guide

Any type implementing `RelationshipSourceCollection` now needs to also
implement `new`, `reserve` and `shrink_to_fit`. `reserve` and
`shrink_to_fit` can be made no-ops if they conceptually mean nothing to
a collection.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-03-24 00:09:29 +01:00
robtfm
27fe954623 Gltf handle missing bindposes (#18419)
# Objective

correctly load gltfs without explicit bindposes

## Solution

use identity matrices if bindposes are not found.

note: currently does nothing, as gltfs without explicit bindposes fail
to load, see <https://github.com/gltf-rs/gltf/pull/449>

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-03-24 00:09:29 +01:00
Brezak
7cd729cf1a Add methods to bulk replace relationships on a entity (#18058)
# Objective

Add a way to efficiently replace a set of specifically related entities
with a new set.
Closes #18041 

## Solution

Add new `replace_(related/children)` to `EntityWorldMut` and friends.

## Testing

Added a new test to `hierarchy.rs` that specifically check if
`replace_children` actually correctly replaces the children on a entity
while keeping the original one.

---

## Showcase

`EntityWorldMut` and `EntityCommands` can now be used to efficiently
replace the entities a entity is related to.

```rust
/// `parent` has 2 children. `entity_a` and `entity_b`.
assert_eq!([entity_a, entity_b], world.entity(parent).get::<Children>());

/// Replace `parent`s children with `entity_a` and `entity_c`
world.entity_mut(parent).replace_related(&[entity_a, entity_c]);

/// `parent` now has 2 children. `entity_a` and `entity_c`.
///
/// `replace_children` has saved time by not removing and reading
/// the relationship between `entity_a` and `parent`
assert_eq!([entity_a, entity_c], world.entity(parent).get::<Children>());

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-19 21:36:18 +01:00
Greeble
bbb79edbe4 Fix bevy_ecs doc tests with --all-features (#18424)
## Objective

Fix `bevy_ecs` doc tests failing when used with `--all-features`.

```
---- crates\bevy_ecs\src\error\handler.rs - error::handler::GLOBAL_ERROR_HANDLER (line 87) stdout ----
error[E0425]: cannot find function `default_error_handler` in this scope
 --> crates\bevy_ecs\src\error\handler.rs:92:24
  |
8 |    let error_handler = default_error_handler();
  |                        ^^^^^^^^^^^^^^^^^^^^^ not found in this scope
```

I happened to come across this while testing #12207. I'm not sure it
actually needs fixing but seemed worth a go

## Testing

```
cargo test --doc -p bevy_ecs --all-features
```

## Side Notes

The CI misses this error as it doesn't use `--all-features`. Perhaps it
should?

I tried adding `--all-features` to `ci/src/commands/doc_tests.rs` but
this triggered a linker error:

```
Compiling bevy_dylib v0.16.0-dev (C:\Projects\bevy\crates\bevy_dylib)
error: linking with `link.exe` failed: exit code: 1189
= note: LINK : fatal error LNK1189: library limit of 65535 objects exceeded␍
```
2025-03-19 21:36:18 +01:00
JMS55
62f7f2d159 Fix specialize_shadows system ordering (#18412)
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/18332

## Solution

- Move specialize_shadows to ManageViews so that it can run after
prepare_lights, so that shadow views exist for specialization.
- Unfortunately this means that specialize_shadows is no longer in
PrepareMeshes like the rest of the specialization systems.

## Testing
- Ran anti_aliasing example, switched between the different AA options,
observed no glitches.
2025-03-19 21:36:18 +01:00
charlotte
48fc396f04 Fix unecessary specialization checks for apps with many materials (#18410)
# Objective

For materials that aren't being used or a visible entity doesn't have an
instance of, we were unnecessarily constantly checking whether they
needed specialization, saying yes (because the material had never been
specialized for that entity), and failing to look up the material
instance.

## Solution

If an entity doesn't have an instance of the material, it can't possibly
need specialization, so exit early before spending time doing the check.

Fixes #18388.
2025-03-19 21:36:18 +01:00
François Mockers
42b74874e4 enable std when building bevy_dylib (#18405)
- bevy_dylib fails to build:
```
   Compiling bevy_dylib v0.16.0-rc.1 (/bevy/crates/bevy_dylib)
error: linking with `cc` failed: exit status: 1
  |
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: Undefined symbols for architecture arm64:
            "__critical_section_1_0_acquire", referenced from:
                critical_section::with::h00cfbe529dea9dc9 in libbevy_tasks-53c9db6a3865f250.rlib[58](bevy_tasks-53c9db6a3865f250.evom2xwveqp508omiiqb25xig.rcgu.o)
            "__critical_section_1_0_release", referenced from:
                core::ptr::drop_in_place$LT$critical_section..with..Guard$GT$::hfa034e0208e1a49d in libbevy_tasks-53c9db6a3865f250.rlib[48](bevy_tasks-53c9db6a3865f250.d9dwgpd0156zfn2h5z5ff94zn.rcgu.o)
          ld: symbol(s) not found for architecture arm64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

- enable `std` when building bevy_dylib

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-03-19 08:03:12 +01:00
François Mockers
f3cbe4267a gate import on bevy_animation in bevy_gltf (#18403)
# Objective

- `collect_path` is only declared when feature `bevy_animation` is
enabled
- it is imported without checking for the feature, not compiling when
not enabled

## Solution

- Gate the import
2025-03-19 00:51:59 +01:00
François Mockers
920515adab Release 0.16.0-rc.1 2025-03-18 21:48:22 +01:00
Alice Cecile
8b6f48ca35 Unified picking cleanup (#18401)
# Objective

@cart noticed some issues with my work in
https://github.com/bevyengine/bevy/pull/17348#discussion_r2001815637,
which I somehow missed before merging the PR.

## Solution

- feature gate the UiPickingPlugin correctly
- don't manually add the picking plugins

## Testing

Ran the debug_picking and sprite_picking examples (for UI and sprites
respectively): both seem to work fine.
2025-03-18 21:48:22 +01:00
Eagster
62896aaf68 Fix dynamic scene resources not being entity mapped (#18395)
# Objective

The resources were converted via `clone_reflect_value` and the cloned
value was mapped. But the value that is inserted is the source of the
clone, which was not mapped.

I ran into this issue while working on #18380. Having non consecutive
entity allocations has caught a lot of bugs.

## Solution

Use the cloned value for insertion if it exists.
2025-03-18 21:23:48 +01:00
Alice Cecile
27d02de375 Unify and simplify command and system error handling (#18351)
# Objective

- ECS error handling is a lovely flagship feature for Bevy 0.16, all in
the name of reducing panics and encouraging better error handling
(#14275).
- Currently though, command and system error handling are completely
disjoint and use different mechanisms.
- Additionally, there's a number of distinct ways to set the
default/fallback/global error handler that have limited value. As far as
I can tell, this will be cfg flagged to toggle between dev and
production builds in 99.9% of cases, with no real value in more granular
settings or helpers.
- Fixes #17272

## Solution

- Standardize error handling on the OnceLock global error mechanisms
ironed out in https://github.com/bevyengine/bevy/pull/17215
- As discussed there, there are serious performance concerns there,
especially for commands
- I also think this is a better fit for the use cases, as it's truly
global
- Move from `SystemErrorContext` to a more general purpose
`ErrorContext`, which can handle observers and commands more clearly
- Cut the superfluous setter methods on `App` and `SubApp`
- Rename the limited (and unhelpful) `fallible_systems` example to
`error_handling`, and add an example of command error handling

## Testing

Ran the `error_handling` example.

## Notes for reviewers

- Do you see a clear way to allow commands to retain &mut World access
in the per-command custom error handlers? IMO that's a key feature here
(allowing the ad-hoc creation of custom commands), but I'm not sure how
to get there without exploding complexity.
- I've removed the feature gate on the default_error_handler: contrary
to @cart's opinion in #17215 I think that virtually all apps will want
to use this. Can you think of a category of app that a) is extremely
performance sensitive b) is fine with shipping to production with the
panic error handler? If so, I can try to gather performance numbers
and/or reintroduce the feature flag. UPDATE: see benches at the end of
this message.
- ~~`OnceLock` is in `std`: @bushrat011899 what should we do here?~~
- Do you have ideas for more automated tests for this collection of
features?

## Benchmarks

I checked the impact of the feature flag introduced: benchmarks might
show regressions. This bears more investigation. I'm still skeptical
that there are users who are well-served by a fast always panicking
approach, but I'm going to re-add the feature flag here to avoid
stalling this out.


![image](https://github.com/user-attachments/assets/237f644a-b36d-4332-9b45-76fd5cbff4d0)

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-03-18 21:18:06 +01:00
Antony
f04406ccce Unify picking backends (#17348)
# Objective

Currently, our picking backends are inconsistent:

- Mesh picking and sprite picking both have configurable opt in/out
behavior. UI picking does not.
- Sprite picking uses `SpritePickingCamera` and `Pickable` for control,
but mesh picking uses `RayCastPickable`.
- `MeshPickingPlugin` is not a part of `DefaultPlugins`.
`SpritePickingPlugin` and `UiPickingPlugin` are.

## Solution

- Add configurable opt in/out behavior to UI picking (defaults to opt
out).
- Replace `RayCastPickable` with `MeshPickingCamera` and `Pickable`.
- Remove `SpritePickingPlugin` and `UiPickingPlugin` from
`DefaultPlugins`.

## Testing

Ran some examples.

## Migration Guide

`UiPickingPlugin` and `SpritePickingPlugin` are no longer included in
`DefaultPlugins`. They must be explicitly added.

`RayCastPickable` has been replaced in favor of the `MeshPickingCamera`
and `Pickable` components. You should add them to cameras and entities,
respectively, if you have `MeshPickingSettings::require_markers` set to
`true`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-18 21:18:06 +01:00
Zachary Harrold
c9f37efeb7
Remove example causing circular dependency in bevy_platform_support (#18390)
# Objective

- Alternative to #18389

## Solution

- Remove improper example.

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-03-18 08:58:52 +00:00
Fabian Thorand
205ae6441f
Force serial command encoding on Linux/amdvlk (#18368)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/18366 which seems to
have a similar underlying cause than the already closed (but not fixed)
https://github.com/bevyengine/bevy/issues/16185.

## Solution

For Windows with the AMD vulkan driver, there was already a hack to
force serial command encoding, which prevented these issues. The Linux
version of the AMD vulkan driver seems to have similar issues than its
Windows counterpart, so I extended the hack to also cover AMD on Linux.

I also removed the mention of `wgpu` since it was already outdated, and
doesn't seem to be relevant to the core issue (the AMD driver being
buggy).

## Testing

- Did you test these changes? If so, how?
- I ran the `3d_scene` example, which on `main` produced the flickering
shadows on Linux with the amdvlk driver, while it no longer does with
the workaround applied.
- Are there any parts that need more testing?
  - Not sure.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Requires a Linux system with an AMD card and the AMDVLK driver.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - My change should only affect Linux, where I did test it.
2025-03-18 03:16:38 +00:00
François Mockers
ce392fade8
remove circular dependency between bevy_sprite and bevy_image (#18379)
# Objective

- #17219 introduced a circular dependency between bevy_image and
bevy_sprite for documentation

## Solution

- Remove the circular dependency
- Simplify the doc example
2025-03-18 01:38:49 +00:00
Carter Anderson
6d6054116a
Support skipping Relationship on_replace hooks (#18378)
# Objective

Fixes #18357

## Solution

Generalize `RelationshipInsertHookMode` to `RelationshipHookMode`, wire
it up to on_replace execution, and use it in the
`Relationship::on_replace` hook.
2025-03-18 01:24:07 +00:00
François Mockers
31d2b6539c
remove circular dependency between bevy_image and bevy_core_pipeline (#18377)
# Objective

- https://github.com/bevyengine/bevy/pull/17887 introduced a circular
dependency between bevy_image and bevy_core_pipeline
- This makes it impossible to publish Bevy

## Solution

- Remove the circular dependency, reintroduce the compilation failure
- This failure shouldn't be an issue for users of Bevy, only for users
of subcrates, and can be workaround
- Proper fix should be done with
https://github.com/bevyengine/bevy/issues/17891
- Limited compilation failure is better than publish failure
2025-03-18 00:52:31 +00:00
ickshonpe
4d8bc6161b
Extract sprites into a Vec (#17619)
# Objective

Extract sprites into a `Vec` instead of a `HashMap`.

## Solution

Extract UI nodes into a `Vec` instead of an `EntityHashMap`.
Add an index into the `Vec` to `Transparent2d`.
Compare both the index and render entity in prepare so there aren't any
collisions.

## Showcase
yellow this PR, red main

```
cargo run --example many_sprites --release --features "trace_tracy"
```

`extract_sprites`
<img width="452" alt="extract_sprites"
src="https://github.com/user-attachments/assets/66c60406-7c2b-4367-907d-4a71d3630296"
/>

`queue_sprites`
<img width="463" alt="queue_sprites"
src="https://github.com/user-attachments/assets/54b903bd-4137-4772-9f87-e10e1e050d69"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-18 00:48:33 +00:00
Zachary Harrold
958c9bb652
Add no_std Library Example (#18333)
# Objective

- Fixes #17506
- Fixes #16258

## Solution

- Added a new folder of examples, `no_std`, similar to the `mobile`
folder.
- Added a single example, `no_std_library`, which demonstrates how to
make a `no_std` compatible Bevy library.
- Added a new CI task, `check-compiles-no-std-examples`, which checks
that `no_std` examples compile on `no_std` targets.
- Added `bevy_platform_support::prelude` to `bevy::prelude`.

## Testing

- CI

---

## Notes

- I've structured the folders here to permit further `no_std` examples
(e.g., GameBoy Games, ESP32 firmware, etc.), but I am starting with the
simplest and least controversial example.
- I've tried to be as clear as possible with the documentation for this
example, catering to an audience who may not have even heard of `no_std`
before.

---------

Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
2025-03-18 00:45:25 +00:00
krunchington
e5158ed96c
Update docs to explain default Hasher issue (#18350)
# Objective

I experienced an issue where `HashMap::new` was not returning a value
typed appropriately for a `HashMap<K,V>` declaration that omitted the
Hasher- e.g. the Default Hasher for the type is different than what the
`new` method produces.

After discussion on discord, this appears to be an issue in `hashbrown`,
and working around it would be very nontrivial, requiring a newtype on
top of the `hashbrown` implementation. Rather than doing that, it was
suggested that we add docs to make the issue more visible and provide a
clear workaround.

## Solution

Updated the docs for `bevy_platform_support::collections`. I couldn't
update Struct docs because they're re-exports, so I had to settle for
the module.

Note that the `[HashMap::new]` link wasn't generating properly- I'm not
sure why. I see the method in the docs.rs site,
https://docs.rs/hashbrown/0.15.1/hashbrown/struct.HashMap.html#method.new,
but not on the generated internal documentation. I wonder if `hashbrown`
isn't actually implementing the new or something?

## Testing

n/a although I did generate and open the docs on my Ubuntu machine.

---

## Showcase

before:

![image](https://github.com/user-attachments/assets/5c80417d-9c4e-4b57-825f-911203ed8558)

after:

![image](https://github.com/user-attachments/assets/420f6775-2f32-466f-a580-bb1344016bda)

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-03-17 23:25:52 +00:00
charlotte
35bf9753e8
Fixes for WESL on Windows (#18373)
# Objective

WESL was broken on windows.

## Solution

- Upgrade to `wesl_rs` 1.2.
- Fix path handling on windows.
- Improve example for khronos demo this week.
2025-03-17 22:29:29 +00:00
François Mockers
4b457cc2ce
Revert "don't use bevy_pbr for base bevy_gizmos plugin" (#18327)
# Objective

- #17581 broke gizmos
- Fixes #18325

## Solution

- Revert #17581 
- Add gizmos to testbed

## Testing

- Run any example with gizmos, it renders correctly
2025-03-17 22:23:42 +00:00
ickshonpe
df1aa39ae4
Use UiRect::all to build the UiRect constants (#18372)
# Objective

Use the const `all` fn to create the UiRect consts instead of setting
the fields individually.
2025-03-17 21:51:11 +00:00
Mads Marquart
e6a6c9fb4c
Link iOS example with rustc, and avoid C trampoline (#14780)
# Objective

On iOS:
- Allow `std` to do its runtime initialization.
- Avoid requiring the user to specify linked libraries and framework in
Xcode.
- Reduce the amount of work that `#[bevy_main]` does
- In the future we may also be able to eliminate the need for it on
Android, cc @daxpedda.

## Solution

We previously:
- Exposed an `extern "C" fn main_rs` entry point.
- Ran Cargo in a separate Xcode target as an external build system.
- Imported that as a dependency of `bevy_mobile_example.app`.
- Compiled a trampoline C file with Xcode that called `main_rs`.
- Linked that via. Xcode.

All of this is unnecessary; `rustc` is well capable of creating iOS
executables, the trick is just to place it at the correct location for
Xcode to understand it, namely `$TARGET_BUILD_DIR/$EXECUTABLE_PATH`
(places it in `bevy_mobile_example.app/bevy_mobile_example`).

Note: We might want to wait with the changes to `#[bevy_main]` until the
problem is resolved on Android too, to make the migration easier.

## Testing

Open the Xcode project, and build for an iOS target.

---

## Migration Guide

**If you have been building your application for iOS:**

Previously, the `#[bevy_main]` attribute created a `main_rs` entry point
that most Xcode templates were using to run your Rust code from C. This
was found to be unnecessary, as you can simply let Rust build your
application as a binary, and run that directly.

You have two options for dealing with this:

If you've added further C code and Xcode customizations, or it makes
sense for your use-case to continue link with Xcode, you can revert to
the old behaviour by adding `#[no_mangle] extern "C" main_rs() { main()
}` to your `main.rs`. Note that the old approach of linking a static
library prevents the Rust standard library from doing runtime
initialization, so certain functionality provided by `std` might be
unavailable (stack overflow handlers, stdout/stderr flushing and other
such functionality provided by the initialization routines).

The other, preferred option is to remove your "compile" and "link" build
phases, and instead replace it with a "run script" phase that invokes
`cargo build --bin ...`, and moves the built binary to the Xcode path
`$TARGET_BUILD_DIR/$EXECUTABLE_PATH`. An example of how to do this can
be viewed at [INSERT LINK TO UPDATED EXAMPLE PROJECT].
To make the debugging experience in Xcode nicer after this, you might
also want to consider either enabling `panic = "abort"` or to set a
breakpoint on the `rust_panic` symbol.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-03-17 21:14:07 +00:00
Gino Valente
49659700b9
bevy: Replace unnecessary tuple type registrations (#18369)
# Objective

As pointed out by @cart on
[Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1351279139872571462),
we should be careful when using tuple shorthand to register types. Doing
so incurs some unnecessary penalties such as memory/compile/performance
cost to generate registrations for a tuple type that will never be used.

A better solution would be to create a custom lint for this, but for now
we can at least remove the existing usages of this pattern.

> [!note]
> This pattern of using tuples to register multiple types at once isn't
inherently bad. Users should feel free to use this pattern, knowing the
side effects it may have. What this problem really is about is using
this in _library_ code, where users of Bevy have no choice in whether a
tuple is unnecessarily registered in an internal plugin or not.

## Solution

Replace tuple registrations with single-type registrations.

Note that I left the tuple registrations in test code since I feel like
brevity is more important in those cases. But let me know if I should
change them or leave a comment above them!

## Testing

You can test locally by running:

```
cargo check --workspace --all-features
```
2025-03-17 20:20:17 +00:00
François Mockers
d4906ddad1
Revert "Transform Propagation Optimization: Static Subtree Marking (#18094)" (#18363)
# Objective

- Fixes #18255
- Transform propagation is broken in some cases

## Solution

- Revert #18093

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-17 20:01:29 +00:00
andristarr
2b21b6cc13
FilteredResource returns a Result instead of a simple Option (#18265)
# Objective
FilteredResource::get should return a Result instead of Option

Fixes #17480 

---

## Migration Guide

Users will need to handle the different return type on
FilteredResource::get, FilteredResource::get_id,
FilteredResource::get_mut as it is now a Result not an Option.
2025-03-17 18:54:13 +00:00
Vic
d229475a3f
wrap EntityIndexMap/Set slices as well (#18134)
# Objective

Continuation of #17449.

#17449 implemented the wrapper types around `IndexMap`/`Set` and co.,
however punted on the slice types.
They are needed to support creating `EntitySetIterator`s from their
slices, not just the base maps and sets.

## Solution

Add the wrappers, in the same vein as #17449 and #17589 before.

The `Index`/`IndexMut` implementations take up a lot of space, however
they cannot be merged because we'd then get overlaps.

They are simply named `Slice` to match the `indexmap` naming scheme, but
this means they cannot be differentiated properly until their modules
are made public, which is already a follow-up mentioned in #17954.
2025-03-17 18:42:18 +00:00
Gino Valente
9b32e09551
bevy_reflect: Add clone registrations project-wide (#18307)
# Objective

Now that #13432 has been merged, it's important we update our reflected
types to properly opt into this feature. If we do not, then this could
cause issues for users downstream who want to make use of
reflection-based cloning.

## Solution

This PR is broken into 4 commits:

1. Add `#[reflect(Clone)]` on all types marked `#[reflect(opaque)]` that
are also `Clone`. This is mandatory as these types would otherwise cause
the cloning operation to fail for any type that contains it at any
depth.
2. Update the reflection example to suggest adding `#[reflect(Clone)]`
on opaque types.
3. Add `#[reflect(clone)]` attributes on all fields marked
`#[reflect(ignore)]` that are also `Clone`. This prevents the ignored
field from causing the cloning operation to fail.
   
Note that some of the types that contain these fields are also `Clone`,
and thus can be marked `#[reflect(Clone)]`. This makes the
`#[reflect(clone)]` attribute redundant. However, I think it's safer to
keep it marked in the case that the `Clone` impl/derive is ever removed.
I'm open to removing them, though, if people disagree.
4. Finally, I added `#[reflect(Clone)]` on all types that are also
`Clone`. While not strictly necessary, it enables us to reduce the
generated output since we can just call `Clone::clone` directly instead
of calling `PartialReflect::reflect_clone` on each variant/field. It
also means we benefit from any optimizations or customizations made in
the `Clone` impl, including directly dereferencing `Copy` values and
increasing reference counters.

Along with that change I also took the liberty of adding any missing
registrations that I saw could be applied to the type as well, such as
`Default`, `PartialEq`, and `Hash`. There were hundreds of these to
edit, though, so it's possible I missed quite a few.

That last commit is **_massive_**. There were nearly 700 types to
update. So it's recommended to review the first three before moving onto
that last one.

Additionally, I can break the last commit off into its own PR or into
smaller PRs, but I figured this would be the easiest way of doing it
(and in a timely manner since I unfortunately don't have as much time as
I used to for code contributions).

## Testing

You can test locally with a `cargo check`:

```
cargo check --workspace --all-features
```
2025-03-17 18:32:35 +00:00
ickshonpe
e61b5a1d67
UiRect::AUTO (#18359)
# Objective

Add a `UiRect::AUTO` const which is a `UiRect` with all its edge values
set to `Val::Auto`.

IIRC `UiRect`'s default for its fields a few versions ago was
`Val::Auto` because positions were represented using a `UiRect` and they
required `Val::Auto` as a default. Then when position was split up and
the `UiRect` default was changed, we forgot add a `UiRect::AUTO` const.
2025-03-17 18:24:21 +00:00
JMS55
0be1529d15
Expose textures to ViewTarget::post_process_write() (#18348)
Extracted from my DLSS branch.

## Changelog
* Added `source_texture` and `destination_texture` to
`PostProcessWrite`, in addition to the existing texture views.
2025-03-17 18:22:06 +00:00
Wuketuke
5c3368fbcf
Fixed Reflect derive macro on empty enums (#18277) (#18298)
obtaining a reference to an empty enum is not possible in Rust, so I
just replaced any match on self with an `unreachable!()`
I checked if an enum is empty by checking if the `variant_patterns` vec
of the `EnumVariantOutputData` struct is empty
Fixes #18277

## Testing

I added one new unit test.
``` rust
#[test]
fn should_allow_empty_enums() {
    #[derive(Reflect)]
    enum Empty {}

    assert_impl_all!(Empty: Reflect);
}
```
2025-03-17 18:13:55 +00:00
Matty Weatherley
af61ec2bc1
Incorporate viewport position into clamping in camera_system (#18242)
# Objective

In its existing form, the clamping that's done in `camera_system`
doesn't work well when the `physical_position` of the associated
viewport is nonzero. In such cases, it may produce invalid viewport
rectangles (i.e. not lying inside the render target), which may result
in crashes during the render pass.

The goal of this PR is to eliminate this possibility by making the
clamping behavior always result in a valid viewport rectangle when
possible.

## Solution

Incorporate the `physical_position` information into the clamping
behavior. In particular, always cut off enough so that it's contained in
the render target rather than clamping it to the same dimensions as the
target itself. In weirder situations, still try to produce a valid
viewport rectangle to avoid crashes.

## Testing

Tested these changes on my work branch where I encountered the crash.
2025-03-17 18:10:11 +00:00
Christian Hughes
fecf2d2591
Provide a safe abstraction for split access to entities and commands (#18215)
# Objective

Currently experimenting with manually implementing
`Relationship`/`RelationshipTarget` to support associated edge data,
which means I need to replace the default hook implementations provided
by those traits. However, copying them over for editing revealed that
`UnsafeWorldCell::get_raw_command_queue` is `pub(crate)`, and I would
like to not have to clone the source collection, like the default impl.
So instead, I've taken to providing a safe abstraction for being able to
access entities and queue commands simultaneously.

## Solution

Added `World::entities_and_commands` and
`DeferredWorld::entities_and_commands`, which can be used like so:

```rust
let eid: Entity = /* ... */;
let (mut fetcher, mut commands) = world.entities_and_commands();
let emut = fetcher.get_mut(eid).unwrap();
commands.entity(eid).despawn();
```

## Testing

- Added a new test for each of the added functions.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-17 18:05:50 +00:00
Rob Parrett
770059c539
Fix clippy lints on Rust beta (#18361)
# Objective

Fixes #18360

## Solution

```
rustup toolchain install beta
rustup default beta
cargo run -p ci
```

Make suggested changes

## Testing

`cargo run -p ci`
2025-03-17 18:00:27 +00:00
JMS55
160d79f24d
Make prepare_view_targets() caching account for CameraMainTextureUsages (#18347)
Small bugfix.
2025-03-17 04:23:29 +00:00
Matt Campbell
35526743b3
bevy_winit: Create the window initially invisible as required by AccessKit (#18346)
The initial `with_visible` call was intended to do this, but that was
undone by a later `with_visible` call.
2025-03-17 00:41:19 +00:00
Tero Laxström
79655269f5
Add process cpu/memory usage to SystemInformationDiagnosticsPlugin (#18279)
# Objective

- Adding process specific cpu/mem usages to
SystemInformationDiagnosticsPlugin
- Fixes #18135

## Solution

- Adding two new stats by using code provided in #18135

## Testing

- Tested by adding SystemInformationDiagnosticsPlugin into
enabling_disabling_diagnostics example
- Tested only on Linux (Ubuntu 24.04.2 LTS)

---

## Showcase

Example output:
> 2025-03-12T18:20:45.355206Z INFO bevy diagnostic: fps : 144.139984
(avg 143.968838)
> 2025-03-12T18:20:45.355229Z INFO bevy diagnostic: system/cpu_usage :
17.299578% (avg 16.410863%)
> 2025-03-12T18:20:45.355235Z INFO bevy diagnostic: frame_time :
6.939720ms (avg 6.953508ms)
> 2025-03-12T18:20:45.355239Z INFO bevy diagnostic: frame_count :
1271.000000
> 2025-03-12T18:20:45.355243Z INFO bevy diagnostic: process/cpu_usage:
172.151901% (avg 165.337555%)
> 2025-03-12T18:20:45.355247Z INFO bevy diagnostic: process/mem_usage:
400.472656% (avg 400.478516%)
> 2025-03-12T18:20:45.355250Z INFO bevy diagnostic: system/mem_usage :
34.244571% (avg 34.356289%)
2025-03-16 21:14:46 +00:00
Vic
b7d5254762
implement get_many_unique (#18315)
# Objective

Continuation to #16547 and #17954.

The `get_many` family are the last methods on `Query`/`QueryState` for
which we're still missing a `unique` version.

## Solution

Offer `get_many_unique`/`get_many_unique_mut` and
`get_many_unique_inner`!

Their implementation is the same as `get_many`, the difference lies in
their guaranteed-to-be unique inputs, meaning we never do any aliasing
checks.

To reduce confusion, we also rename `get_many_readonly` into
`get_many_inner` and the current `get_many_inner` into
`get_many_mut_inner` to clarify their purposes.

## Testing

Doc examples.

## Migration Guide

`get_many_inner` is now called `get_many_mut_inner`.
`get_many_readonly` is now called `get_many_inner`.
2025-03-16 21:12:26 +00:00
andriyDev
9bcaad7b43
Canonicalize the root path to match the canonicalized asset path. (#18345)
# Objective

- Fixes #18342.

## Solution

- Canonicalize the root path so that when we try to strip the prefix, it
matches the canonicalized asset path.
- This is basically just a followup to #18023.

## Testing

- Ran the hot_asset_reloading example and it no longer panics.
2025-03-16 21:03:29 +00:00
Gino Valente
137451b584
bevy_render: Derive Error on ViewportConversionError (#18336)
# Objective

The `ViewportConversionError` error type does not implement `Error`,
making it incompatible with `BevyError`.

## Solution

Derive `Error` for `ViewportConversionError`.

I chose to use `thiserror` since it's already a dependency, but do let
me know if we should be preferring `derive_more`.

## Testing

You can test this by trying to compile the following:

```rust
let error: BevyError = ViewportConversionError::InvalidData.into();
```
2025-03-16 18:58:30 +00:00
urben1680
ca6630a24a
Introduce public World::register_dynamic_bundle method (#18198)
Registering dynamic bundles was not possible for the user yet.

It is alone not very useful though as there are no methods to clone,
move or remove components via a `BundleId`. This could be a follow-up
work if this PR is approved and such a third (besides `T: Bundle` and
`ComponentId`(s)) API for structural operation is desired. I certainly
would use a hypothetical `EntityClonerBuilder::allow_by_bundle_id`.

I personally still would like this register method because I have a
`Bundles`-like custom data structure and I would like to not reinvent
the wheel. Then instead of having boxed `ComponentId` slices in my
collection I could look up explicit and required components there.

For reference scroll up to the typed version right above the new one.
2025-03-16 18:58:16 +00:00
noxmore
18f543474d
Derive Clone for ImageLoaderSettings and ImageFormatSetting (#18335)
# Objective

I was setting up an asset loader that passes settings through to
`ImageLoader`, and i have to clone the settings to achieve this.

## Solution

Derive `Clone` for `ImageLoaderSettings` and `ImageFormatSetting`.

## Testing

Full CI passed.
2025-03-16 18:57:25 +00:00
Patrick Walton
528e68f5bb
Pad out binding arrays to their full length if partially bound binding arrays aren't supported. (#18126)
I mistakenly thought that with the wgpu upgrade we'd have
`PARTIALLY_BOUND_BINDING_ARRAY` everywhere. Unfortunately this is not
the case. This PR adds a workaround back in.

Closes #18098.
2025-03-16 10:57:33 +00:00
JMS55
195a74afad
Add missing system ordering constraint to prepare_lights (#18308)
Fix https://github.com/bevyengine/bevy/issues/18094.
2025-03-15 22:57:52 +00:00
JMS55
d41de7f3df
Fix MainTransparentPass2dNode attachment ordering (#18306)
Fix https://github.com/bevyengine/bevy/issues/17763.

Attachment info needs to be created outside of the command encoding
task, as it needs to be part of the serial node runners in order to get
the ordering correct.
2025-03-15 17:31:52 +00:00
Robert Swain
bc7416aa22
Use 4-byte LightmapSlabIndex for batching instead of 16-byte AssetId<Image> (#18326)
Less data accessed and compared gives better batching performance.

# Objective

- Use a smaller id to represent the lightmap in batch data to enable a
faster implementation of draw streams.
- Improve batching performance for 3D sorted render phases.

## Solution

- 3D batching can use `LightmapSlabIndex` (a `NonMaxU32` which is 4
bytes) instead of the lightmap `AssetId<Image>` (an enum where the
largest variant is a 16-byte UUID) to discern the ability to batch.

## Testing

Tested main (yellow) vs this PR (red) on an M4 Max using the
`many_cubes` example with `WGPU_SETTINGS_PRIO=webgl2` to avoid
GPU-preprocessing, and modifying the materials in `many_cubes` to have
`AlphaMode::Blend` so that they would rely on the less efficient sorted
render phase batching.
<img width="1500" alt="Screenshot_2025-03-15_at_12 17 21"
src="https://github.com/user-attachments/assets/14709bd3-6d06-40fb-aa51-e1d2d606ebe3"
/>
A 44.75us or 7.5% reduction in median execution time of the batch and
prepare sorted render phase system for the `Transparent3d` phase
(handling 160k cubes).

---

## Migration Guide

- Changed: `RenderLightmap::new()` no longer takes an `AssetId<Image>`
argument for the asset id of the lightmap image.
2025-03-15 14:16:32 +00:00
Vic
b462f47864
add Entity default to the entity set wrappers (#18319)
# Objective

Installment of the #16547 series.

The vast majority of uses for these types will be the `Entity` case, so
it makes sense for it to be the default.

## Solution

`UniqueEntityVec`, `UniqueEntitySlice`, `UniqueEntityArray` and their
helper iterator aliases now have `Entity` as a default.

Unfortunately, this means the the `T` parameter for `UniqueEntityArray`
now has to be ordered after the `N` constant, which breaks the
consistency to `[T; N]`.
Same with about a dozen iterator aliases that take some `P`/`F`
predicate/function parameter.
This should however be an ergonomic improvement in most cases, so we'll
just have to live with this inconsistency.

## Migration Guide

Switch type parameter order for the relevant wrapper types/aliases.
2025-03-15 01:51:39 +00:00
Gino Valente
c2854a2a05
bevy_reflect: Deprecate PartialReflect::clone_value (#18284)
# Objective

#13432 added proper reflection-based cloning. This is a better method
than cloning via `clone_value` for reasons detailed in the description
of that PR. However, it may not be immediately apparent to users why one
should be used over the other, and what the gotchas of `clone_value`
are.

## Solution

This PR marks `PartialReflect::clone_value` as deprecated, with the
deprecation notice pointing users to `PartialReflect::reflect_clone`.
However, it also suggests using a new method introduced in this PR:
`PartialReflect::to_dynamic`.

`PartialReflect::to_dynamic` is essentially a renaming of
`PartialReflect::clone_value`. By naming it `to_dynamic`, we make it
very obvious that what's returned is a dynamic type. The one caveat to
this is that opaque types still use `reflect_clone` as they have no
corresponding dynamic type.

Along with changing the name, the method is now optional, and comes with
a default implementation that calls out to the respective reflection
subtrait method. This was done because there was really no reason to
require manual implementors provide a method that almost always calls
out to a known set of methods.

Lastly, to make this default implementation work, this PR also did a
similar thing with the `clone_dynamic ` methods on the reflection
subtraits. For example, `Struct::clone_dynamic` has been marked
deprecated and is superseded by `Struct::to_dynamic_struct`. This was
necessary to avoid the "multiple names in scope" issue.

### Open Questions

This PR maintains the original signature of `clone_value` on
`to_dynamic`. That is, it takes `&self` and returns `Box<dyn
PartialReflect>`.

However, in order for this to work, it introduces a panic if the value
is opaque and doesn't override the default `reflect_clone`
implementation.

One thing we could do to avoid the panic would be to make the conversion
fallible, either returning `Option<Box<dyn PartialReflect>>` or
`Result<Box<dyn PartialReflect>, ReflectCloneError>`.

This makes using the method a little more involved (i.e. users have to
either unwrap or handle the rare possibility of an error), but it would
set us up for a world where opaque types don't strictly need to be
`Clone`. Right now this bound is sort of implied by the fact that
`clone_value` is a required trait method, and the default behavior of
the macro is to use `Clone` for opaque types.

Alternatively, we could keep the signature but make the method required.
This maintains that implied bound where manual implementors must provide
some way of cloning the value (or YOLO it and just panic), but also
makes the API simpler to use.

Finally, we could just leave it with the panic. It's unlikely this would
occur in practice since our macro still requires `Clone` for opaque
types, and thus this would only ever be an issue if someone were to
manually implement `PartialReflect` without a valid `to_dynamic` or
`reflect_clone` method.

## Testing

You can test locally using the following command:

```
cargo test --package bevy_reflect --all-features
```

---

## Migration Guide

`PartialReflect::clone_value` is being deprecated. Instead, use
`PartialReflect::to_dynamic` if wanting to create a new dynamic instance
of the reflected value. Alternatively, use
`PartialReflect::reflect_clone` to attempt to create a true clone of the
underlying value.

Similarly, the following methods have been deprecated and should be
replaced with these alternatives:
- `Array::clone_dynamic` → `Array::to_dynamic_array`
- `Enum::clone_dynamic` → `Enum::to_dynamic_enum`
- `List::clone_dynamic` → `List::to_dynamic_list`
- `Map::clone_dynamic` → `Map::to_dynamic_map`
- `Set::clone_dynamic` → `Set::to_dynamic_set`
- `Struct::clone_dynamic` → `Struct::to_dynamic_struct`
- `Tuple::clone_dynamic` → `Tuple::to_dynamic_tuple`
- `TupleStruct::clone_dynamic` → `TupleStruct::to_dynamic_tuple_struct`
2025-03-14 19:33:57 +00:00
andriyDev
adbb53b87f
Return an error when direct-nested-loading a subasset (#18213)
# Objective

- Prevents #18291.
- Previously, attempting to direct-nested-load a subasset would return
the root of the nested-loaded asset. This is most problematic when doing
direct-nested-**untyped**-loads of subassets, where you may not even
realize you're dealing with the entirely wrong asset (at least with
typed loads, *most of the time* the root asset has a different type from
the subasset, and so at least you'd get an error that the types don't
match).

## Solution

- We now return an error when doing these kinds of loads.

Note an alternative would be to "solve" this problem, by just looking up
the appropriate subasset after doing the nested load. However there's
two problems: 1) we don't know which subassets of the root asset are
necessary for the subasset we are looking up (so any handles in that
subasset may never get registered), 2) a solution will likely hamper
attempts to resolve #18010. AFAICT, no one has complained about this
issue, so it doesn't seem critical to fix this for now.

## Testing

- Added a test to ensure this returns an error. I also checked that the
error before this was just a mismatched type error, meaning it was
trying to pass off the root asset type `CoolText` as the subasset type
`SubText` (which would have worked had I not been using typed loads).
2025-03-13 16:36:18 +00:00
Lynn
f245490e4a
implement Bounded2d for ConvexPolygon (#18286)
# Objective

- Implement `Bounded2d` for `ConvexPolygon`
2025-03-13 16:35:52 +00:00
Alice Cecile
ab0e3f8714
Small cleanup for ECS error handling (#18280)
# Objective

While poking at https://github.com/bevyengine/bevy/issues/17272, I
noticed a few small things to clean up.

## Solution

- Improve the docs
- ~~move `SystemErrorContext` out of the `handler.rs` module: it's not
an error handler~~
2025-03-13 00:13:02 +00:00
MevLyshkin
8f38ea352e
RPC Discover endpoint with basic informations (#18068)
# Objective

It does not resolves issue for full support for OpenRPC for
`bevy_remote`, but it is a first step in that direction. Connected to
the #16744 issue.

## Solution

- Adds `rpc.discover` endpoint to the bevy_remote which follows
https://spec.open-rpc.org/#openrpc-document For now in methods array
only the name, which is the endpoint address is populated.
- Moves json_schema structs into new module inside `bevy_remote`. 

## Testing

Tested the commands by running the BRP sample( cargo run --example
server --features="bevy_remote") and with these curl command:

```sh
curl -X POST -d '{ "jsonrpc": "2.0", "id": 1, "method": "rpc.discover"}' 127.0.0.1:15702 | jq .
```
The output is: 
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "info": {
      "title": "Bevy Remote Protocol",
      "version": "0.16.0-dev"
    },
    "methods": [
      {
        "name": "bevy/mutate_component",
        "params": []
      },
      {
        "name": "bevy/insert",
        "params": []
      },
      {
        "name": "bevy/get",
        "params": []
      },
      {
        "name": "bevy/spawn",
        "params": []
      },
      {
        "name": "bevy/get+watch",
        "params": []
      },
      {
        "name": "bevy/destroy",
        "params": []
      },
      {
        "name": "bevy/list",
        "params": []
      },
      {
        "name": "bevy/mutate_resource",
        "params": []
      },
      {
        "name": "bevy/reparent",
        "params": []
      },
      {
        "name": "bevy/registry/schema",
        "params": []
      },
      {
        "name": "bevy/get_resource",
        "params": []
      },
      {
        "name": "bevy/query",
        "params": []
      },
      {
        "name": "bevy/remove_resource",
        "params": []
      },
      {
        "name": "rpc.discover",
        "params": []
      },
      {
        "name": "bevy/insert_resource",
        "params": []
      },
      {
        "name": "bevy/list_resources",
        "params": []
      },
      {
        "name": "bevy/remove",
        "params": []
      },
      {
        "name": "bevy/list+watch",
        "params": []
      }
    ],
    "openrpc": "1.3.2",
    "servers": [
      {
        "name": "Server",
        "url": "127.0.0.1:15702"
      }
    ]
  }
}
```

---------

Co-authored-by: Viktor Gustavsson <villor94@gmail.com>
2025-03-12 23:32:06 +00:00
Matty Weatherley
84463e60e1
Implement Serialize/Deserialize/PartialEq for bounding primitives (#18281)
# Objective

Probably just because of an oversight, bounding primitives like `Aabb3d`
did not implement `Serialize`/`Deserialize` with the `serialize` feature
enabled, so the goal of this PR is to fill the gap.

## Solution

Derive it conditionally, just like we do for everything else. Also added
in `PartialEq`, just because I touched the files.

## Testing

Compiled with different feature combinations.
2025-03-12 21:38:29 +00:00
Zachary Harrold
dc7cb2a3e1
Switch to ImDocument in BevyManifest (#18272)
# Objective

When reviewing #18263, I noticed that `BevyManifest` internally stores a
`DocumentMut`, a mutable TOML document, instead of an `ImDocument`, an
immutable one. The process of creating a `DocumentMut` first involves
creating a `ImDocument` and then cloning all the referenced spans of
text into their own allocations (internally referred to as `despan` in
`toml_edit`). As such, using a `DocumentMut` without mutation is
strictly additional overhead.

In addition, I noticed that the filesystem operations associated with
reading a manifest and parsing it were written to be completed _while_ a
write-lock was held on `MANIFESTS`. This likely doesn't translate into a
performance or deadlock issue as the manifest files are generally small
and can be read quickly, but it is generally considered a bad practice.

## Solution

- Switched to `ImDocument<Box<str>>` instead of `DocumentMut`
- Re-ordered operations in `BevyManifest::shared` to minimise time spent
holding open the write-lock on `MANIFESTS`

## Testing

- CI

---

## Notes

I wasn't able to measure a meaningful performance difference with this
PR, so this is purely a code quality change and not one for performance.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2025-03-12 20:15:39 +00:00
Rob Parrett
81c0900cf2
Upgrade to cosmic-text 0.13 (#18239)
# Objective

Upgrade to `cosmic-text` 0.13

https://github.com/pop-os/cosmic-text/releases

This should include some performance improvements for layout and system
font loading.

## Solution

Bump version, fix the one changed API.

## Testing

Tested some examples locally, will invoke the example runner.

## Layout Perf

||main fps|cosmic-13 fps|
|-|-|-|
|many_buttons --recompute-text --no-borders|6.79|9.42 🟩 +38.7%|
|many_text2d --no-frustum-culling --recompute|3.19|4.28 🟩 +34.0%|
|many_glyphs --recompute-text|7.09|11.17 🟩 +57.6%|
|text_pipeline |140.15|139.90  -0.2%|

## System Font Loading Perf

I tested on macOS somewhat lazily by adding the following system to the
`system_fonts` example from #16365.

<details>
<summary>Expand code</summary>

```rust
fn exit_on_load(
    mut reader: EventReader<bevy::text::SystemFontsAvailable>,
    mut writer: EventWriter<AppExit>,
) {
    for _evt in reader.read() {
        writer.write(AppExit::Success);
    }
}
```
</details>

And running `hyperfine 'cargo run --release --example system_fonts
--features=system_font'`.

The results were nearly identical with and without this PR cherry-picked
there.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-12 18:03:45 +00:00
NiseVoid
5d80ac3ded
Add derive Default to Disabled (#18275)
# Objective

- `#[require(Disabled)]` doesn't work as you'd expect

## Solution

- `#[derive(Default)]`
2025-03-12 17:57:20 +00:00
ickshonpe
26ea38e4a6
Remove the entity index from the UI phase's sort key (#18273)
# Objective

The sort key for the transparent UI phase is a (float32, u32) pair
consisting of the stack index and the render entity's index.
I guess the render entity index was intended to break ties but it's not
needed as the sort is stable. It also assumes the indices of the render
entities are generated sequentially, which isn't guaranteed.

Fixes the issues with the text wrap example seen in #18266

## Solution

Change the sort key to just use the stack index alone.
2025-03-12 17:11:02 +00:00
Carter Anderson
e21dfe81ce
Internalize BevyManifest logic. Switch to RwLock (#18263)
# Objective

Fixes #18103

#17330 introduced a significant compile time performance regression
(affects normal builds, clippy, and Rust Analyzer). While it did fix the
type-resolution bug (and the general approach there is still our best
known solution to the problem that doesn't involve [significant
maintenance
overhead](https://github.com/bevyengine/bevy/issues/18103#issuecomment-2702724676)),
the changes had a couple of issues:

1. It used a Mutex, which poses a significant threat to parallelization.
2. It externalized existing, relatively simple, performance critical
Bevy code to a crate outside of our control. I am not comfortable doing
that for cases like this. Going forward @bevyengine/maintainer-team
should be much stricter about this.
3. There were a number of other areas that introduced complexity and
overhead that I consider unnecessary for our use case. On a case by case
basis, if we encounter a need for more capabilities we can add them (and
weigh them against the cost of doing so).

## Solution

1. I moved us back to our original code as a baseline
2. I selectively ported over the minimal changes required to fix the
type resolution bug
3. I swapped `Mutex<BTreeMap<PathBuf, &'static Mutex<CargoManifest>>>`
for `RwLock<BTreeMap<PathBuf, CargoManifest>>`. Note that I used the
`parking_lot` RwLock because it has a mapping API that enables us to
return mapped guards.
2025-03-12 00:46:01 +00:00
newclarityex
ecccd57417
Generic system config (#17962)
# Objective
Prevents duplicate implementation between IntoSystemConfigs and
IntoSystemSetConfigs using a generic, adds a NodeType trait for more
config flexibility (opening the door to implement
https://github.com/bevyengine/bevy/issues/14195?).

## Solution
Followed writeup by @ItsDoot:
https://hackmd.io/@doot/rJeefFHc1x

Removes IntoSystemConfigs and IntoSystemSetConfigs, instead using
IntoNodeConfigs with generics.

## Testing
Pending

---

## Showcase
N/A

## Migration Guide
SystemSetConfigs -> NodeConfigs<InternedSystemSet>
SystemConfigs -> NodeConfigs<ScheduleSystem>
IntoSystemSetConfigs -> IntoNodeConfigs<InternedSystemSet, M>
IntoSystemConfigs -> IntoNodeConfigs<ScheduleSystem, M>

---------

Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-12 00:12:30 +00:00
krunchington
f1331069e7
Implement SpawnableList for Vec<Bundle> (#18259)
# Objective

In updating examples to use the Improved Spawning API I got tripped up
on being able to spawn children with a Vec. I eventually figured out
that I could use `Children::spawn(SpawnIter(my_vec.into_iter()))` but
thought there might be a more ergonomic way to approach it. After
tinkering with it for a while I came up with the implementation here. It
allows authors to use `Children::spawn(my_vec)` as an equivalent
implementation.

## Solution

- Implements `<R: Relationship, B: Bundle SpawnableList<R> for Vec<B>`
- uses `alloc::vec::Vec` for compatibility with `no_std` (`std::Vec`
also inherits implementations against the `alloc::vec::Vec` because std
is a re-export of the alloc struct, thanks @bushrat011899 for the info
on this!)

## Testing

- Did you test these changes? If so, how?
- Opened the examples before and after and verified the same behavior
was observed. I did this on Ubuntu 24.04.2 LTS using `--features
wayland`.
- Are there any parts that need more testing?
- Other OS's and features can't hurt, but this is such a small change it
shouldn't be a problem.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Run the examples yourself with and without these changes.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - see above

## Showcase

n/a

## Migration Guide

- Optional: you may use the new API to spawn `Vec`s of `Bundle` instead
of using the `SpawnIter` approach.
2025-03-11 20:32:37 +00:00
Peepo-Juice
949d7811cd
Sync up the Derive of DragEntry to match the other events (#18220)
# Objective
Add `#[derive(Clone, PartialEq, Debug, Reflect)]` to DragEntry so it
matches the other picking events.

## Solution
Copy/paste (RIP Larry Tesler)

## Testing
Just ran cargo check. I don't believe this should break anything because
I did not remove any derives it had before.

---
2025-03-11 19:58:20 +00:00
Cyrill Schenkel
8570af1d96
Add print_stdout and print_stderr lints (#17446) (#18233)
# Objective

- Prevent usage of `println!`, `eprintln!` and the like because they
require `std`
- Fixes #17446

## Solution

- Enable the `print_stdout` and `print_stderr` clippy lints
- Replace all `println!` and `eprintln!` occurrences with `log::*` where
applicable or alternatively ignore the warnings

## Testing

- Run `cargo clippy --workspace` to ensure that there are no warnings
relating to printing to `stdout` or `stderr`
2025-03-11 19:35:48 +00:00
Brezak
4f6241178f
Remove superfluous spaces in Transform documentation (#18244)
# Objective

Closes #18228

## Solution

`hx
.\crates\bevy_transform\src\components\transform.rs<enter>40ggllldd:wq<enter>`

## Testing

`cargo +beta clippy --all-features`
2025-03-11 11:25:12 +00:00
Gino Valente
f5210c54d2
bevy_reflect: Reflection-based cloning (#13432)
# Objective

Using `Reflect::clone_value` can be somewhat confusing to those
unfamiliar with how Bevy's reflection crate works. For example take the
following code:

```rust
let value: usize = 123;
let clone: Box<dyn Reflect> = value.clone_value();
```

What can we expect to be the underlying type of `clone`? If you guessed
`usize`, then you're correct! Let's try another:

```rust
#[derive(Reflect, Clone)]
struct Foo(usize);

let value: Foo = Foo(123);
let clone: Box<dyn Reflect> = value.clone_value();
```

What about this code? What is the underlying type of `clone`? If you
guessed `Foo`, unfortunately you'd be wrong. It's actually
`DynamicStruct`.

It's not obvious that the generated `Reflect` impl actually calls
`Struct::clone_dynamic` under the hood, which always returns
`DynamicStruct`.

There are already some efforts to make this a bit more apparent to the
end-user: #7207 changes the signature of `Reflect::clone_value` to
instead return `Box<dyn PartialReflect>`, signaling that we're
potentially returning a dynamic type.

But why _can't_ we return `Foo`?

`Foo` can obviously be cloned— in fact, we already derived `Clone` on
it. But even without the derive, this seems like something `Reflect`
should be able to handle. Almost all types that implement `Reflect`
either contain no data (trivially clonable), they contain a
`#[reflect_value]` type (which, by definition, must implement `Clone`),
or they contain another `Reflect` type (which recursively fall into one
of these three categories).

This PR aims to enable true reflection-based cloning where you get back
exactly the type that you think you do.

## Solution

Add a `Reflect::reflect_clone` method which returns `Result<Box<dyn
Reflect>, ReflectCloneError>`, where the `Box<dyn Reflect>` is
guaranteed to be the same type as `Self`.

```rust
#[derive(Reflect)]
struct Foo(usize);

let value: Foo = Foo(123);
let clone: Box<dyn Reflect> = value.reflect_clone().unwrap();
assert!(clone.is::<Foo>());
```

Notice that we didn't even need to derive `Clone` for this to work: it's
entirely powered via reflection!

Under the hood, the macro generates something like this:

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Self {
        // The `reflect_clone` impl for `usize` just makes use of its `Clone` impl
        0: Reflect::reflect_clone(&self.0)?.take().map_err(/* ... */)?,
    }))
}
```

If we did derive `Clone`, we can tell `Reflect` to rely on that instead:

```rust
#[derive(Reflect, Clone)]
#[reflect(Clone)]
struct Foo(usize);
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Clone::clone(self)))
}
```

</details>

Or, we can specify our own cloning function:

```rust
#[derive(Reflect)]
#[reflect(Clone(incremental_clone))]
struct Foo(usize);

fn incremental_clone(value: &usize) -> usize {
  *value + 1
}
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(incremental_clone(self)))
}
```

</details>

Similarly, we can specify how fields should be cloned. This is important
for fields that are `#[reflect(ignore)]`'d as we otherwise have no way
to know how they should be cloned.

```rust
#[derive(Reflect)]
struct Foo {
 #[reflect(ignore, clone)]
  bar: usize,
  #[reflect(ignore, clone = "incremental_clone")]
  baz: usize,
}

fn incremental_clone(value: &usize) -> usize {
  *value + 1
}
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Self {
        bar: Clone::clone(&self.bar),
        baz: incremental_clone(&self.baz),
    }))
}
```

</details>

If we don't supply a `clone` attribute for an ignored field, then the
method will automatically return
`Err(ReflectCloneError::FieldNotClonable {/* ... */})`.

`Err` values "bubble up" to the caller. So if `Foo` contains `Bar` and
the `reflect_clone` method for `Bar` returns `Err`, then the
`reflect_clone` method for `Foo` also returns `Err`.

### Attribute Syntax

You might have noticed the differing syntax between the container
attribute and the field attribute.

This was purely done for consistency with the current attributes. There
are PRs aimed at improving this. #7317 aims at making the
"special-cased" attributes more in line with the field attributes
syntactically. And #9323 aims at moving away from the stringified paths
in favor of just raw function paths.

### Compatibility with Unique Reflect

This PR was designed with Unique Reflect (#7207) in mind. This method
actually wouldn't change that much (if at all) under Unique Reflect. It
would still exist on `Reflect` and it would still `Option<Box<dyn
Reflect>>`. In fact, Unique Reflect would only _improve_ the user's
understanding of what this method returns.

We may consider moving what's currently `Reflect::clone_value` to
`PartialReflect` and possibly renaming it to `partial_reflect_clone` or
`clone_dynamic` to better indicate how it differs from `reflect_clone`.

## Testing

You can test locally by running the following command:

```
cargo test --package bevy_reflect
```

---

## Changelog

- Added `Reflect::reflect_clone` method
- Added `ReflectCloneError` error enum
- Added `#[reflect(Clone)]` container attribute
- Added `#[reflect(clone)]` field attribute
2025-03-11 06:02:59 +00:00
Vic
32d53e7bd3
make various entity wrapper type modules public (#18248)
# Objective

Part of the #16547 series.

The entity wrapper types often have some associated types an aliases
with them that cannot be re-exported into an outer module together.
Some helper types are best used with part of their path:
`bevy::ecs::entity::index_set::Slice` as `index_set::Slice`.
This has already been done for `entity::hash_set` and
`entity::hash_map`.

## Solution

Publicize the `index_set`, `index_map`, `unique_vec`, `unique_slice`,
and `unique_array` modules.

## Migration Guide

Any mention or import of types in the affected modules have to add the
respective module name to the import path.
F.e.:
`bevy::ecs::entity::EntityIndexSet` ->
`bevy::ecs::entity::index_set::EntityIndexSet`
2025-03-11 05:48:31 +00:00
jf908
bfe932d1f3
Rework WindowMode::Fullscreen API (#17525)
# Objective

- #16883 
- Improve the default behaviour of the exclusive fullscreen API.

## Solution

This PR changes the exclusive fullscreen window mode to require the type
`WindowMode::Fullscreen(MonitorSelection, VideoModeSelection)` and
removes `WindowMode::SizedFullscreen`. This API somewhat intentionally
more closely resembles Winit 0.31's upcoming fullscreen and video mode
API.

The new VideoModeSelection enum is specified as follows:

```rust
pub enum VideoModeSelection {
    /// Uses the video mode that the monitor is already in.
    Current,
    /// Uses a given [`crate::monitor::VideoMode`]. A list of video modes supported by the monitor
    /// is supplied by [`crate::monitor::Monitor::video_modes`].
    Specific(VideoMode),
}
```

### Changing default behaviour

This might be contentious because it removes the previous behaviour of
`WindowMode::Fullscreen` which selected the highest resolution possible.
While the previous behaviour would be quite easy to re-implement as
additional options, or as an impl method on Monitor, I would argue that
this isn't an implementation that should be encouraged.

From the perspective of a Windows user, I prefer what the majority of
modern games do when entering fullscreen which is to preserve the OS's
current resolution settings, which allows exclusive fullscreen to be
entered faster, and to only have it change if I manually select it in
either the options of the game or the OS. The highest resolution
available is not necessarily what the user prefers.

I am open to changing this if I have just missed a good use case for it.

Likewise, the only functionality that `WindowMode::SizedFullscreen`
provided was that it selected the resolution closest to the current size
of the window so it was removed since this behaviour can be replicated
via the new `VideoModeSelection::Specific` if necessary.

## Out of scope

WindowResolution and scale factor act strangely in exclusive fullscreen,
this PR doesn't address it or regress it.

## Testing

- Tested on Windows 11 and macOS 12.7
- Linux untested

## Migration Guide

`WindowMode::SizedFullscreen(MonitorSelection)` and
`WindowMode::Fullscreen(MonitorSelection)` has become
`WindowMode::Fullscreen(MonitorSelection, VideoModeSelection)`.
Previously, the VideoMode was selected based on the closest resolution
to the current window size for SizedFullscreen and the largest
resolution for Fullscreen. It is possible to replicate that behaviour by
searching `Monitor::video_modes` and selecting it with
`VideoModeSelection::Specific(VideoMode)` but it is recommended to use
`VideoModeSelection::Current` as the default video mode when entering
fullscreen.
2025-03-11 01:20:53 +00:00
Brezak
906d788420
Expand the RelationshipSourceCollection to return more information (#18241)
# Objective

While redoing #18058 I needed `RelationshipSourceCollection` (henceforth
referred to as the **Trait**) to implement `clear` so I added it.

## Solution

Add the `clear` method to the **Trait**.
Also make `add` and `remove` report if they succeeded.

## Testing

Eyeballs

---

## Showcase

The `RelationshipSourceCollection` trait now reports if adding or
removing an entity from it was successful.
It also not contains the `clear` method so you can easily clear the
collection in generic contexts.

## Changes

EDITED by Alice: We should get this into 0.16, so no migration guide
needed.

The `RelationshipSourceCollection` methods `add` and `remove` now need
to return a boolean indicating if they were successful (adding a entity
to a set that already contains it counts as failure). Additionally the
`clear` method has been added to support clearing the collection in
generic contexts.
2025-03-10 22:04:08 +00:00
BD103
e24191dd89
(Adoped) Remove panics and optimise mesh picking (#18232)
_Note from BD103: this PR was adopted from #16148. The majority of this
PR's description is copied from the original._

# Objective

Adds tests to cover various mesh picking cases and removes sources of
panics.

It should prevent users being able to trigger panics in `bevy_picking`
code via bad mesh data such as #15891, and is a follow up to my comments
in [#15800
(review)](https://github.com/bevyengine/bevy/pull/15800#pullrequestreview-2361694213).

This is motivated by #15979

## Testing

Adds 8 new tests to cover `ray_mesh_intersection` code.

## Changes from original PR

I reverted the changes to the benchmarks, since that was the largest
factor blocking it merging. I'll open a follow-up issue so that those
benchmark changes can be implemented.

---------

Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
2025-03-10 21:55:40 +00:00
Benjamin Brienen
690858166c
Fix mikkitspace typos (#18218)
# Objective

Correct spelling

## Solution

Fix 2 minor typos in crates/bevy_mikkitspace

## Testing

Doesn't change functional code
2025-03-10 21:53:00 +00:00
Matt Thompson
4e2dc4b15f
Add Saturation trait to bevy_color (#18202)
# Objective

- Allow for convenient access and mutation of color saturation providing
following the `Hue`, `Luminance` traits.

- `with_saturation()` builder method
- `saturation()` to get the saturation of a `Color`
- `set_saturation()` to set the saturation of a mutable `Color`

## Solution

- Defined `Saturation` trait in `color_ops.rs`
- Implemented `Saturation` on `Hsla` and `Hsva`
- Implemented `Saturation` on `Color` which proxies to other color space
impls.
- In the case of colorspaces which don't have native saturation
components
  the color is converted to 'Hsla` internally

## Testing

- Empirically tested
---

## Showcase

```rust
fn next_golden(&mut self) -> Color {
    self.current
        .rotate_hue((1.0 / GOLDEN_RATIO) * 360.0)
        .with_saturation(self.rand_saturation())
        .with_luminance(self.rand_luminance())
        .into()
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-10 21:52:04 +00:00
Eagster
65a9e6fd9f
Address Entities::len inconsistency (#18190)
# Objective

I was recently exploreing `Entities` and stumbled on something strange.
`Entities::len` (the field) has the comment `Stores the number of free
entities for [`len`](Entities::len)`, refering to the method. But that
method says `The count of currently allocated entities.` Looking at the
code, the field's comment is wrong, and the public `len()` is correct.
Phew!

## Solution

So, I was just going to fix the comment, so it didn't confuse anyone
else, but as it turns out, we can just remove the field entirely. As a
bonus, this saves some book keeping work too. We can just calculate it
on the fly.

Also, add additional length methods and documentation for completeness.
These new length methods might be useful debug tools in the future.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-03-10 21:51:01 +00:00
Eagster
21f003f13f
Improve component registration performance (#18180)
# Objective

Make component registration faster. This is a tinny, almost petty PR,
but it led to roughly 10% faster registration, according to my
benchmarks in #17871.

Up to y'all if we do this or not. It is completely unnecessary, but its
such low hanging fruit that I wanted to put it out there.

## Solution

Instead of cloning a `HashSet`, collect it into a `SmallVec`. Since this
is empty for many components, this saves a lot of allocation and hashing
work.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-10 21:49:07 +00:00
Eagster
246ce590e5
Queued component registration (#18173)
# Objective

This is an alternative to #17871 and #17701 for tracking issue #18155.
This thanks to @maniwani for help with this design.

The goal is to enable component ids to be reserved from multiple threads
concurrently and with only `&World`. This contributes to assets as
entities, read-only query and system parameter initialization, etc.

## What's wrong with #17871 ?

In #17871, I used my proposed staging utilities to allow *fully*
registering components from any thread concurrently with only
`&Components`. However, if we want to pursue components as entities
(which is desirable for a great many reasons. See
[here](https://discord.com/channels/691052431525675048/692572690833473578/1346499196655505534)
on discord), this staging isn't going to work. After all, if registering
a component requires spawning an entity, and spawning an entity requires
`&mut World`, it is impossible to register a component fully with only
`&World`.

## Solution

But what if we don't have to register it all the way? What if it's
enough to just know the `ComponentId` it will have once it is registered
and to queue it to be registered at a later time? Spoiler alert: That is
all we need for these features.

Here's the basic design:

Queue a registration:

1. Check if it has already been registered.
2. Check if it has already been queued.
3. Reserve a `ComponentId`.
4. Queue the registration at that id.

Direct (normal) registration:

1. Check if this registration has been queued.
2. If it has, use the queued registration instead.
3. Otherwise, proceed like normal.

Appllying the queue:

1. Pop queued items off one by one.
2. Register them directly.

One other change:

The whole point of this design over #17871 is to facilitate coupling
component registration with the World. To ensure that this would fully
work with that, I went ahead and moved the `ComponentId` generator onto
the world itself. That stemmed a couple of minor organizational changes
(see migration guide). As we do components as entities, we will replace
this generator with `Entities`, which lives on `World` too. Doing this
move early let me verify the design and will reduce migration headaches
in the future. If components as entities is as close as I think it is, I
don't think splitting this up into different PRs is worth it. If it is
not as close as it is, it might make sense to still do #17871 in the
meantime (see the risks section). I'll leave it up to y'all what we end
up doing though.

## Risks and Testing

The biggest downside of this compared to #17871 is that now we have to
deal with correct but invalid `ComponentId`s. They are invalid because
the component still isn't registered, but they are correct because, once
registered, the component will have exactly that id.

However, the only time this becomes a problem is if some code violates
safety rules by queuing a registration and using the returned id as if
it was valid. As this is a new feature though, nothing in Bevy does
this, so no new tests were added for it. When we do use it, I left
detailed docs to help mitigate issues here, and we can test those
usages. Ex: we will want some tests on using queries initialized from
queued registrations.

## Migration Guide

Component registration can now be queued with only `&World`. To
facilitate this, a few APIs needed to be moved around.

The following functions have moved from `Components` to
`ComponentsRegistrator`:

- `register_component`
- `register_component_with_descriptor`
- `register_resource_with_descriptor`
- `register_non_send`
- `register_resource`
- `register_required_components_manual`

Accordingly, functions in `Bundle` and `Component` now take
`ComponentsRegistrator` instead of `Components`.
You can obtain `ComponentsRegistrator` from the new
`World::components_registrator`.
You can obtain `ComponentsQueuedRegistrator` from the new
`World::components_queue`, and use it to stage component registration if
desired.

# Open Question

Can we verify that it is enough to queue registration with `&World`? I
don't think it would be too difficult to package this up into a
`Arc<MyComponentsManager>` type thing if we need to, but keeping this on
`&World` certainly simplifies things. If we do need the `Arc`, we'll
need to look into partitioning `Entities` for components as entities, so
we can keep most of the allocation fast on `World` and only keep a
smaller partition in the `Arc`. I'd love an SME on assets as entities to
shed some light on this.

---------

Co-authored-by: andriyDev <andriydzikh@gmail.com>
2025-03-10 21:46:27 +00:00
Patrick Walton
b46d9f0825
Make buffer binding arrays emit bind group layout entries and bindless resource descriptors again. (#18125)
PR #17965 mistakenly made the `AsBindGroup` macro no longer emit a bind
group layout entry and a resource descriptor for buffers. This commit
adds that functionality back, fixing the `shader_material_bindless`
example.

Closes #18124.
2025-03-10 21:40:24 +00:00
SpecificProtagonist
54247bcf86
Recursive run_system (#18076)
# Objective

Fixes #18030

## Solution

When running a one-shot system, requeue the system's command queue onto
the world's command queue, then execute the later.

If running the entire command queue of the world is undesired, I could
add a new method to `RawCommandQueue` to only apply part of it.

## Testing

See the new test.

---

## Showcase

```rust
#[derive(Resource)]
pub struct Test {
    id: SystemId,
    counter: u32,
}

let mut world = World::new();
let id = world.register_system(|mut commands: Commands, mut test: ResMut<Test>| {
    print!("{:?} ", test.counter);
    test.counter -= 1;
    if test.counter > 0 {
        commands.run_system(test.id);
    }
});
world.insert_resource(Test { id, counter: 5 });
world.run_system(id).unwrap();
```

```
5 4 3 2 1 
```
2025-03-10 21:38:36 +00:00
Eagster
79e7f8ae0c
Use register_dynamic for merging (#18028)
# Objective

I found a bug while working on #17871. When required components are
registered, ones that are more specific (smaller inheritance depth) are
preferred to others. So, if a ComponentA is already required, but it is
registered as required again, it will be updated if and only if the new
requirement has a smaller inheritance depth (is more specific). However,
this logic was not reflected in merging `RequriedComponents`s together.
Hence, for complicated requirement trees, the wrong initializer could be
used.

## Solution

Re-write merging to work by extending the collection via
`require_dynamic` instead of blindly combining the inner storage.

## Testing

I created this test to ensure this bug doesn't creep back in. This test
fails on main, but passes on this branch.

```rs
    #[test]
    fn required_components_inheritance_depth_bias() {
        #[derive(Component, PartialEq, Eq, Clone, Copy, Debug)]
        struct MyRequired(bool);

        #[derive(Component, Default)]
        #[require(MyRequired(|| MyRequired(false)))]
        struct MiddleMan;

        #[derive(Component, Default)]
        #[require(MiddleMan)]
        struct ConflictingRequire;

        #[derive(Component, Default)]
        #[require(MyRequired(|| MyRequired(true)))]
        struct MyComponent;

        let mut world = World::new();
        let order_a = world
            .spawn((ConflictingRequire, MyComponent))
            .get::<MyRequired>()
            .cloned();
        let order_b = world
            .spawn((MyComponent, ConflictingRequire))
            .get::<MyRequired>()
            .cloned();

        assert_eq!(order_a, Some(MyRequired(true)));
        assert_eq!(order_b, Some(MyRequired(true)));
    }
```
Note that when the inheritance depth is 0 (Like if there were no middle
man above), the order of the components in the bundle still matters.

## Migration Guide

`RequiredComponents::register_dynamic` has been changed to
`RequiredComponents::register_dynamic_with`.

Old:
```rust
required_components.register_dynamic(
      component_id,
      component_constructor.clone(),
      requirement_inheritance_depth,
);
```

New:
```rust
required_components.register_dynamic_with(
      component_id,
      requirement_inheritance_depth,
      || component_constructor.clone(),
);
```

This can prevent unnecessary cloning.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2025-03-10 21:35:55 +00:00
Patrick Walton
913eb46324
Reimplement bindless storage buffers. (#17994)
Support for bindless storage buffers was temporarily removed with the
bindless revamp. This commit restores that support.
2025-03-10 21:32:19 +00:00
Chris Russell
6df711ce7f
Fix unsound lifetimes in Query::join and Query::join_filtered (#17972)
# Objective

Fix unsound lifetimes in `Query::join` and `Query::join_filtered`.  

The joined query allowed access from either input query, but it only
took the `'world` lifetime from `self`, not from `other`. This meant
that after the borrow of `other` ended, the joined query would unsoundly
alias `other`.

## Solution

Change the lifetimes on `join` and `join_filtered` to require mutable
borrows of the *same* lifetime for the input queries. This ensures both
input queries are borrowed for the full lifetime of the joined query.

Change `join_inner` to take `other` by value instead of reference so
that the returned query is still usable without needing to borrow from a
local variable.

## Testing

Added a compile-fail test.
2025-03-10 21:30:34 +00:00
ickshonpe
a6144e3e5c
extract_text_shadows camera query fix (#17930)
# Objective

`extract_text_shadows` was still using `UiTargetCamera` and
`DefaultUiCamera` for UI camera resolution, which no longer always
selects the right camera.

To see this modify the last lines of the `multiple_windows` example
from:
```rust
    commands.spawn((
        Text::new("First window"),
        node.clone(),
        // Since we are using multiple cameras, we need to specify which camera UI should be rendered to
        UiTargetCamera(first_window_camera),
    ));

    commands.spawn((
        Text::new("Second window"),
        node,
        UiTargetCamera(second_window_camera),
    ));
```
to:
```rust
    commands
        .spawn((
            node.clone(),
            // Since we are using multiple cameras, we need to specify which camera UI should be rendered to
            UiTargetCamera(first_window_camera),
        ))
        .with_child((Text::new("First window"), TextShadow::default()));

    commands
        .spawn((node, UiTargetCamera(second_window_camera)))
        .with_child((Text::new("Second window"), TextShadow::default()));
```

which results in the shadow that is meant to be displayed for the
"Second Window" label instead being written over the first:

<img width="800" alt="first_window_label"
src="https://github.com/user-attachments/assets/2eebccba-5749-4064-bb1c-e4f25ff0baf7">

## Solution
Remove the `UiTargetCamera` query and the `default_camera` parameter
from `extract_text_shadows` and use `UiCameraMap` with
`ComputedNodeTarget` instead.

## Testing
The `multiple_windows` example for this PR has been updated to add text
shadow to the window labels. You should see that it displays the "Second
Window" label's shadow correctly now.
2025-03-10 21:22:14 +00:00
Johannes Ringler
683b08fec9
Respect viewport position in coordinate conversion functions (#17633)
# Objective

- In `Camera::viewport_to_world_2d`, `Camera::viewport_to_world`,
`Camera::world_to_viewport` and `Camera::world_to_viewport_with_depth`,
the results were incorrect when the `Camera::viewport` field was
configured with a viewport position that was non-zero. This PR attempts
to correct that.
- Fixes #16200 

## Solution

- This PR now takes the viewport position into account in the functions
mentioned above.
- Extended `2d_viewport_to_world` example to test the functions with a
dynamic viewport position and size, camera positions and zoom levels. It
is probably worth discussing whether to change the example, add a new
one or just completely skip touching the examples.

## Testing

Used the modified example to test the functions with dynamic camera
transform as well as dynamic viewport size and position.
2025-03-10 21:19:26 +00:00
Antonin Peronnet
b574599444
don't use bevy_pbr for base bevy_gizmos plugin (#17581)
# Objective

This PR enables `bevy_gizmos` to be used without `bevy_pbr`, for user
who want to create their custom mesh rendering logic.

It can also be useful for user who just want to use bevy for drawing
lines (why not).

This work is part of a bigger effort to make the bevy rendering pipeline
more modular. I would like to contribute an exemple to render custom
meshes without `bevy_pbr`. Something like
[this](https://github.com/rambip/plant-mesh/blob/main/src/shader/mod.rs)

## Solution

Now, `bevy_pbr` is an optional dependency, and used only to debug
lights.

I query the `ViewUniforms` manually, instead of using `bevy_pbr` to get
the heavy `MeshViewLayout`

## Testing

I'm not used to testing with bevy at all, but I was able to use
successfully in my project.
It might break for some different mesh pipelines, but I don't think so.

---

## Showcase


![image](https://github.com/user-attachments/assets/7fa22d1c-8b4f-456b-a74b-1a579449e9f5)
So nice ...

## Migration Guide

I don't think there is any breaking change


# Remaining work

Before merging it, it would be useful to:
- rewrite the `pipeline_2d.rs` logic to remove the `bevy_sprite`
depedency too
- move `view.rs` to `bevy_render`, so that it can be used in a more
modular way.
~~- include the most recent changes from 0.16~~

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-03-10 21:16:52 +00:00
SpecificProtagonist
cdef139710
Backtrace: std and threadsafe bevy_error_panic_hook (#18235)
# Objective

Make `bevy_error_panic_hook` threadsafe. As it relies on a global
variable, it fails when multiple threads panic.

## Solution

Switch from a global variable for storing whether an error message was
printed to a thread-local one.

`thread_local` is in `std`; the `backtrace` already relies on `std`
APIs. It didn't depend on the `std` feature though, so I've added that.
I've also put `bevy_error_panic_hook` behind the `backtrace` feature,
since it relies on the thread local variable, which fixes #18231.

## Testing

The following now loops instead of crashing:

```rust
std:🧵:scope(|s| {
    use bevy_ecs::error::*;

    #[derive(Debug)]
    struct E;
    impl std::fmt::Display for E {
        fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            todo!()
        }
    }
    impl std::error::Error for E {}

    std::panic::set_hook(Box::new(bevy_error_panic_hook(|_| {
        unreachable!();
    })));
    for _ in 0..2 {
        s.spawn(|| {
            loop {
                let _ = std::panic::catch_unwind(|| {
                    panic!("{:?}", BevyError::from(E));
                });
            }
        });
    }
});
```
2025-03-10 21:16:14 +00:00
Alix Bott
b054d116a6
Replace winit's synthetic events by our own key tracking (#14379)
# Objective

Defocusing a window while a key is held (such as when Alt+tabbing), will
currently send a key release on X11 and Windows. This is likely the
behavior that most people expect.
However it's synthetic events from winit are unimplemented for WASM and
some other platforms. (See
https://github.com/rust-windowing/winit/issues/1272).
While we can implement it upstream, there is also some doubt about the
synthetic events API as a whole
(https://github.com/rust-windowing/winit/issues/3543), so I propose to
do it in bevy directly for now.

## Solution

This PR implements key tracking in bevy directly so we can synthesize
our own key release events across all platforms.

Note regarding X11 specifically:
- On `main`, pressing a keyboard shortcut to unfocus the window (`Ctrl +
Super + ArrowRight` in my case) will yield the following events:
```
Pressed Control
Pressed Super
Released Control
Released ArrowRight
Released Super
```
- On this branch, it will yield the following sequence:
```
Pressed Control
Pressed Super
Released Control
Released Super
```
To me the behavior of this branch is more expected than `main`, because
`main` produces an `ArrowRight` release without producing a press first.

## Testing

Tested in WASM and X11 with
```rust
App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Update, |mut keys: EventReader<KeyboardInput>| {
            for ev in keys.read() {
                error!("received {ev:?}");
            }
        })
        .run();
```
2025-03-10 21:11:29 +00:00
dependabot[bot]
3b9e2e640f
Update petgraph requirement from 0.6 to 0.7 (#18224)
Updates the requirements on
[petgraph](https://github.com/petgraph/petgraph) to permit the latest
version.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/petgraph/petgraph/blob/master/RELEASES.rst">petgraph's
changelog</a>.</em></p>
<blockquote>
<h1>Version 0.7.1 (2025-01-08)</h1>
<ul>
<li>Do not unnecessarily restrict <code>indexmap</code> version
(<code>[#714](https://github.com/petgraph/petgraph/issues/714)</code>_)</li>
<li>Export <code>UndirectedAdaptor</code>
(<code>[#717](https://github.com/petgraph/petgraph/issues/717)</code>_)</li>
</ul>
<p>..
_<code>[#714](https://github.com/petgraph/petgraph/issues/714)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/714">petgraph/petgraph#714</a>
..
_<code>[#717](https://github.com/petgraph/petgraph/issues/717)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/717">petgraph/petgraph#717</a></p>
<h1>Version 0.7.0 (2024-12-31)</h1>
<ul>
<li>Re-released version 0.6.6 with the correct version number, as it
included a major update to an exposed crate
(<code>[#664](https://github.com/petgraph/petgraph/issues/664)</code>_).</li>
</ul>
<h1>Version 0.6.6 (2024-12-31 - yanked)</h1>
<ul>
<li>Add graph6 format encoder and decoder
(<code>[#658](https://github.com/petgraph/petgraph/issues/658)</code>_)</li>
<li>Dynamic Topological Sort algorithm support
(<code>[#675](https://github.com/petgraph/petgraph/issues/675)</code>_)</li>
<li>Add <code>UndirectedAdaptor</code>
(<code>[#695](https://github.com/petgraph/petgraph/issues/695)</code>_)</li>
<li>Add <code>LowerHex</code> and <code>UpperHex</code> implementations
for <code>Dot</code>
(<code>[#687](https://github.com/petgraph/petgraph/issues/687)</code>_)</li>
<li>Make <code>serde</code> support more complete
(<code>[#550](https://github.com/petgraph/petgraph/issues/550)</code>_)</li>
<li>Process multiple edges in the Floyd-Warshall implementation
(<code>[#685](https://github.com/petgraph/petgraph/issues/685)</code>_)</li>
<li>Update <code>fixedbitset</code> to 0.5.7
(<code>[#664](https://github.com/petgraph/petgraph/issues/664)</code>_)</li>
<li>Fix <code>immediately_dominated_by</code> function called on root of
graph returns root itself
(<code>[#670](https://github.com/petgraph/petgraph/issues/670)</code>_)</li>
<li>Fix adjacency matrix for <code>Csr</code> and <code>List</code>
(<code>[#648](https://github.com/petgraph/petgraph/issues/648)</code>_)</li>
<li>Fix clippy warnings
(<code>[#701](https://github.com/petgraph/petgraph/issues/701)</code>_)</li>
<li>Add performance note to the <code>all_simple_paths</code> function
documentation
(<code>[#693](https://github.com/petgraph/petgraph/issues/693)</code>_)</li>
</ul>
<p>..
_<code>[#658](https://github.com/petgraph/petgraph/issues/658)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/658">petgraph/petgraph#658</a>
..
_<code>[#675](https://github.com/petgraph/petgraph/issues/675)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/675">petgraph/petgraph#675</a>
..
_<code>[#695](https://github.com/petgraph/petgraph/issues/695)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/695">petgraph/petgraph#695</a>
..
_<code>[#687](https://github.com/petgraph/petgraph/issues/687)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/687">petgraph/petgraph#687</a>
..
_<code>[#550](https://github.com/petgraph/petgraph/issues/550)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/550">petgraph/petgraph#550</a>
..
_<code>[#685](https://github.com/petgraph/petgraph/issues/685)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/685">petgraph/petgraph#685</a>
..
_<code>[#664](https://github.com/petgraph/petgraph/issues/664)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/664">petgraph/petgraph#664</a>
..
_<code>[#670](https://github.com/petgraph/petgraph/issues/670)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/670">petgraph/petgraph#670</a>
..
_<code>[#648](https://github.com/petgraph/petgraph/issues/648)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/648">petgraph/petgraph#648</a>
..
_<code>[#701](https://github.com/petgraph/petgraph/issues/701)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/701">petgraph/petgraph#701</a>
..
_<code>[#693](https://github.com/petgraph/petgraph/issues/693)</code>:
<a
href="https://redirect.github.com/petgraph/petgraph/pull/693">petgraph/petgraph#693</a></p>
<h1>Version 0.6.5 (2024-05-06)</h1>
<ul>
<li>Add rayon support for <code>GraphMap</code>
(<code>[#573](https://github.com/petgraph/petgraph/issues/573)</code><em>,
<code>[#615](https://github.com/petgraph/petgraph/issues/615)</code></em>)</li>
<li>Add <code>Topo::with_initials</code> method
(<code>[#585](https://github.com/petgraph/petgraph/issues/585)</code>_)</li>
<li>Add logo to the project
(<code>[#598](https://github.com/petgraph/petgraph/issues/598)</code>_)</li>
<li>Add Ford-Fulkerson algorithm
(<code>[#640](https://github.com/petgraph/petgraph/issues/640)</code>_)</li>
<li>Update <code>itertools</code> to 0.12.1
(<code>[#628](https://github.com/petgraph/petgraph/issues/628)</code>_)</li>
<li>Update <code>GraphMap</code> to allow custom hash functions
(<code>[#622](https://github.com/petgraph/petgraph/issues/622)</code>_)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2765d2a550"><code>2765d2a</code></a>
Release 0.7.1 (<a
href="https://redirect.github.com/petgraph/petgraph/issues/722">#722</a>)</li>
<li><a
href="d341db9d18"><code>d341db9</code></a>
ci: downgrade hashbrown rather than limiting indexmap (<a
href="https://redirect.github.com/petgraph/petgraph/issues/714">#714</a>)</li>
<li><a
href="73c64b629f"><code>73c64b6</code></a>
Make UndirectedAdaptor &amp; inner G pub (<a
href="https://redirect.github.com/petgraph/petgraph/issues/717">#717</a>)</li>
<li><a
href="d057429081"><code>d057429</code></a>
Release <code>0.7.0</code> (<a
href="https://redirect.github.com/petgraph/petgraph/issues/713">#713</a>)</li>
<li><a
href="13ebd7d2dd"><code>13ebd7d</code></a>
Release <code>0.6.6</code> (<a
href="https://redirect.github.com/petgraph/petgraph/issues/706">#706</a>)</li>
<li><a
href="159341e4af"><code>159341e</code></a>
Implement DSatur graph coloring algorithm</li>
<li><a
href="7fa3aac971"><code>7fa3aac</code></a>
fix: adjacency matrix for csr and adjacency list (<a
href="https://redirect.github.com/petgraph/petgraph/issues/648">#648</a>)</li>
<li><a
href="9fda6bbe2e"><code>9fda6bb</code></a>
Update gitignore with possible editor extensions to ensure they do not
occur ...</li>
<li><a
href="9b5837e395"><code>9b5837e</code></a>
Allow clippy::needless_range_loop in benches</li>
<li><a
href="ad9f83c2ae"><code>ad9f83c</code></a>
Process warnings in 'test' target</li>
<li>Additional commits viewable in <a
href="https://github.com/petgraph/petgraph/compare/petgraph@v0.6.0...petgraph@v0.7.1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 07:12:27 +00:00
Brian Reavis
dacb77d745
Parallelize prepare_assets::<T> systems (#17914)
# Objective

Because `prepare_assets::<T>` had a mutable reference to the
`RenderAssetBytesPerFrame` resource, no render asset preparation could
happen in parallel. This PR fixes this by using an `AtomicUsize` to
count bytes written (if there's a limit in place), so that the system
doesn't need mutable access.

- Related: https://github.com/bevyengine/bevy/pull/12622

**Before**
<img width="1049" alt="Screenshot 2025-02-17 at 11 40 53 AM"
src="https://github.com/user-attachments/assets/040e6184-1192-4368-9597-5ceda4b8251b"
/>

**After**
<img width="836" alt="Screenshot 2025-02-17 at 1 38 37 PM"
src="https://github.com/user-attachments/assets/95488796-3323-425c-b0a6-4cf17753512e"
/>

## Testing

- Tested on a local project (with and without limiting enabled)
- Someone with more knowledge of wgpu/underlying driver guts should
confirm that this doesn't actually bite us by introducing contention
(i.e. if buffer writing really *should be* serial).
2025-03-10 05:01:12 +00:00
ickshonpe
8980be997e
UiTargetCamera doc comment correction (#18216)
# Objective

As pointed out in #18177 this line in the doc comment for
`UiTargetCamera`:

```
/// Optional if there is only one camera in the world. Required otherwise.
```

Is incorrect, `UiTargetCamera` component is only needed when you want to
display UI nodes using a camera other than the default camera.

## Solution

Change it to:
```
/// Root node's without an explicit [`UiTargetCamera`] will be rendered to the default UI camera,
/// which is either a single camera with the [`IsDefaultUiCamera`] marker component or the highest
/// order camera targeting the primary window.
```
2025-03-09 22:48:52 +00:00
JMS55
bb1616a212
Decoupled naga for wgpu testing (#18099)
# Objective
- Allow bevy and wgpu developers to test newer versions of wgpu without
having to update naga_oil.

## Solution

- Currently bevy feeds wgsl through naga_oil to get a naga::Module that
it passes to wgpu.
- Added a way to pass wgsl through naga_oil, and then serialize the
naga::Module back into a wgsl string to feed to wgpu, allowing wgpu to
parse it using it's internal version of naga (and not the version of
naga bevy_render/naga_oil is using).

## Testing
1. Run 3d_scene (it works)
2. Run 3d_scene with `--features bevy_render/decoupled_naga` (it still
works)
3. Add the following patch to bevy/Cargo.toml, run cargo update, and
compile again (it will fail)
```toml
[patch.crates-io]
wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "2764e7a39920e23928d300e8856a672f1952da63" }
wgpu-core = { git = "https://github.com/gfx-rs/wgpu", rev = "2764e7a39920e23928d300e8856a672f1952da63" }
wgpu-hal = { git = "https://github.com/gfx-rs/wgpu", rev = "2764e7a39920e23928d300e8856a672f1952da63" }
wgpu-types = { git = "https://github.com/gfx-rs/wgpu", rev = "2764e7a39920e23928d300e8856a672f1952da63" }
```
4. Fix errors and compile again (it will work, and you didn't have to
touch naga_oil)
2025-03-09 21:49:48 +00:00
Joona Aalto
9f6d628c48
Improve Segment2d/Segment3d API and docs (#18206)
# Objective

#17404 reworked the `Segment2d` and `Segment3d` types to be defined by
two endpoints rather than a direction and half-length. However, the API
is still very minimal and limited, and documentation is inconsistent and
outdated.

## Solution

Add the following helper methods for `Segment2d` and `Segment3d`:

- `from_scaled_direction`
- `from_ray_and_length`
- `length_squared`
- `direction`
- `try_direction`
- `scaled_direction`
- `transformed`
- `reversed`

`Segment2d` has a few 2D-specific methods:

- `left_normal`
- `try_left_normal`
- `scaled_left_normal`
- `right_normal`
- `try_right_normal`
- `scaled_right_normal`

There are now also `From` implementations for converting `[Vec2; 2]` and
`(Vec2, Vec2)` to a `Segment2d`, and similarly for 3D.

I have also updated documentation to be more accurate and consistent,
and simplified a few methods.

---

## Prior Art

Parry's
[`Segment`](https://docs.rs/parry2d/latest/parry2d/shape/struct.Segment.html)
type has a lot of similar methods, though my implementation is a bit
more comprehensive. A lot of these methods can be useful for various
geometry algorithms.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
2025-03-09 20:21:31 +00:00
Greeble
09ff7ce9f6
Partially fix panics when setting WGPU_SETTINGS_PRIO=webgl2 (#18113)
# Overview

Fixes https://github.com/bevyengine/bevy/issues/17869.

# Summary

`WGPU_SETTINGS_PRIO` changes various limits on `RenderDevice`. This is
useful to simulate platforms with lower limits.

However, some plugins only check the limits on `RenderAdapter` (the
actual GPU) - these limits are not affected by `WGPU_SETTINGS_PRIO`. So
the plugins try to use features that are unavailable and wgpu says "oh
no". See https://github.com/bevyengine/bevy/issues/17869 for details.

The PR adds various checks on `RenderDevice` limits. This is enough to
get most examples working, but some are not fixed (see below).

# Testing

- Tested native, with and without "WGPU_SETTINGS=webgl2".
Win10/Vulkan/Nvidia".
- Also WebGL. Win10/Chrome/Nvidia.

```
$env:WGPU_SETTINGS_PRIO = "webgl2"
cargo run --example testbed_3d
cargo run --example testbed_2d
cargo run --example testbed_ui
cargo run --example deferred_rendering
cargo run --example many_lights
cargo run --example order_independent_transparency # Still broken, see below.
cargo run --example occlusion_culling # Still broken, see below.
```

# Not Fixed

While testing I found a few other cases of limits being broken. 

"Compatibility" settings (WebGPU minimums) breaks native in various
examples.

```
$env:WGPU_SETTINGS_PRIO = "compatibility"
cargo run --example testbed_3d

  In Device::create_bind_group_layout, label = 'build mesh uniforms GPU early occlusion culling bind group layout'
    Too many bindings of type StorageBuffers in Stage ShaderStages(COMPUTE), limit is 8, count was 9. Check the limit `max_storage_buffers_per_shader_stage` passed to `Adapter::request_device`
```

`occlusion_culling` breaks fake webgl.
```
$env:WGPU_SETTINGS_PRIO = "webgl2"
cargo run --example occlusion_culling

thread '<unnamed>' panicked at C:\Projects\bevy\crates\bevy_render\src\render_resource\pipeline_cache.rs:555:28:
index out of bounds: the len is 0 but the index is 2
Encountered a panic in system `bevy_render::renderer::render_system`!
```

`occlusion_culling` breaks real webgl.

```
cargo run --example occlusion_culling --target wasm32-unknown-unknown

ERROR app: panicked at C:\Users\T\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\glow-0.16.0\src\web_sys.rs:4223:9:
Tex storage 2D multisample is not supported
```

OIT breaks fake webgl.

```
$env:WGPU_SETTINGS_PRIO = "webgl2"
cargo run --example order_independent_transparency

  In Device::create_bind_group, label = 'mesh_view_bind_group'
    Number of bindings in bind group descriptor (28) does not match the number of bindings defined in the bind group layout (25)

```

OIT breaks real webgl

```
cargo run --example order_independent_transparency --target wasm32-unknown-unknown

  In Device::create_render_pipeline, label = 'pbr_oit_mesh_pipeline'
    Error matching ShaderStages(FRAGMENT) shader requirements against the pipeline
      Shader global ResourceBinding { group: 0, binding: 34 } is not available in the pipeline layout
        Binding is missing from the pipeline layout
```
2025-03-09 20:14:27 +00:00
Zachary Harrold
cbc931723e
Remove lifetime from QueryEntityError (#18157)
# Objective

- Allow `Query` methods such as `Query::get` to have their error
short-circuited using `?` in systems using Bevy's `Error` type

## Solution

- Removed `UnsafeWorldCell<'w>` from `QueryEntityError` and instead
store `ArchetypeId` (the information the error formatter was extracting
anyway).
- Replaced trait implementations with derives now that the type is
plain-old-data.

## Testing

- CI

---

## Migration Guide

- `QueryEntityError::QueryDoesNotMatch.1` is of type `ArchetypeId`
instead of `UnsafeWorldCell`. It is up to the caller to obtain an
`UnsafeWorldCell` now.
- `QueryEntityError` no longer has a lifetime parameter, remove it from
type signatures where required.

## Notes

This was discussed on Discord and accepted by Cart as the desirable path
forward in [this
message](https://discord.com/channels/691052431525675048/749335865876021248/1346611950527713310).
Scroll up from this point for context.

---------

Co-authored-by: SpecificProtagonist <30270112+SpecificProtagonist@users.noreply.github.com>
2025-03-09 20:05:22 +00:00
Aevyrie
f22d93c90f
Transform Propagation Optimization: Static Subtree Marking (#18093)
# Objective

- Optimize static scene performance by marking unchanged subtrees.

## Solution

- Mark hierarchy subtrees with dirty bits to avoid transform propagation
where not needed
- This causes a performance regression when spawning many entities, or
when the scene is entirely dynamic.
- This results in massive speedups for largely static scenes.
- In the future we could allow the user to change this behavior, or add
some threshold based on how dynamic the scene is?

## Testing

- Caldera Hotel scene
2025-03-09 19:29:01 +00:00
charlotte
181445c56b
Add support for experimental WESL shader source (#17953)
# Objective

WESL's pre-MVP `0.1.0` has been
[released](https://docs.rs/wesl/latest/wesl/)!

Add support for WESL shader source so that we can begin playing and
testing WESL, as well as aiding in their development.

## Solution

Adds a `ShaderSource::WESL` that can be used to load `.wesl` shaders.

Right now, we don't support mixing `naga-oil`. Additionally, WESL
shaders currently need to pass through the naga frontend, which the WESL
team is aware isn't great for performance (they're working on compiling
into naga modules). Also, since our shaders are managed using the asset
system, we don't currently support using file based imports like `super`
or package scoped imports. Further work will be needed to asses how we
want to support this.

---

## Showcase

See the `shader_material_wesl` example. Be sure to press space to
activate party mode (trigger conditional compilation)!


https://github.com/user-attachments/assets/ec6ad19f-b6e4-4e9d-a00f-6f09336b08a4
2025-03-09 19:26:55 +00:00
Zachary Harrold
c14733d177
Ensure bevy_utils is included with std feature (#18201)
# Objective

- Fixes #18200

## Solution

- Ensure `bevy_utils` is included with `bevy_transform/std`

## Testing

- `cargo build  --no-default-features --features std`

## Notes

Compilation failure was caused by `bevy_transform`'s new parallel
propagation system requiring `bevy_utils/std` when `bevy_transform/std`
was active, but it was left optional. Additionally,
`bevy_transform/async_executor` wasn't being enabled by
`bevy/async_executor`.
2025-03-08 21:51:51 +00:00
sam edelsten
64d57fad08
Add byte information to PositionedGlyph (#17900)
# Objective

Adds information about the byte length and index of a glyph to
`PositionedGlyph`. Useful for text picking, allows for picking with
multi-byte characters. Also adds a `line` field that helps with
converting back and forth from cosmic's `Cursor`.

## Solution

Retrieve the relevant data from cosmic and add it to the glyph in the
text pipeline.

## Testing

`cargo r -p ci`

---

## Migration Guide

`PositionedGlyph::new()` has been removed as there is no longer an
unused field. Create new `PositionedGlyph`s directly.
2025-03-08 16:35:01 +00:00
krunchington
ab38b61001
Update Component docs to point to Relationship trait (#18179)
also updates Relationship docs terminology

# Objective

- Contributes to #18111 

## Solution

Updates Component docs with a new section linking to Relationship. Also
updates some Relationship terminology as I understand it.

## Testing

- Did you test these changes? If so, how?
  - opened Docs, verified link
- Are there any parts that need more testing?
  - I don't think so
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- run `cargo doc --open` and check out Component and Relationship docs,
verify their correctness
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - I think this is n/a but I ran the doc command on Ubuntu 24.04.2 LTS

---

## Showcase


![image](https://github.com/user-attachments/assets/241eecb2-dd98-43ab-875a-1a3ec1176a79)


## Migration Guide

n/a
2025-03-07 23:32:43 +00:00
Zachary Harrold
c6204279eb
Support for non-browser wasm (#17499)
# Objective

- Contributes to #15460
- Supersedes #8520
- Fixes #4906

## Solution

- Added a new `web` feature to `bevy`, and several of its crates.
- Enabled new `web` feature automatically within crates without `no_std`
support.

## Testing

- `cargo build --no-default-features --target wasm32v1-none`

---

## Migration Guide

When using Bevy crates which _don't_ automatically enable the `web`
feature, please enable it when building for the browser.

## Notes

- I added [`cfg_if`](https://crates.io/crates/cfg-if) to help manage
some of the feature gate gore that this extra feature introduces. It's
still pretty ugly, but I think much easier to read.
- Certain `wasm` targets (e.g.,
[wasm32-wasip1](https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-wasip1.html#wasm32-wasip1))
provide an incomplete implementation for `std`. I have not tested these
platforms, but I suspect Bevy's liberal use of usually unsupported
features (e.g., threading) will cause these targets to fail. As such,
consider `wasm32-unknown-unknown` as the only `wasm` platform with
support from Bevy for `std`. All others likely will need to be treated
as `no_std` platforms.
2025-03-07 21:22:28 +00:00
aloucks
edba54adac
Fix mesh tangent attribute matching in mesh transform operations (#17992)
Fixes #17170

# Objective

Tangents are not currently transformed as described in #17170. I came
across this while working on #17989 and it seemed like low hanging
fruit.
2025-03-07 17:39:42 +00:00
Zachary Harrold
cc69fdd0c6
Add no_std support to bevy (#17955)
# Objective

- Fixes #15460 (will open new issues for further `no_std` efforts)
- Supersedes #17715

## Solution

- Threaded in new features as required
- Made certain crates optional but default enabled
- Removed `compile-check-no-std` from internal `ci` tool since GitHub CI
can now simply check `bevy` itself now
- Added CI task to check `bevy` on `thumbv6m-none-eabi` to ensure
`portable-atomic` support is still valid [^1]

[^1]: This may be controversial, since it could be interpreted as
implying Bevy will maintain support for `thumbv6m-none-eabi` going
forward. In reality, just like `x86_64-unknown-none`, this is a
[canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine) target to
make it clear when `portable-atomic` no longer works as intended (fixing
atomic support on atomically challenged platforms). If a PR comes
through and makes supporting this class of platforms impossible, then
this CI task can be removed. I however wager this won't be a problem.

## Testing

- CI

---

## Release Notes

Bevy now has support for `no_std` directly from the `bevy` crate.

Users can disable default features and enable a new `default_no_std`
feature instead, allowing `bevy` to be used in `no_std` applications and
libraries.

```toml
# Bevy for `no_std` platforms
bevy = { version = "0.16", default-features = false, features = ["default_no_std"] }
```

`default_no_std` enables certain required features, such as `libm` and
`critical-section`, and as many optional crates as possible (currently
just `bevy_state`). For atomically-challenged platforms such as the
Raspberry Pi Pico, `portable-atomic` will be used automatically.

For library authors, we recommend depending on `bevy` with
`default-features = false` to allow `std` and `no_std` users to both
depend on your crate. Here are some recommended features a library crate
may want to expose:

```toml
[features]
# Most users will be on a platform which has `std` and can use the more-powerful `async_executor`.
default = ["std", "async_executor"]

# Features for typical platforms.
std = ["bevy/std"]
async_executor = ["bevy/async_executor"]

# Features for `no_std` platforms.
libm = ["bevy/libm"]
critical-section = ["bevy/critical-section"]

[dependencies]
# We disable default features to ensure we don't accidentally enable `std` on `no_std` targets, for example. 
bevy = { version = "0.16", default-features = false }
```

While this is verbose, it gives the maximum control to end-users to
decide how they wish to use Bevy on their platform.

We encourage library authors to experiment with `no_std` support. For
libraries relying exclusively on `bevy` and no other dependencies, it
may be as simple as adding `#![no_std]` to your `lib.rs` and exposing
features as above! Bevy can also provide many `std` types, such as
`HashMap`, `Mutex`, and `Instant` on all platforms. See
`bevy::platform_support` for details on what's available out of the box!

## Migration Guide

- If you were previously relying on `bevy` with default features
disabled, you may need to enable the `std` and `async_executor`
features.
- `bevy_reflect` has had its `bevy` feature removed. If you were relying
on this feature, simply enable `smallvec` and `smol_str` instead.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-07 03:39:46 +00:00
Alice Cecile
5bc1d68a65
Deprecated Query::many and many_mut (#18183)
# Objective

Alternative to and closes #18120.

Sibling to #18082, see that PR for broader reasoning.

Folks weren't sold on the name `many` (get_many is clearer, and this is
rare), and that PR is much more complex.

## Solution

- Simply deprecate `Query::many` and `Query::many_mut`
- Clean up internal usages

Mentions of this in the docs can wait until it's fully removed in the
0.17 cycle IMO: it's much easier to catch the problems when doing that.

## Testing

CI!

## Migration Guide

`Query::many` and `Query::many_mut` have been deprecated to reduce
panics and API duplication. Use `Query::get_many` and
`Query::get_many_mut` instead, and handle the `Result`.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-03-07 02:10:32 +00:00
Tim Overbeek
664000f848
Improve derive(Event) and simplify macro code (#18083)
# Objective

simplify some code and improve Event macro

Closes https://github.com/bevyengine/bevy/issues/14336,


# Showcase

you can now write derive Events like so
```rust
#[derive(event)]
#[event(auto_propagate, traversal = MyType)]
struct MyEvent;
```
2025-03-07 02:01:23 +00:00
copygirl
6cd98b38b9
Add TextureAtlasSources::uv_rect to get Rect in UV coords (#18178)
# Objective

I'm building a bloxel game in which I (currently) use a texture atlas to
render the blocks the world is made of. While I was coding it, I was
using the `TextureAtlas...` types to build the terrain's texture atlas
at runtime as shown in the
[example](https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs).
But when I was using it to build a 3D mesh out of the blocks, I found
that there was no easy way get the texture rect in UV coordinates, only
in pixels via `texture_rect()`. I had to resort to writing code like
this:

```rs
let size = layout.size.as_vec2();
if let Some(rect) = sources.texture_rect(layout, texture) {
    let rect = rect.as_rect();
    let uvs = Rect::from_corners(rect.min / size, rect.max / size);
    // use the UVs here, such as to build vertex buffer
}
```

That is, until I wrote a helper function that's practically identical to
the one in this PR.

## Solution

Add a `uv_rect` function to `TextureAtlasSources` that will return a
`Rect` with coordinates in the range of 0.0 to 1.0 – that is, UV
coordinates – which can then be used directly to build `Vec2` UV values
to put into a buffer and send to the GPU.

I'm a little unsure about the wording of the `texture_rect`
documentation but I kept it intact and based mine on it. If you think
this could be improved and have some advice, I'd love to include that in
this PR.

## Testing

I've not done any testing with the updated bevy branch, other than
seeing that the original helper function (identical in functionality)
worked in my currently very small project, and making sure `cargo build`
doesn't error, but I'm new to making changes to Bevy so unsure if this
is sufficient.

## Showcase


![image](https://github.com/user-attachments/assets/a6d25608-e4ea-4cfd-ba1f-911dc4430138)
2025-03-07 01:59:45 +00:00
Carter Anderson
cca5813472
BevyError: Bevy's new catch-all error type (#18144)
## Objective

Fixes #18092

Bevy's current error type is a simple type alias for `Box<dyn Error +
Send + Sync + 'static>`. This largely works as a catch-all error, but it
is missing a critical feature: the ability to capture a backtrace at the
point that the error occurs. The best way to do this is `anyhow`-style
error handling: a new error type that takes advantage of the fact that
the `?` `From` conversion happens "inline" to capture the backtrace at
the point of the error.

## Solution

This PR adds a new `BevyError` type (replacing our old
`std::error::Error` type alias), which uses the "from conversion
backtrace capture" approach:

```rust
fn oh_no() -> Result<(), BevyError> {
    // this fails with Rust's built in ParseIntError, which
    // is converted into the catch-all BevyError type
    let number: usize = "hi".parse()?;
    println!("parsed {number}");
    Ok(())
}
```

This also updates our exported `Result` type alias to default to
`BevyError`, meaning you can write this instead:

```rust
fn oh_no() -> Result {
    let number: usize = "hi".parse()?;
    println!("parsed {number}");
    Ok(())
}
```

When a BevyError is encountered in a system, it will use Bevy's default
system error handler (which panics by default). BevyError does custom
"backtrace filtering" by default, meaning we can cut out the _massive_
amount of "rust internals", "async executor internals", and "bevy system
scheduler internals" that show up in backtraces. It also trims out the
first generally-unnecssary `From` conversion backtrace lines that make
it harder to locate the real error location. The result is a blissfully
simple backtrace by default:


![image](https://github.com/user-attachments/assets/7a5f5c9b-ea70-4176-af3b-d231da31c967)

The full backtrace can be shown by setting the `BEVY_BACKTRACE=full`
environment variable. Non-BevyError panics still use the default Rust
backtrace behavior.

One issue that prevented the truly noise-free backtrace during panics
that you see above is that Rust's default panic handler will print the
unfiltered (and largely unhelpful real-panic-point) backtrace by
default, in _addition_ to our filtered BevyError backtrace (with the
helpful backtrace origin) that we capture and print. To resolve this, I
have extended Bevy's existing PanicHandlerPlugin to wrap the default
panic handler. If we panic from the result of a BevyError, we will skip
the default "print full backtrace" panic handler. This behavior can be
enabled and disabled using the new `error_panic_hook` cargo feature in
`bevy_app` (which is enabled by default).

One downside to _not_ using `Box<dyn Error>` directly is that we can no
longer take advantage of the built-in `Into` impl for strings to errors.
To resolve this, I have added the following:

```rust
// Before
Err("some error")?

// After
Err(BevyError::message("some error"))?
```

We can discuss adding shorthand methods or macros for this (similar to
anyhow's `anyhow!("some error")` macro), but I'd prefer to discuss that
later.

I have also added the following extension method:

```rust
// Before
some_option.ok_or("some error")?;

// After
some_option.ok_or_message("some error")?;
```

I've also moved all of our existing error infrastructure from
`bevy_ecs::result` to `bevy_ecs::error`, as I think that is the better
home for it

## Why not anyhow (or eyre)?

The biggest reason is that `anyhow` needs to be a "generically useful
error type", whereas Bevy is a much narrower scope. By using our own
error, we can be significantly more opinionated. For example, anyhow
doesn't do the extensive (and invasive) backtrace filtering that
BevyError does because it can't operate on Bevy-specific context, and
needs to be generically useful.

Bevy also has a lot of operational context (ex: system info) that could
be useful to attach to errors. If we have control over the error type,
we can add whatever context we want to in a structured way. This could
be increasingly useful as we add more visual / interactive error
handling tools and editor integrations.

Additionally, the core approach used is simple and requires almost no
code. anyhow clocks in at ~2500 lines of code, but the impl here uses
160. We are able to boil this down to exactly what we need, and by doing
so we improve our compile times and the understandability of our code.
2025-03-07 01:50:07 +00:00
aloucks
19ee692f96
Prevent an additional world update after all windows have closed on Windows (#18175)
# Objective

The fix in #18105 includes a check for running headless, but this allows
for an extra world update during shutdown.

This commit checks if the `AppExit` event has been recorded and prevents
the additional world update.

### Before

```
2025-03-06T03:11:59.999679Z  INFO bevy_window::system: No windows are open, exiting    
2025-03-06T03:12:00.001942Z  INFO bevy_winit::system: Closing window 0v1
2025-03-06T03:12:00.012691Z  INFO bevy_window::system: No windows are open, exiting
```
### After

```
2025-03-06T03:18:45.552243Z  INFO bevy_window::system: No windows are open, exiting    
2025-03-06T03:18:45.554119Z  INFO bevy_winit::system: Closing window 0v1
```
## Testing

Ran `window` examples

- `monitor_info` continues to run after all windows are closed (it has
`ExitCondition::DontExit`)
- `window_settings` invisible window creation works as expected
- `multiple_windows` exits after both windows are closed with a single
exit message
2025-03-06 21:13:18 +00:00
andriyDev
d8f3eb3e8b
Stop automatically generating meta files for assets while using asset processing. (#17216)
# Objective

- Today, enabling asset processing can generate many meta files. This
makes it a painful transition for users as they get a "mega commit"
containing tons of meta files.

## Solution

- Stop automatically generating meta files! Users can just leave the
meta files defaulted.
- Add a function `AssetServer::write_default_meta_file_for_path`

## Testing

- Tested this manually on the asset_processing example (by removing the
meta files for the assets that had default meta files).
- I did not add a unit test for the `write_default_meta_file_for_path`
since we don't have an in-memory asset writer. Writing one could be
useful in the future.

---

## Showcase

Asset processing no longer automatically generates meta files! This
makes it much easier to transition to using asset processing since you
don't suddenly get many meta files when turning it on.

You can still manually generate meta files using the new
`AssetServer::write_default_meta_file_for_path` function.
2025-03-06 20:25:40 +00:00
Eagster
ed7b366b24
Deprecate insert_or_spawn function family (#18147)
# Objective

Based on #18054, this PR builds on #18035 to deprecate:

- `Commands::insert_or_spawn_batch`
- `Entities::alloc_at_without_replacement`
- `Entities::alloc_at`
- `World::insert_or_spawn_batch`
- `World::insert_or_spawn_batch_with_caller`

## Testing

Just deprecation, so no new tests. Note that as of writing #18035 is
still under testing and review.

## Open Questions

- [x] Should `entity::AllocAtWithoutReplacement` be deprecated? It is
internal and only used in `Entities::alloc_at_without_replacement`.
**EDIT:** Now deprecated.

## Migration Guide

The following functions have been deprecated:

- `Commands::insert_or_spawn_batch`
- `World::insert_or_spawn_batch`
- `World::insert_or_spawn_batch_with_caller`

These functions, when used incorrectly, can cause major performance
problems and are generally viewed as anti-patterns and foot guns. These
are planned to be removed altogether in 0.17.

Instead of these functions consider doing one of the following:

Option A) Instead of despawing entities and re-spawning them at a
particular id, insert the new `Disabled` component without despawning
the entity, and use `try_insert_batch` or `insert_batch` and remove
`Disabled` instead of re-spawning it.

Option B) Instead of giving special meaning to an entity id, simply use
`spawn_batch` and ensure entity references are valid when despawning.

---------

Co-authored-by: JaySpruce <jsprucebruce@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-03-06 17:04:16 +00:00
Jak Kos
47509ef6a9
Helper function for getting inverse model matrix in WGSL shaders (#10462)
In 0.11 you could easily access the inverse model matrix inside a WGSL
shader with `transpose(mesh.inverse_transpose_model)`. This was changed
in 0.12 when `inverse_transpose_model` was removed and it's now not as
straightfoward. I wrote a helper function for my own code and thought
I'd submit a pull request in case it would be helpful to others.
2025-03-06 16:43:22 +00:00
RobWalt
a85a3a2a15
allow Call and Closure expressions in hook macro attributes (#18017)
# Objective

This PR adds:

- function call hook attributes `#[component(on_add = func(42))]`
  - main feature of this commit
- closure hook attributes `#[component(on_add = |w, ctx| { /* ... */
})]`
  - maybe too verbose
  - but was easy to add
  - was suggested on discord

This allows to reuse common functionality without replicating a lot of
boilerplate. A small example is a hook which just adds different default
sprites. The sprite loading code would be the same for every component.
Unfortunately we can't use the required components feature, since we
need at least an `AssetServer` or other `Resource`s or `Component`s to
load the sprite.

```rs
fn load_sprite(path: &str) -> impl Fn(DeferredWorld, HookContext) {
  |mut world, ctx| {
    // ... use world to load sprite
  }
}

#[derive(Component)]
#[component(on_add = load_sprite("knight.png"))]
struct Knight;

#[derive(Component)]
#[component(on_add = load_sprite("monster.png"))]
struct Monster;
```

---

The commit also reorders the logic of the derive macro a bit. It's
probably a bit less lazy now, but the functionality shouldn't be
performance critical and is executed at compile time anyways.

## Solution

- Introduce `HookKind` enum in the component proc macro module
- extend parsing to allow more cases of expressions

## Testing

I have some code laying around. I'm not sure where to put it yet though.
Also is there a way to check compilation failures? Anyways, here it is:

```rs
use bevy::prelude::*;

#[derive(Component)]
#[component(
    on_add = fooing_and_baring,
    on_insert = fooing_and_baring,
    on_replace = fooing_and_baring,
    on_despawn = fooing_and_baring,
    on_remove = fooing_and_baring
)]
pub struct FooPath;

fn fooing_and_baring(
    world: bevy::ecs::world::DeferredWorld,
    ctx: bevy::ecs::component::HookContext,
) {
}

#[derive(Component)]
#[component(
    on_add = baring_and_bazzing("foo"),
    on_insert = baring_and_bazzing("foo"),
    on_replace = baring_and_bazzing("foo"),
    on_despawn = baring_and_bazzing("foo"),
    on_remove = baring_and_bazzing("foo")
)]
pub struct FooCall;

fn baring_and_bazzing(
    path: &str,
) -> impl Fn(bevy::ecs::world::DeferredWorld, bevy::ecs::component::HookContext) {
    |world, ctx| {}
}

#[derive(Component)]
#[component(
    on_add = |w,ctx| {},
    on_insert = |w,ctx| {},
    on_replace = |w,ctx| {},
    on_despawn = |w,ctx| {},
    on_remove = |w,ctx| {}
)]
pub struct FooClosure;

#[derive(Component, Debug)]
#[relationship(relationship_target = FooTargets)]
#[component(
    on_add = baring_and_bazzing("foo"),
    // on_insert = baring_and_bazzing("foo"),
    // on_replace = baring_and_bazzing("foo"),
    on_despawn = baring_and_bazzing("foo"),
    on_remove = baring_and_bazzing("foo")
)]
pub struct FooTargetOf(Entity);

#[derive(Component, Debug)]
#[relationship_target(relationship = FooTargetOf)]
#[component(
    on_add = |w,ctx| {},
    on_insert = |w,ctx| {},
    // on_replace = |w,ctx| {},
    // on_despawn = |w,ctx| {},
    on_remove = |w,ctx| {}
)]
pub struct FooTargets(Vec<Entity>);

// MSG:  mismatched types  expected fn pointer `for<'w> fn(bevy::bevy_ecs::world::DeferredWorld<'w>, bevy::bevy_ecs::component::HookContext)`    found struct `Bar`
//
// pub struct Bar;
// #[derive(Component)]
// #[component(
//     on_add = Bar,
// )]
// pub struct FooWrongPath;

// MSG: this function takes 1 argument but 2 arguements were supplied
//
// #[derive(Component)]
// #[component(
//     on_add = wrong_bazzing("foo"),
// )]
// pub struct FooWrongCall;
//
// fn wrong_bazzing(path: &str) -> impl Fn(bevy::ecs::world::DeferredWorld) {
//     |world| {}
// }

// MSG: expected 1 argument, found 2
//
// #[derive(Component)]
// #[component(
//     on_add = |w| {},
// )]
// pub struct FooWrongCall;
```

---

## Showcase

I'll try to continue to work on this to have a small section in the
release notes.
2025-03-06 16:39:11 +00:00
JaySpruce
d6db78b5dd
Replace internal uses of insert_or_spawn_batch (#18035)
## Objective
`insert_or_spawn_batch` is due to be deprecated eventually (#15704), and
removing uses internally will make that easier.

## Solution

Replaced internal uses of `insert_or_spawn_batch` with
`try_insert_batch` (non-panicking variant because
`insert_or_spawn_batch` didn't panic).

All of the internal uses are in rendering code. Since retained rendering
was meant to get rid non-opaque entity IDs, I assume the code was just
using `insert_or_spawn_batch` because `insert_batch` didn't exist and
not because it actually wanted to spawn something. However, I am *not*
confident in my ability to judge rendering code.
2025-03-06 16:16:36 +00:00
Carter Anderson
06cb5c5fd9
Fix Component require() IDE integration (#18165)
# Objective

Component `require()` IDE integration is fully broken, as of #16575.

## Solution

This reverts us back to the previous "put the docs on Component trait"
impl. This _does_ reduce the accessibility of the required components in
rust docs, but the complete erasure of "required component IDE
experience" is not worth the price of slightly increased prominence of
requires in docs.

Additionally, Rust Analyzer has recently started including derive
attributes in suggestions, so we aren't losing that benefit of the
proc_macro attribute impl.
2025-03-06 02:44:47 +00:00
François Mockers
54701a844e
Revert "Replace Ambient Lights with Environment Map Lights (#17482)" (#18167)
This reverts commit 0b5302d96a.

# Objective

- Fixes #18158
- #17482 introduced rendering changes and was merged a bit too fast

## Solution

- Revert #17482 so that it can be redone and rendering changes discussed
before being merged. This will make it easier to compare changes with
main in the known "valid" state

This is not an issue with the work done in #17482 that is still
interesting
2025-03-05 23:08:46 +00:00
Carter Anderson
a530c07bc5
Preserve spawned RelationshipTarget order and other improvements (#17858)
Fixes #17720

## Objective

Spawning RelationshipTargets from scenes currently fails to preserve
RelationshipTarget ordering (ex: `Children` has an arbitrary order).
This is because it uses the normal hook flow to set up the collection,
which means we are pushing onto the collection in _spawn order_ (which
is currently in archetype order, which will often produce mismatched
orderings).

We need to preserve the ordering in the original RelationshipTarget
collection. Ideally without expensive checking / fixups.

## Solution

One solution would be to spawn in hierarchy-order. However this gets
complicated as there can be multiple hierarchies, and it also means we
can't spawn in more cache-friendly orders (ex: the current per-archetype
spawning, or future even-smarter per-table spawning). Additionally,
same-world cloning has _slightly_ more nuanced needs (ex: recursively
clone linked relationships, while maintaining _original_ relationships
outside of the tree via normal hooks).

The preferred approach is to directly spawn the remapped
RelationshipTarget collection, as this trivially preserves the ordering.
Unfortunately we can't _just_ do that, as when we spawn the children
with their Relationships (ex: `ChildOf`), that will insert a duplicate.

We could "fixup" the collection retroactively by just removing the back
half of duplicates, but this requires another pass / more lookups /
allocating twice as much space. Additionally, it becomes complicated
because observers could insert additional children, making it harder
(aka more expensive) to determine which children are dupes and which are
not.

The path I chose is to support "opting out" of the relationship target
hook in the contexts that need that, as this allows us to just cheaply
clone the mapped collection. The relationship hook can look for this
configuration when it runs and skip its logic when that happens. A
"simple" / small-amount-of-code way to do this would be to add a "skip
relationship spawn" flag to World. Sadly, any hook / observer that runs
_as the result of an insert_ would also read this flag. We really need a
way to scope this setting to a _specific_ insert.

Therefore I opted to add a new `RelationshipInsertHookMode` enum and an
`entity.insert_with_relationship_insert_hook_mode` variant. Obviously
this is verbose and ugly. And nobody wants _more_ insert variants. But
sadly this was the best I could come up with from a performance and
capability perspective. If you have alternatives let me know!

There are three variants:

1. `RelationshipInsertHookMode::Run`: always run relationship insert
hooks (this is the default)
2. `RelationshipInsertHookMode::Skip`: do not run any relationship
insert hooks for this insert (this is used by spawner code)
3. `RelationshipInsertHookMode::RunIfNotLinked`: only run hooks for
_unlinked_ relationships (this is used in same-world recursive entity
cloning to preserve relationships outside of the deep-cloned tree)

Note that I have intentionally only added "insert with relationship hook
mode" variants to the cases we absolutely need (everything else uses the
default `Run` mode), just to keep the code size in check. I do not think
we should add more without real _very necessary_ use cases.

I also made some other minor tweaks:

1. I split out `SourceComponent` from `ComponentCloneCtx`. Reading the
source component no longer needlessly blocks mutable access to
`ComponentCloneCtx`.
2. Thanks to (1), I've removed the `RefCell` wrapper over the cloned
component queue.
3. (1) also allowed me to write to the EntityMapper while queuing up
clones, meaning we can reserve entities during the component clone and
write them to the mapper _before_ inserting the component, meaning
cloned collections can be mapped on insert.
4. I've removed the closure from `write_target_component_ptr` to
simplify the API / make it compatible with the split `SourceComponent`
approach.
5. I've renamed `EntityCloner::recursive` to
`EntityCloner::linked_cloning` to connect that feature more directly
with `RelationshipTarget::LINKED_SPAWN`
6. I've removed `EntityCloneBehavior::RelationshipTarget`. This was
always intended to be temporary, and this new behavior removes the need
for it.

---------

Co-authored-by: Viktor Gustavsson <villor94@gmail.com>
2025-03-05 22:18:57 +00:00
Chris Russell
1f6642df4c
Fix unsound query transmutes on queries obtained from Query::as_readonly() (#17973)
# Objective

Fix unsound query transmutes on queries obtained from
`Query::as_readonly()`.

The following compiles, and the call to `transmute_lens()` should panic,
but does not:
```rust
fn bad_system(query: Query<&mut A>) {
    let mut readonly = query.as_readonly();
    let mut lens: QueryLens<&mut A> = readonly.transmute_lens();
    let other_readonly: Query<&A> = query.as_readonly();
    // `lens` and `other_readonly` alias, and are both alive here!
}
```

To make `Query::as_readonly()` zero-cost, we pointer-cast
`&QueryState<D, F>` to `&QueryState<D::ReadOnly, F>`. This means that
the `component_access` for a read-only query's state may include
accesses for the original mutable version, but the `Query` does not have
exclusive access to those components! `transmute` and `join` use that
access to ensure that a join is valid, and will incorrectly allow a
transmute that includes mutable access.

As a bonus, allow `Query::join`s that output `FilteredEntityRef` or
`FilteredEntityMut` to receive access from the `other` query. Currently
they only receive access from `self`.

## Solution

When transmuting or joining from a read-only query, remove any writes
before performing checking that the transmute is valid. For joins, be
sure to handle the case where one input query was the result of
`as_readonly()` but the other has valid mutable access.

This requires identifying read-only queries, so add a
`QueryData::IS_READ_ONLY` associated constant. Note that we only call
`QueryState::as_transmuted_state()` with `NewD: ReadOnlyQueryData`, so
checking for read-only queries is sufficient to check for
`as_transmuted_state()`.

Removing writes requires allocating a new `FilteredAccess`, so only do
so if the query is read-only and the state has writes. Otherwise, the
existing access is correct and we can continue using a reference to it.

Use the new read-only state to call `NewD::set_access`, so that
transmuting to a `FilteredAccessMut` results in a read-only
`FilteredAccessMut`. Otherwise, it would take the original write access,
and then the transmute would panic because it had too much access.

Note that `join` was previously passing `self.component_access` to
`NewD::set_access`. Switching it to `joined_component_access` also
allows a join that outputs `FilteredEntity(Ref|Mut)` to receive access
from `other`. The fact that it didn't do that before seems like an
oversight, so I didn't try to prevent that change.

## Testing

Added unit tests with the unsound transmute and join.
2025-03-04 19:26:31 +00:00
GlFolker
c819beb02c
Emphasize no structural changes in SystemParam::get_param (#17996)
# Objective

Many systems like `Schedule` rely on the fact that every structural ECS
changes are deferred until an exclusive system flushes the `World`
itself. This gives us the benefits of being able to run systems in
parallel without worrying about dangling references caused by memory
(re)allocations, which will in turn lead to **Undefined Behavior**.
However, this isn't explicitly documented in `SystemParam`; currently it
only vaguely hints that in `init_state`, based on the fact that
structural ECS changes require mutable access to the _whole_ `World`.

## Solution

Document this behavior explicitly in `SystemParam`'s type-level
documentations.
2025-03-04 18:09:39 +00:00