Commit Graph

6865 Commits

Author SHA1 Message Date
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
Zachary Harrold
ff1143ec87
Remove deprecated component_reads_and_writes (#16348)
# Objective

- Fixes #16339

## Solution

- Replaced `component_reads_and_writes` and `component_writes` with
`try_iter_component_access`.

## Testing

- Ran `dynamic` example to confirm behaviour is unchanged.
- CI

---

## Migration Guide

The following methods (some removed in previous PRs) are now replaced by
`Access::try_iter_component_access`:

* `Access::component_reads_and_writes`
* `Access::component_reads`
* `Access::component_writes`

As `try_iter_component_access` returns a `Result`, you'll now need to
handle the failing case (e.g., `unwrap()`). There is currently a single
failure mode, `UnboundedAccess`, which occurs when the `Access` is for
all `Components` _except_ certain exclusions. Since this list is
infinite, there is no meaningful way for `Access` to provide an
iterator. Instead, get a list of components (e.g., from the `Components`
structure) and iterate over that instead, filtering using
`Access::has_component_read`, `Access::has_component_write`, etc.

Additionally, you'll need to `filter_map` the accesses based on which
method you're attempting to replace:

* `Access::component_reads_and_writes` -> `Exclusive(_) | Shared(_)`
* `Access::component_reads` -> `Shared(_)`
* `Access::component_writes` -> `Exclusive(_)`

To ease migration, please consider the below extension trait which you
can include in your project:

```rust
pub trait AccessCompatibilityExt {
    /// Returns the indices of the components this has access to.
    fn component_reads_and_writes(&self) -> impl Iterator<Item = T> + '_;

    /// Returns the indices of the components this has non-exclusive access to.
    fn component_reads(&self) -> impl Iterator<Item = T> + '_;

    /// Returns the indices of the components this has exclusive access to.
    fn component_writes(&self) -> impl Iterator<Item = T> + '_;
}

impl<T: SparseSetIndex> AccessCompatibilityExt for Access<T> {
    fn component_reads_and_writes(&self) -> impl Iterator<Item = T> + '_ {
        self
            .try_iter_component_access()
            .expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
            .filter_map(|component_access| {
                let index = component_access.index().sparse_set_index();

                match component_access {
                    ComponentAccessKind::Archetypal(_) => None,
                    ComponentAccessKind::Shared(_) => Some(index),
                    ComponentAccessKind::Exclusive(_) => Some(index),
                }
            })
    }

    fn component_reads(&self) -> impl Iterator<Item = T> + '_ {
        self
            .try_iter_component_access()
            .expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
            .filter_map(|component_access| {
                let index = component_access.index().sparse_set_index();

                match component_access {
                    ComponentAccessKind::Archetypal(_) => None,
                    ComponentAccessKind::Shared(_) => Some(index),
                    ComponentAccessKind::Exclusive(_) => None,
                }
            })
    }

    fn component_writes(&self) -> impl Iterator<Item = T> + '_ {
        self
            .try_iter_component_access()
            .expect("Access is unbounded. Please refactor the usage of this method to directly use try_iter_component_access")
            .filter_map(|component_access| {
                let index = component_access.index().sparse_set_index();

                match component_access {
                    ComponentAccessKind::Archetypal(_) => None,
                    ComponentAccessKind::Shared(_) => None,
                    ComponentAccessKind::Exclusive(_) => Some(index),
                }
            })
    }
}
```

Please take note of the use of `expect(...)` in these methods. You
should consider using these as a starting point for a more appropriate
migration based on your specific needs.

## Notes

- This new method is fallible based on whether the `Access` is bounded
or unbounded (unbounded occurring with inverted component sets). If
bounded, will return an iterator of every item and its access level. I
believe this makes sense without exposing implementation details around
`Access`.
- The access level is defined by an `enum` `ComponentAccessKind<T>`,
either `Archetypical`, `Shared`, or `Exclusive`. As a convenience, this
`enum` has a method `index` to get the inner `T` value without a match
statement. It does add more code, but the API is clearer.
- Within `QueryBuilder` this new method simplifies several pieces of
logic without changing behaviour.
- Within `QueryState` the logic is simplified and the amount of
iteration is reduced, potentially improving performance.
- Within the `dynamic` example it has identical behaviour, with the
inversion footgun explicitly highlighted by an `unwrap`.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: Mike <2180432+hymm@users.noreply.github.com>
2025-03-04 08:22:29 +00:00
ickshonpe
8a87a51c54
BorderRadius comment fix (#18141)
# Objective

The doc comment for `BorderRadius::resolve_single_corner` returns a
value in physical pixels but the doc comments implies it returns a
logical value.
2025-03-04 08:06:34 +00:00
Dmytro Banin
7a1972ed3d
One-to-One Relationships (#18087)
# Objective

Minimal implementation of directed one-to-one relationships via
implementing `RelationshipSourceCollection` for `Entity`.

Now you can do

```rust
#[derive(Component)]
#[relationship(relationship_target = Below)]
pub struct Above(Entity);

#[derive(Component)]
#[relationship_target(relationship = Above)]
pub struct Below(Entity);
```

## Future Work

It would be nice if the relationships could be fully symmetrical in the
future - in the example above, since `Above` is the source of truth you
can't add `Below` to an entity and have `Above` added automatically.

## Testing

Wrote unit tests for new relationship sources and and verified
adding/removing relationships maintains connection as expected.
2025-03-04 07:57:35 +00:00
Joshua Holmes
df6e136ab0
Replace some !Send resources with thread_local! (#17730)
# Objective

Work for issue #17682 

What's in this PR:
* Removal of some `!Send` resources that Bevy uses internally
* Replaces `!Send` resources with `thread_local!` static

What this PR does not cover:
* The ability to create `!Send` resources still exists
* Tests that test `!Send` resources are present (and should not be
removed until the ability to create `!Send` resources is removed)
* The example `log_layers_ecs` still uses a `!Send` resource. In this
example, removing the `!Send` resource results in the system that uses
it running on a thread other than the main thread, which doesn't work
with lazily initialized `thread_local!` static data. Removing this
`!Send` resource will need to be deferred until the System API is
extended to support configuring which thread the System runs on. Once an
issue for this work is created, it will be mentioned in #17667

Once the System API is extended to allow control of which thread the
System runs on, the rest of the `!Send` resources can be removed in a
different PR.
2025-03-04 07:48:02 +00:00
Shaye Garg
0b5302d96a
Replace Ambient Lights with Environment Map Lights (#17482)
# Objective

Transparently uses simple `EnvironmentMapLight`s to mimic
`AmbientLight`s. Implements the first part of #17468, but I can
implement hemispherical lights in this PR too if needed.

## Solution

- A function `EnvironmentMapLight::solid_color(&mut Assets<Image>,
Color)` is provided to make an environment light with a solid color.
- A new system is added to `SimulationLightSystems` that maps
`AmbientLight`s on views or the world to a corresponding
`EnvironmentMapLight`.

I have never worked with (or on) Bevy before, so nitpicky comments on
how I did things are appreciated :).

## Testing

Testing was done on a modified version of the `3d/lighting` example,
where I removed all lights except the ambient light. I have not included
the example, but can if required.

## Migration
`bevy_pbr::AmbientLight` has been deprecated, so all usages of it should
be replaced by a `bevy_pbr::EnvironmentMapLight` created with
`EnvironmentMapLight::solid_color` placed on the camera. There is no
alternative to ambient lights as resources.
2025-03-04 07:40:53 +00:00
Ben Frankel
0a841ba9c1
Cache systems by S instead of S::System (#16694)
# Objective

- Fixes the issue described in this comment:
https://github.com/bevyengine/bevy/issues/16680#issuecomment-2522764239.

## Solution

- Cache one-shot systems by `S: IntoSystem` (which is const-asserted to
be a ZST) rather than `S::System`.

## Testing

Added a new unit test named `cached_system_into_same_system_type` to
`system_registry.rs`.

---

## Migration Guide

The `CachedSystemId` resource has been changed:

```rust
// Before:
let cached_id = CachedSystemId::<S::System>(id);
assert!(id == cached_id.0);

// After:
let cached_id = CachedSystemId::<S>::new(id);
assert!(id == SystemId::from_entity(cached_id.entity));
```
2025-03-04 07:31:10 +00:00
Martín Maita
a23f397dab
Update ruzstd requirement from 0.7.0 to 0.8.0 (#18145)
# Objective

- Fixes #18129

## Solution

- Update ruzstd requirement from 0.7.0 to 0.8.0 and fixed imports.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 21:44:51 +00:00
ickshonpe
912de69cfb
Val::resolve doc comment fix (#18143)
# Objective

Fix the doc comment for `Val::resolve`. It doesn't return a value in
logical pixels unless the inputs are also in logical pixels.
2025-03-03 19:49:52 +00:00
dependabot[bot]
cf18c346d8
Update itertools requirement from 0.13 to 0.14 (#18128)
Updates the requirements on
[itertools](https://github.com/rust-itertools/itertools) to permit the
latest version.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md">itertools's
changelog</a>.</em></p>
<blockquote>
<h2>0.14.0</h2>
<h3>Breaking</h3>
<ul>
<li>Increased MSRV to 1.63.0 (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/960">#960</a>)</li>
<li>Removed generic parameter from <code>cons_tuples</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/988">#988</a>)</li>
</ul>
<h3>Added</h3>
<ul>
<li>Added <code>array_combinations</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/991">#991</a>)</li>
<li>Added <code>k_smallest_relaxed</code> and variants (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/925">#925</a>)</li>
<li>Added <code>next_array</code> and <code>collect_array</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/560">#560</a>)</li>
<li>Implemented <code>DoubleEndedIterator</code> for
<code>FilterOk</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/948">#948</a>)</li>
<li>Implemented <code>DoubleEndedIterator</code> for
<code>FilterMapOk</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/950">#950</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Allow <code>Q: ?Sized</code> in <code>Itertools::contains</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/971">#971</a>)</li>
<li>Improved hygiene of <code>chain!</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/943">#943</a>)</li>
<li>Improved <code>into_group_map_by</code> documentation (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/1000">#1000</a>)</li>
<li>Improved <code>tree_reduce</code> documentation (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/955">#955</a>)</li>
<li>Improved discoverability of <code>merge_join_by</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/966">#966</a>)</li>
<li>Improved discoverability of <code>take_while_inclusive</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/972">#972</a>)</li>
<li>Improved documentation of <code>find_or_last</code> and
<code>find_or_first</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/984">#984</a>)</li>
<li>Prevented exponentially large type sizes in
<code>tuple_combinations</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/945">#945</a>)</li>
<li>Added <code>track_caller</code> attr for <code>asser_equal</code>
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/976">#976</a>)</li>
</ul>
<h3>Notable Internal Changes</h3>
<ul>
<li>Fixed clippy lints (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/956">#956</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/987">#987</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/1008">#1008</a>)</li>
<li>Addressed warnings within doctests (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/964">#964</a>)</li>
<li>CI: Run most tests with miri (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/961">#961</a>)</li>
<li>CI: Speed up &quot;cargo-semver-checks&quot; action (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/938">#938</a>)</li>
<li>Changed an instance of <code>default_features</code> in
<code>Cargo.toml</code> to <code>default-features</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/985">#985</a>)</li>
</ul>
<h2>0.13.0</h2>
<h3>Breaking</h3>
<ul>
<li>Removed implementation of <code>DoubleEndedIterator</code> for
<code>ConsTuples</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/853">#853</a>)</li>
<li>Made <code>MultiProduct</code> fused and fixed on an empty iterator
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/835">#835</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/834">#834</a>)</li>
<li>Changed <code>iproduct!</code> to return tuples for maxi one
iterator too (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/870">#870</a>)</li>
<li>Changed <code>PutBack::put_back</code> to return the old value (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/880">#880</a>)</li>
<li>Removed deprecated <code>repeat_call, Itertools::{foreach, step,
map_results, fold_results}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/878">#878</a>)</li>
<li>Removed <code>TakeWhileInclusive::new</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/912">#912</a>)</li>
</ul>
<h3>Added</h3>
<ul>
<li>Added <code>Itertools::{smallest_by, smallest_by_key, largest,
largest_by, largest_by_key}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/654">#654</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/885">#885</a>)</li>
<li>Added <code>Itertools::tail</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/899">#899</a>)</li>
<li>Implemented <code>DoubleEndedIterator</code> for
<code>ProcessResults</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/910">#910</a>)</li>
<li>Implemented <code>Debug</code> for <code>FormatWith</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/931">#931</a>)</li>
<li>Added <code>Itertools::get</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/891">#891</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Deprecated <code>Itertools::group_by</code> (renamed
<code>chunk_by</code>) (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/866">#866</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/879">#879</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a015a68315"><code>a015a68</code></a>
Add <code>next_array</code> and <code>collect_array</code></li>
<li><a
href="a1213e1c81"><code>a1213e1</code></a>
Prepare v0.14.0 release</li>
<li><a
href="ff0c942b2e"><code>ff0c942</code></a>
fix clippy lints</li>
<li><a
href="f80883b8e0"><code>f80883b</code></a>
Fix into_group_map_by documentation errors</li>
<li><a
href="b793238ff1"><code>b793238</code></a>
Add track_caller for asser_equal</li>
<li><a
href="5d4056b643"><code>5d4056b</code></a>
<code>default_features</code> is deprecated - switch it to
<code>default-features</code></li>
<li><a
href="a447b68960"><code>a447b68</code></a>
doc for added trait</li>
<li><a
href="d0479b0807"><code>d0479b0</code></a>
&quot;nitpicks&quot;</li>
<li><a
href="35c78ce0bc"><code>35c78ce</code></a>
IndexMut -&gt; BorrowMut&lt;slice&gt;</li>
<li><a
href="deb53ba210"><code>deb53ba</code></a>
refactored to share code</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-itertools/itertools/compare/v0.13.0...v0.14.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 19:36:29 +00:00
Tim Overbeek
173680944f
fix generics for relationships (#18136)
# Objective
Allow Relationship to be derived for structs with generics.

fixes #18133
## Solution

"X" inside #[relationship_target(relationship = X)] was previously
parsed as Idents,
now they are parsed as syn::Type

## Testing

```rust
#[derive(Component)]
#[relationship(relationship_target = Attachments<T>)]
pub struct AttachedTo<T: Send + Sync + 'static> {
    #[relationship]
    pub entity: Entity,
    pub marker: PhantomData<T>,
}

#[derive(Component)]
#[relationship_target(relationship = AttachedTo<T>)]
pub struct Attachments<T: Send + Sync + 'static> {
    #[relationship]
    entities: Vec<Entity>,
    pub marker: PhantomData<T>,
}
```
This now compiles!
2025-03-03 19:33:29 +00:00
Patrick Walton
236091adce
Reextract meshes when their material assets change. (#18123)
This commit makes the
`mark_meshes_as_changed_if_their_materials_changed` system use the new
`AssetChanged<MeshMaterial3d>` query filter in addition to
`Changed<MeshMaterial3d>`. This ensures that we update the
`MeshInputUniform`, which contains the bindless material slot. Updating
the `MeshInputUniform` fixes problems that occurred when the
`MeshBindGroupAllocator` reallocated meshes in such a way as to change
their bindless slot.

Closes #18102.
2025-03-03 06:28:33 +00:00
Nathan Fenner
755adae0f8
fix test for .iter().sort() to include data to sort (#18127)
The test case `query_iter_sorts` was doing lots of comparisons to ensure
that various query arrays were sorted, but the arrays were all empty.

This PR spawns some entities so that the entity lists to compare not
empty, and sorting can actually be tested for correctness.
2025-03-03 06:24:43 +00:00
Greeble
f42ecc44f8
Fix panic with multiple fog volumes (#18119)
# Objective

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

## Solution

`prepare_volumetric_fog_uniforms` adds a uniform for each combination of
fog volume and view. But it only allocated enough uniforms for one fog
volume per view.

## Testing

Ran the `volumetric_fog` example with 1/2/3/4 fog volumes. Also checked
the `fog_volumes` and `scrolling_fog` examples (without multiple
volumes). Win10/Vulkan/Nvidia.

To test multiple views I tried adding fog volumes to the `split_screen`
example. This doesn't quite work - the fog should be centred on the fox,
but instead it's centred on the window. Same result with and without the
PR, so I'm assuming it's a separate bug.


![image](https://github.com/user-attachments/assets/4a74d6d7-8a73-4322-9dc6-c5ddd054ece2)
2025-03-03 06:22:36 +00:00
Alice Cecile
2ad5908e58
Make Query::single (and friends) return a Result (#18082)
# Objective

As discussed in #14275, Bevy is currently too prone to panic, and makes
the easy / beginner-friendly way to do a large number of operations just
to panic on failure.

This is seriously frustrating in library code, but also slows down
development, as many of the `Query::single` panics can actually safely
be an early return (these panics are often due to a small ordering issue
or a change in game state.

More critically, in most "finished" products, panics are unacceptable:
any unexpected failures should be handled elsewhere. That's where the
new

With the advent of good system error handling, we can now remove this.

Note: I was instrumental in a) introducing this idea in the first place
and b) pushing to make the panicking variant the default. The
introduction of both `let else` statements in Rust and the fancy system
error handling work in 0.16 have changed my mind on the right balance
here.

## Solution

1. Make `Query::single` and `Query::single_mut` (and other random
related methods) return a `Result`.
2. Handle all of Bevy's internal usage of these APIs.
3. Deprecate `Query::get_single` and friends, since we've moved their
functionality to the nice names.
4. Add detailed advice on how to best handle these errors.

Generally I like the diff here, although `get_single().unwrap()` in
tests is a bit of a downgrade.

## Testing

I've done a global search for `.single` to track down any missed
deprecated usages.

As to whether or not all the migrations were successful, that's what CI
is for :)

## Future work

~~Rename `Query::get_single` and friends to `Query::single`!~~

~~I've opted not to do this in this PR, and smear it across two releases
in order to ease the migration. Successive deprecations are much easier
to manage than the semantics and types shifting under your feet.~~

Cart has convinced me to change my mind on this; see
https://github.com/bevyengine/bevy/pull/18082#discussion_r1974536085.

## Migration guide

`Query::single`, `Query::single_mut` and their `QueryState` equivalents
now return a `Result`. Generally, you'll want to:

1. Use Bevy 0.16's system error handling to return a `Result` using the
`?` operator.
2. Use a `let else Ok(data)` block to early return if it's an expected
failure.
3. Use `unwrap()` or `Ok` destructuring inside of tests.

The old `Query::get_single` (etc) methods which did this have been
deprecated.
2025-03-02 19:51:56 +00:00
Kim Simmons
ff1ae62e1c
Fix incorrect doc about GamepadAxis::RightZ/LeftZ (#18114)
# Objective

Documentation correction.

# Reasoning
The `GamepadAxis::RightZ` and `LeftZ` do not map to the trigger buttons
on a gamepad. They are in fact for the twisting/yaw of a flight Joystick
and throttle lever respectively. I confirmed this with two gamepads that
has analog triggers (Logitech F710, 8bitdo ultimate BT controller) and a
HOTAS joystick (Saitek X52).
2025-03-02 19:18:01 +00:00
Rob Parrett
36cb64b382
Bump typos to 1.30.0 (#18097)
# Objective

Update `typos` and fix newly detected typos.


[Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md#1300---2025-03-01)
(just a dictionary update releases)

## Solution

Fix em

- Describe the solution used to achieve the objective above.

## Testing

CI
2025-03-02 19:02:23 +00:00
Joshua Maleszewski
1ef334cc25
Make asset watcher work when path contains "../" (#18023)
# Objective

Fixes #18022

## Solution

Canonicalize asset paths

## Testing

I ran the examples `sprite`, `desk_toy` and `game_menu` with the feature
`file_watcher` enabled. All correctly updated an asset when the source
file was altered.

Co-authored-by: Threadzless <threadzless@gmail.com>
2025-03-02 18:15:27 +00:00
aloucks
ef9b898c2d
Fix invisible window creation on Windows (#18105)
# Objective

Fixes #18027 

## Solution

Run `redraw_requested` logic in `about_to_wait` on Windows during
initial application startup and when in headless mode

## Testing

- Ran `cargo run --example window_settings` to demonstrate invisible
window creation worked again and fixes #18027
- Ran `cargo run --example eased_motion` to demonstrate no regression
with the fix for #17488

Ran all additional `window` examples. 

Notes:

- The `transparent_window` was not transparent but this appears to have
been broken prior to #18004. See: #7544
2025-03-02 18:07:21 +00:00
Patrick Walton
57143a8298
Add missing bindless imports in pbr_prepass.wgsl. (#18110)
The bindless reform PR neglected to include these, causing the prepass
shader to fail to compile in some circumstances.
2025-03-02 09:12:18 +00:00
RobWalt
73ffd9a508
chore: update compile fail test stderr files (#18056)
I noticed this while working on #18017 . Some of the `stderr`
compile_fail tests were updated while I generated the output for the new
tests I introduced in the mentioned PR.

I'm on rust 1.85.0
2025-03-01 00:31:55 +00:00
Zachary Harrold
fdd9ffab01
Allow bevy_reflect and wgpu-types features in no_std for bevy_color (#18061)
# Objective

- Improve feature parity in `no_std` for `bevy_color`

## Solution

- Allowed `bevy_reflect` in `no_std` now that it has full support
- Allowed `wgpu-types` in `no_std` now version 24 has full support
- Added `critical-section` feature to make standalone usage in `no_std`
easier

## Testing

- `cargo check -p bevy_color --no-default-features --features
libm,bevy_reflect,critical-section,serialize,alloc,wgpu-types --target
thumbv6m-none-eabi`

---

## Notes

With these changes, `bevy_color`'s feature support looks like this:

| Feature | `no_std` (Before) | `no_std` (After) | Notes |
| - | - | - | - |
| `default` |  |  | |
| `std` |  |  | |
| `alloc` | ✔️ | ✔️ | |
| `serialize` | ✔️ | ✔️ | |
| `bevy_reflect` |  | ✔️ | |
| `wgpu-types` |  | ✔️ | |
| `encase` |  |  | |
| `libm` | ✔️ | ✔️ | |
| `critical-section` |  | ✔️ | |
2025-03-01 00:31:35 +00:00
JaySpruce
ad1691e44a
Update EntityCommands::trigger to check for the entity's existence (#18071)
## Objective

`EntityCommands::trigger` internally uses `Commands::trigger_targets`,
which means it gets queued using `Commands::queue` rather
`EntityCommands::queue`. This previously wouldn't have made much
difference, but now entity commands check whether the entity exists, and
that check never happens in this case.

## Solution

- Add `entity_command::trigger`, which calls the same function as before
(`World::trigger_targets_with_caller`) but through the `EntityWorldMut`
passed to entity commands.
- Change `EntityCommands::trigger` to queue the new entity command
normally.
2025-03-01 00:08:03 +00:00
Greeble
780f658f2c
Update ChildOf deprecation advice to match new layout (#18089)
https://github.com/bevyengine/bevy/pull/17905 replaced `ChildOf(entity)`
with `ChildOf { parent: entity }`, but some deprecation advice was
overlooked. Also corrected formatting in documentation.

## Testing

Added a `set_parent` to a random example. Confirmed that the deprecation
warning shows and the advice can be pasted in.
2025-02-28 23:15:23 +00:00
Will Schroeder
e43b28c1ec
moved Debug from derive to impl_ptr in bevy_ptr (#18042)
# Objective

Fixes #17988

## Solution

Added two Debug impls to the `impl_ptr` macro - one for Aligned and one
for Unaligned.

## Testing

No tests have been added. Would a test guaranteeing debug layout be
appropriate?

---

## Showcase

The debug representation of a `Ptr<'_, Aligned>` follows. `PtrMut` and
`OwningPtr` are similar.

`Ptr<Aligned>(0x0123456789ab)`
2025-02-28 02:54:46 +00:00
Carter Anderson
b73811d40e
Remove ChildOf::get and Deref impl (#18080)
# Objective

There are currently three ways to access the parent stored on a ChildOf
relationship:

1. `child_of.parent` (field accessor)
2. `child_of.get()` (get function)
3. `**child_of` (Deref impl)

I will assert that we should only have one (the field accessor), and
that the existence of the other implementations causes confusion and
legibility issues. The deref approach is heinous, and `child_of.get()`
is significantly less clear than `child_of.parent`.

## Solution

Remove `impl Deref for ChildOf` and `ChildOf::get`.

The one "downside" I'm seeing is that:

```rust
entity.get::<ChildOf>().map(ChildOf::get)
```
Becomes this:

```rust
entity.get::<ChildOf>().map(|c| c.parent)
```

I strongly believe that this is worth the increased clarity and
consistency. I'm also not really a huge fan of the "pass function
pointer to map" syntax. I think most people don't think this way about
maps. They think in terms of a function that takes the item in the
Option and returns the result of some action on it.

## Migration Guide

```rust
// Before
**child_of
// After
child_of.parent

// Before
child_of.get()
// After
child_of.parent

// Before
entity.get::<ChildOf>().map(ChildOf::get)
// After
entity.get::<ChildOf>().map(|c| c.parent)
```
2025-02-27 23:11:03 +00:00
JaySpruce
058497e0bb
Change Commands::get_entity to return Result and remove panic from Commands::entity (#18043)
## Objective

Alternative to #18001.

- Now that systems can handle the `?` operator, `get_entity` returning
`Result` would be more useful than `Option`.
- With `get_entity` being more flexible, combined with entity commands
now checking the entity's existence automatically, the panic in `entity`
isn't really necessary.

## Solution

- Changed `Commands::get_entity` to return `Result<EntityCommands,
EntityDoesNotExistError>`.
- Removed panic from `Commands::entity`.
2025-02-27 21:05:16 +00:00
Tim Overbeek
ccb7069e7f
Change ChildOf to Childof { parent: Entity} and support deriving Relationship and RelationshipTarget with named structs (#17905)
# Objective

fixes #17896 

## Solution

Change ChildOf ( Entity ) to ChildOf { parent: Entity }

by doing this we also allow users to use named structs for relationship
derives, When you have more than 1 field in a struct with named fields
the macro will look for a field with the attribute #[relationship] and
all of the other fields should implement the Default trait. Unnamed
fields are still supported.

When u have a unnamed struct with more than one field the macro will
fail.
Do we want to support something like this ? 

```rust
 #[derive(Component)]
 #[relationship_target(relationship = ChildOf)]
 pub struct Children (#[relationship] Entity, u8);
```
I could add this, it but doesn't seem nice.
## Testing

crates/bevy_ecs - cargo test


## Showcase


```rust

use bevy_ecs::component::Component;
use bevy_ecs::entity::Entity;

 #[derive(Component)]
 #[relationship(relationship_target = Children)]
 pub struct ChildOf {
     #[relationship]
     pub parent: Entity,
     internal: u8,
 };

 #[derive(Component)]
 #[relationship_target(relationship = ChildOf)]
 pub struct Children {
     children: Vec<Entity>
 };

```

---------

Co-authored-by: Tim Overbeek <oorbecktim@Tims-MacBook-Pro.local>
Co-authored-by: Tim Overbeek <oorbecktim@c-001-001-042.client.nl.eduvpn.org>
Co-authored-by: Tim Overbeek <oorbecktim@c-001-001-059.client.nl.eduvpn.org>
Co-authored-by: Tim Overbeek <oorbecktim@c-001-001-054.client.nl.eduvpn.org>
Co-authored-by: Tim Overbeek <oorbecktim@c-001-001-027.client.nl.eduvpn.org>
2025-02-27 19:22:17 +00:00
JaySpruce
67146bdef7
Add missing unsafe to entity_command::insert_by_id and make it more configurable (#18052)
## Objective

`insert_by_id` is unsafe, but I forgot to add that to the
manually-queueable version in `entity_command`.

It also can only insert using `InsertMode::Replace`, when it could
easily be configurable by threading an `InsertMode` parameter to the
final `BundleInserter::insert` call.

## Solution

- Add `unsafe` and safety comment.
- Add `InsertMode` parameter to `entity_command::insert_by_id`,
`EntityWorldMut::insert_by_id_with_caller`, and
`EntityWorldMut::insert_dynamic_bundle`.
- Add `InsertMode` parameter to `entity_command::insert` and remove
`entity_command::insert_if_new`, for consistency with the other
manually-queued insertion commands.
2025-02-27 06:20:32 +00:00
Zachary Harrold
ad016cb850
Improve bevy_reflect no_std support (#18060)
# Objective

- Fixes #18051

## Solution

- Switched function registry to use `bevy_platform_support::sync`
instead of `std::sync`
- Also documented that `debug_stack` (and transitively `debug`) require
`std`
- Also removed `std` from `wgpu-types` since that crate is now `no_std`
compatible

## Testing

- `cargo check -p bevy_reflect --no-default-features --features
critical-section,documentation,glam,glam/libm,smallvec,wgpu-types,functions
--target thumbv6m-none-eabi`

---

## Notes

With these changes, `bevy_reflect`'s feature support looks like this:

| Feature | `no_std` (Before) | `no_std` (After) | Notes |
| - | - | - | - |
| `default` |  |  | |
| `std` |  |  | |
| `documentation` | ✔️ | ✔️ | |
| `functions` |  | ✔️ | |
| `critical-section` | ✔️ | ✔️ | |
| `bevy` | ✔️* | ✔️* | Partial due to `smol_str` |
| `debug` |  |  | |
| `debug_stack` |  |  | |
| `petgraph` |  |  | |
| `glam` | ✔️* | ✔️* | Requires enabling `glam/libm` |
| `smallvec` | ✔️ | ✔️ | |
| `uuid` | ✔️* | ✔️* | Requires setting up `getrandom` backend |
| `wgpu-types ` |  | ✔️ | |
| `smol_str` | ✔️* | ✔️* | Partial due to `smol_str` not supporting
`portable-atomic` |
2025-02-27 06:16:10 +00:00
urben1680
2f384643c3
Bubble sync points if ignore_deferred, do not ignore if target system is exclusive (#17880)
# Objective

Fixes #17828

This fixes two bugs:

1. Exclusive systems should see the effect of all commands queued to
that point. That does not happen when the system is configured with
`*_ignore_deferred` which may lead to surprising situations. These
configurations should not behave like that.
2. If `*_ignore_deferred` is used, no sync point may be added at all
**after** the config. Currently this can happen if the last nodes in
that config have no deferred parameters themselves. Instead, sync points
should always be added after such a config, so long systems have
deferred parameters.

## Solution

1. When adding sync points on edges, do not consider
`AutoInsertApplyDeferredPass::no_sync_edges` if the target is an
exclusive system.
2. when going through the nodes in a directed way, store the information
that `AutoInsertApplyDeferredPass::no_sync_edges` suppressed adding a
sync point at the target node. Then, when the target node is evaluated
later by the iteration and that prior suppression was the case, the
target node will behave like it has deferred parameters even if the
system itself does not.

## Testing

I added a test for each bug, please let me know if more are wanted and
if yes, which cases you would want to see.
These tests also can be read as examples how the current code would
fail.
2025-02-26 20:39:23 +00:00
Ruslan Baynazarov
c7531074bc
Improve cubic segment bezier functionality (#17645)
# Objective

- Fixes #17642

## Solution

- Implemented method `new_bezier(points: [P; 4]) -> Self` for
`CubicSegment<P>`
- Old implementation of `new_bezier` is now `new_bezier_easing(p1: impl
Into<Vec2>, p2: impl Into<Vec2>) -> Self` (**breaking change**)
- ~~added method `new_bezier_with_anchor`, which can make a bezier curve
between two points with one control anchor~~
- added methods `iter_positions`, `iter_velocities`,
`iter_accelerations`, the same as in `CubicCurve` (**copied code,
potentially can be reduced)**
- bezier creation logic is moved from `CubicCurve` to `CubicSegment`,
removing the unneeded allocation

## Testing

- Did you test these changes? If so, how?
  - Run tests inside `crates/bevy_math/`
  - Tested the functionality in my project
- Are there any parts that need more testing?
  - Did not run `cargo test` on the whole bevy directory because of OOM
- Performance improvements are expected when creating `CubicCurve` with
`new_bezier` and `new_bezier_easing`, but not tested
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Use in any code that works created `CubicCurve::new_bezier`
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - I don't think relevant

---

## Showcase

```rust
// Imagine a car goes towards a local target

// Create a simple `CubicSegment`, without using heap
let planned_path = CubicSegment::new_bezier([
    car_pos,
    car_pos + car_dir * turn_radius,
    target_point - target_dir * turn_radius,
    target_point,
]);

// Check if the planned path itersect other entities
for pos in planned_path.iter_positions(8) {
   // do some collision checks
}
```

## Migration Guide

> This section is optional. If there are no breaking changes, you can
delete this section.

- Replace `CubicCurve::new_bezier` with `CubicCurve::new_bezier_easing`
2025-02-26 20:36:54 +00:00
Chris Russell
94e6fa168f
Fix unsoundness in QueryIter::sort_by (#17826)
# Objective

`QueryIter::sort_by()` is unsound. It passes the lens items with the
full `'w` lifetime, and a malicious user could smuggle them out of the
closure where they could alias with the query results.

## Solution

Make the sort closures generic in the lifetime parameter of the lens
item. This ensures the lens items cannot outlive the call to the
closure.

## Testing

Added a compile-fail test that demonstrates the unsound pattern.

## Migration Guide

The `sort` family of methods on `QueryIter` unsoundly gave access
`L::Item<'w>` with the full `'w` lifetime. It has been shortened to
`L::Item<'w>` so that items cannot escape the comparer. If you get
lifetime errors using these methods, you will need to make the comparer
generic in the new lifetime. Often this can be done by replacing named
`'w` with `'_`, or by replacing the use of a function item with a
closure.

```rust
// Before: Now fails with "error: implementation of `FnMut` is not general enough"
query.iter().sort_by::<&C>(Ord::cmp);
// After: Wrap in a closure
query.iter().sort_by::<&C>(|l, r| Ord::cmp(l, r));

query.iter().sort_by::<&C>(comparer);
// Before: Uses specific `'w` lifetime from some outer scope
// now fails with "error: implementation of `FnMut` is not general enough"
fn comparer(left: &&'w C, right: &&'w C) -> Ordering { /* ... */ }
// After: Accepts any lifetime using inferred lifetime parameter
fn comparer(left: &&C, right: &&C) -> Ordering { /* ... */ }
2025-02-26 20:36:37 +00:00
Matty Weatherley
4b1745f813
BRP resource methods (#17423)
# Objective

So far, built-in BRP methods allow users to interact with entities'
components, but global resources have remained beyond its reach. The
goal of this PR is to take the first steps in rectifying this shortfall.

## Solution

Added five new default methods to BRP:
- `bevy/get_resource`: Extracts the value of a given resource from the
world.
- `bevy/insert_resource`: Serializes an input value to a given resource
type and inserts it into the world.
- `bevy/remove_resource`: Removes the given resource from the world.
- `bevy/mutate_resource`: Replaces the value of a field in a given
resource with the result of serializing a given input value.
- `bevy/list_resources`: Lists all resources in the type registry with
an available `ReflectResource`.

## Testing

Added a test resource to the `server` example scene that you can use to
mess around with the new BRP methods.

## Showcase

Resources can now be retrieved and manipulated remotely using a handful
of new BRP methods. For example, a resource that looks like this:
```rust
#[derive(Resource, Reflect, Serialize, Deserialize)]
#[reflect(Resource, Serialize, Deserialize)]
pub struct PlayerSpawnSettings {
  pub location: Vec2,
  pub lives: u8,
}
```

can be manipulated remotely as follows.

Retrieving the value of the resource:
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "bevy/get_resource",
  "params": {
    "resource": "path::to::my::module::PlayerSpawnSettings"
  }
}
```

Inserting a resource value into the world:
```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "bevy/insert_resource",
  "params": {
    "resource": "path::to::my::module::PlayerSpawnSettings",
    "value": {
      "location": [
        2.5, 
        2.5
      ],
      "lives": 25
    }
  }
}
```

Removing the resource from the world:
```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "bevy/remove_resource",
  "params": {
    "resource": "path::to::my::module::PlayerSpawnSettings"
  }
}
```

Mutating a field of the resource specified by a path:
```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "bevy/mutate_resource",
  "params": {
    "resource": "path::to::my::module::PlayerSpawnSettings",
    "path": ".location.x",
    "value": -3.0
  }
}
```

Listing all manipulable resources in the type registry:
```json
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "bevy/list_resources"
}
```
2025-02-26 20:29:47 +00:00
Lucas Franca
11db71727d
Refactor bevy_gltf (#15994)
# Objective

Refactor `bevy_gltf`, the criteria for the split is kind of arbitrary
but at least it is not a 2.6k line file.

## Solution

Move methods and structs found in `bevy_gltf/loader.rs` into multiple
new modules.

## Testing

`cargo run -p ci`
2025-02-26 01:00:11 +00:00
Aevyrie
831ecf030c
TaskPool: Prefer task completion over executing new tasks (#18009)
# Objective

- Systems that use the task pool, either explicitly or implicitly using
parallel queries, will often end up executing tasks from different
systems.
- This can cause random tasks to block the main or render schedule at
random, adding frame variance and increasing frame times when CPU bound.
- This profile is a common occurrence on `main`.
`propagate_parent_transforms` takes more than twice as long as it
should, blocking the main schedule for that time, because it uses `task
pool.scope`, which has decided to execute tasks from the render schedule
on the main schedule.

![image](https://github.com/user-attachments/assets/c363be40-82ce-451e-ba29-3eb4ee367e0b)


## Solution

- In task pool scope execution, prefer to check if the current task is
complete instead of ticking the executor to find new work.

## Testing

- Ran the scene viewer with tracy to look for images like the one in the
objective section.
- Things look much, much better, and I could not find any occurrences: 

![image](https://github.com/user-attachments/assets/18b79394-1a7c-49c1-820a-f5207e81bbac)

![image](https://github.com/user-attachments/assets/e7d4831d-66c3-41c1-ae2c-a624724c9965)
2025-02-26 00:08:36 +00:00
Sou1gh0st
f2b37c733e
Deduplicate register_inherited_required_components (#16519)
# Objective
- Fixes #16416 

## Solution
- Add a intermediate temporary mutable `RequiredComponents` to get avoid
of the borrowing issues.

## Testing

- I have run `cargo test --package bevy_ecs -- --exact --show-output`
and past all the tests.
2025-02-25 23:59:58 +00:00
SpecificProtagonist
25cee420e4
do_not_recommend interned Labels (#17950)
# Objective

Follow up on #17441 now that `do_not_recommend` is stable.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-25 23:46:21 +00:00
JaySpruce
36a2f7fdf1
Remove unnecessary bounds on EntityClonerBuilder::without_required_components (#17969)
## Objective

The closure argument for
`EntityClonerBuilder::without_required_components` has `Send + Sync +
'static` bounds, but the closure immediately gets called and never needs
to be sent anywhere. (This was my fault :P )

## Solution

Remove the bounds so that users aren't unnecessarily restricted.

I also took the opportunity to expand the tests a little.
2025-02-25 23:34:46 +00:00
Tristan Maindron
0f153ffb44
Prevent last_trigger_id from overflowing (#17978)
# Objective

This prevents overflowing the `last_trigger_id` property that leads to a
panic in debug mode.

```bash
panicked at C:\XXX\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.15.2\src\world\unsafe_world_cell.rs:630:18:
attempt to add with overflow
Encountered a panic when applying buffers for system `bevy_sprite::calculate_bounds_2d`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
```

## Solution

As this value is only used for detecting a change, we can wrap when it
reaches max value.

## Testing

This can be verified by running `cargo run --example observers`
2025-02-25 23:12:51 +00:00
Brezak
b43c8f8c4f
Add methods to add single entity relationships (#18038)
# Objective

Closes #17572

## Solution

Add the `add_one_related` methods to `EntityCommands` and
`EntityWorldMut`.

## Testing

Clippy

---

## Showcase

The `EntityWorldMut` and `FilteredResourcesMut` now include the
`add_one_related` method if you just want to relate 2 entities.
2025-02-25 23:07:44 +00:00
Patrick Walton
df5e3a7b96
Load each glTF skin at most once. (#18026)
Currently, we reload a glTF skin each time we encounter a node that
references it. By checking for duplicates, PR #18013 turned this into a
fatal error. But this was always wasteful. This commit fixes the issue
by caching each skin by its index as we load it.

The Maya babylon.js export plugin likes to emit glTFs with multiple
nodes that reference the same skin, so this effectively unbreaks Maya
rigs.
2025-02-25 01:27:29 +00:00
Zachary Harrold
20813aed64
Handle TriggerTargets that are combinations for components/entities (#18024)
# Objective

* Fixes https://github.com/bevyengine/bevy/issues/14074
* Applies CI fixes for #16326

It is currently not possible to issues a trigger that targets a specific
list of components AND a specific list of entities

## Solution

We can now use `((A, B), (entity_1, entity_2))` as a trigger target, as
well as the reverse

## Testing

Added a unit test.

The triggering rules for observers are quite confusing:

Triggers once per entity target

For each entity target, an observer system triggers if any of its
components matches the trigger target components (but it triggers at
most once, since we use an internal counter to make sure that an
observer can run at most once per entity target)

(copied from #14563)
(copied from #16326)

## Notes

All credit to @BenjaminBrienen and @cBournhonesque! Just applying a
small fix to this PR so it can be merged.

---------

Co-authored-by: Benjamin Brienen <Benjamin.Brienen@outlook.com>
Co-authored-by: Christian Hughes <xdotdash@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-24 23:57:34 +00:00
andriyDev
ed1143b26b
Make adding a subasset label return a result for if there is a duplicate label. (#18013)
# Objective

- Makes #18010 more easily debuggable. This doesn't solve that issue,
but protects us from it in the future.

## Solution

- Make `LoadContext::add_labeled_asset` and friends return an error if
it finds a duplicate asset.

## Testing

- Added a test - it fails before the fix.

---

## Migration Guide

- `AssetLoader`s must now handle the case of a duplicate subasset label
when using `LoadContext::add_labeled_asset` and its variants. If you
know your subasset labels are unique by construction (e.g., they include
an index number), you can simply unwrap this result.
2025-02-24 21:51:40 +00:00
VitalyR
6bae04ab36
Add usage notes for register_component (#18011)
# Objective

- Add usage notes for `register_component`, fixes #16447


## Testing

CI
2025-02-24 21:47:25 +00:00
Patrick Walton
172c020b60
Cache opaque deferred entities so we don't have to continuously re-queue them. (#18007)
Even though opaque deferred entities aren't placed into the `Opaque3d`
bin, we still want to cache them as though they were, so that we don't
have to re-queue them every frame. This commit implements that logic,
reducing the time of `queue_material_meshes` to near-zero on Caldera.
2025-02-24 21:44:24 +00:00
Patrick Walton
5d7a60592d
Add a new #[data] attribute to AsBindGroup that allows packing data for multiple materials into a single array. (#17965)
Currently, the structure-level `#[uniform]` attribute of `AsBindGroup`
creates a binding array of individual buffers, each of which contains
data for a single material. A more efficient approach would be to
provide a single buffer with an array containing all of the data for all
materials in the bind group. Because `StandardMaterial` uses
`#[uniform]`, this can be notably inefficient with large numbers of
materials.

This patch introduces a new attribute on `AsBindGroup`, `#[data]`, which
works identically to `#[uniform]` except that it concatenates all the
data into a single buffer that the material bind group allocator itself
manages. It also converts `StandardMaterial` to use this new
functionality. This effectively provides the "material data in arrays"
feature.
2025-02-24 21:38:55 +00:00
Vic
a1717331e4
implement UniqueEntityArray (#17954)
# Objective

Continuation of #17589 and #16547.

`get_many` is last of the `many` methods with a missing `unique`
counterpart.
It both takes and returns arrays, thus necessitates a matching
`UniqueEntityArray` type!
Plus, some slice methods involve returning arrays, which are currently
missing from `UniqueEntitySlice`.

## Solution

Add the type, the related methods and trait impls.

Note that for this PR, we abstain from some methods/trait impls that
create `&mut UniqueEntityArray`, because it can be successfully
mem-swapped. This can potentially invalidate a larger slice, which is
the same reason we punted on some mutable slice methods in #17589. We
can follow-up on all of these together in a following PR.

The new `unique_array` module is not glob-exported, because the trait
alias `unique_array::IntoIter` would conflict with
`unique_vec::IntoIter`.
The solution for this is to make the various `unique_*` modules public,
which I intend to do in yet another PR.
2025-02-24 21:36:59 +00:00
Matty Weatherley
1cbaabaa64
Incorporate OIT into MeshPipelineKey used by the LineGizmoPipeline (#17946)
# Objective

Fixes #17945 

## Solution

Check if the view being extracted has OIT enabled and incorporate the
associated bit into the mesh pipeline key.

I basically have no idea what's going on in the renderer, so let me know
if I missed something, which is extraordinarily possible.

## Testing

I modified the `order_independent_transparency` example to put
everything on the default render layer and render a gizmo at the origin.
Previously, this would cause the application to panic.
2025-02-24 21:31:54 +00:00
andriyDev
bb09751cf0
Fix observer/hook OnReplace and OnRemove triggering when removing a bundle even when the component is not present on the entity (#17942)
# Objective

- Fixes #17897.

## Solution

- When removing components, we filter the list of components in the
removed bundle based on whether they are actually in the archetype.

## Testing

- Added a test.
2025-02-24 21:25:31 +00:00
Florian Poncabaré
910e405ea9
Allow prepass to run without ATTRIBUTE_NORMAL (#17881)
# Objective

Allow prepass to run without ATTRIBUTE_NORMAL. 
This is needed for custom materials with non-standard vertex attributes.
For example a voxel material with manually packed vertex data.

Fixes #13054.

This PR covers the first part of the **stale** PR #13569 to only focus
on fixing #13054.

## Solution

- Only push normals `vertex_attributes` when the layout contains
`Mesh::ATTRIBUTE_NORMAL`

## Testing

- Did you test these changes? If so, how?
**Tested the fix on my own project with a mesh without normal
attribute.**
- 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?
**Prepass should not be blocked on a mesh without normal attributes
(with or without custom material).**
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  **Probably irrelevant, but Windows/Vulkan.**
2025-02-24 21:22:34 +00:00
Lucas Franca
7d7c43dd62
Add uv_transform to ColorMaterial (#17879)
# Objective

Implements and closes #17515

## Solution

Add `uv_transform` to `ColorMaterial`

## Testing

Create a example similar to `repeated_texture` but for `Mesh2d` and
`MeshMaterial2d<ColorMaterial>`

## Showcase


![image](https://github.com/user-attachments/assets/72943b9b-59a6-489a-96a2-f9c245f0dd53)

## Migration Guide

Add `uv_transform` field to constructors of `ColorMaterial`
2025-02-24 21:17:26 +00:00
notmd
f7b2a02224
Make sprite picking opt-in (#17842)
# Objective

Fix https://github.com/bevyengine/bevy/issues/17108
See
https://github.com/bevyengine/bevy/issues/17108#issuecomment-2653020889

## Solution

- Make the query match `&Pickable` instead `Option<&Pickable>`

## Testing

- Run the `sprite_picking` example and everything still work


## Migration Guide

- Sprite picking are now opt-in, make sure you insert `Pickable`
component when using sprite picking.
```diff
-commands.spawn(Sprite { .. } );
+commands.spawn((Sprite { .. }, Pickable::default());
```
2025-02-24 21:09:39 +00:00
Chanceler Shaffer
cb628516d1
Add core Error to InvalidDirectionError (#17820)
# Objective

Fixes #17761 

## Solution
- Added core error to InvalidDirectionError

## Testing

- Did you test these changes? If so, how?
- An added test that pulls in anyhow as a dev dependency to ensure the
conversion is accounted for in creation via From
- Are there any parts that need more testing?
  - I'm unsure but probably not due to being a trivial change 
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- I did not try a fully built version of Bevy. Relied purely on tests.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - Only windows

---------

Co-authored-by: Chanceler Shaffer <cshaffer2@lululemon.com>
Co-authored-by: Chanceler Shaffer <chancelershaffer@lululemon.com>
2025-02-24 21:04:22 +00:00
ickshonpe
d76c782f39
Remove camera from UiBatch (#17663)
# Objective

A `TransparentUI` phase's items all target the same camera so there is
no need to store the current camera entity in `UiBatch` and ending the
current `UiBatch` on camera changes is pointless as the camera doesn't
change.

## Solution

Remove the `camera` fields from `UiBatch`, `UiShadowsBatch` and
`UiTextureSliceBatch`.
Remove the camera changed check from `prepare_uinodes`.

## Testing
The `multiple_windows` and `split_screen` examples both render UI
elements to multiple cameras and can be used to test these changes.

The UI material plugin already didn't store the camera entity per batch
and worked fine without it.
2025-02-24 20:55:30 +00:00
Zachary Harrold
76e9bf9c99
Automatically enable portable-atomic when required (#17570)
# Objective

- Contributes to #15460
- Reduce quantity and complexity of feature gates across Bevy

## Solution

- Used `target_has_atomic` configuration variable to automatically
detect impartial atomic support and automatically switch to
`portable-atomic` over the standard library on an as-required basis.

## Testing

- CI

## Notes

To explain the technique employed here, consider getting `Arc` either
from `alloc::sync` _or_ `portable-atomic-util`. First, we can inspect
the `alloc` crate to see that you only have access to `Arc` _if_
`target_has_atomic = "ptr"`. We add a target dependency for this
particular configuration _inverted_:

```toml
[target.'cfg(not(target_has_atomic = "ptr"))'.dependencies]
portable-atomic-util = { version = "0.2.4", default-features = false }
```

This ensures we only have the dependency when it is needed, and it is
entirely excluded from the dependency graph when it is not. Next, we
adjust our configuration flags to instead of checking for `feature =
"portable-atomic"` to instead check for `target_has_atomic = "ptr"`:

```rust
// `alloc` feature flag hidden for brevity

#[cfg(not(target_has_atomic = "ptr"))]
use portable_atomic_util as arc;

#[cfg(target_has_atomic = "ptr")]
use alloc::sync as arc;

pub use arc::{Arc, Weak};
```

The benefits of this technique are three-fold:

1. For platforms without full atomic support, the functionality is
enabled automatically.
2. For platforms with atomic support, the dependency is never included,
even if a feature was enabled using `--all-features` (for example)
3. The `portable-atomic` feature no longer needs to virally spread to
all user-facing crates, it's instead something handled within
`bevy_platform_support` (with some extras where other dependencies also
need their features enabled).
2025-02-24 20:52:46 +00:00
andriyDev
7f14581495
Use explicitly added ApplyDeferred stages when computing automatically inserted sync points. (#16782)
# Objective

- The previous implementation of automatically inserting sync points did
not consider explicitly added sync points. This created additional sync
points. For example:

```
A-B
C-D-E
```

If `A` and `B` needed a sync point, and `D` was an `ApplyDeferred`, an
additional sync point would be generated between `A` and `B`.

```
A-D2-B
C-D -E
```

This can result in the following system ordering:
```
A-D2-(B-C)-D-E
```
Where only `B` and `C` run in parallel. If we could reuse `D` as the
sync point, we would get the following ordering:
```
(A-C)-D-(B-E)
```
Now we have two more opportunities for parallelism!

## Solution

- In the first pass, we:
    - Compute the number of sync points before each node
- This was already happening but now we consider `ApplyDeferred` nodes
as creating a sync point.
- Pick an arbitrary explicit `ApplyDeferred` node for each "sync point
index" that we can (some required sync points may be missing!)
- In the second pass, we:
- For each edge, if two nodes have a different number of sync points
before them then there must be a sync point between them.
- Look for an explicit `ApplyDeferred`. If one exists, use it as the
sync point.
    - Otherwise, generate a new sync point.

I believe this should also gracefully handle changes to the
`ScheduleGraph`. Since automatically inserted sync points are inserted
as systems, they won't look any different to explicit sync points, so
they are also candidates for "reusing" sync points.

One thing this solution does not handle is "deduping" sync points. If
you add 10 sync points explicitly, there will be at least 10 sync
points. You could keep track of all the sync points at the same
"distance" and then hack apart the graph to dedup those, but that could
be a follow-up step (and it's more complicated since you have to worry
about transferring edges between nodes).

## Testing

- Added a test to test the feature.
-  The existing tests from all our crates still pass.

## Showcase

- Automatically inserted sync points can now reuse explicitly inserted
`ApplyDeferred` systems! Previously, Bevy would add new sync points
between systems, ignoring the explicitly added sync points. This would
reduce parallelism of systems in some situations. Now, the parallelism
has been improved!
2025-02-24 20:51:34 +00:00
Lucien Menassol
7c7b1e9fc0
Load and convert RGB8 dds textures (#12952)
# Objective

- Closes #12944.

## Solution

- Load `R8G8B8` textures by transcoding to an rgba format since `wgpu`
does not support texture formats with 3 channels.
- Switch to erroring out instead of panicking on an invalid dds file.

---

## Changelog

### Added

- DDS Textures with the `R8G8B8` format are now supported. They require
an additional conversion step, so using `R8G8B8A8` or a similar format
is preferable for texture loading performance.
2025-02-24 20:45:56 +00:00
Zachary Harrold
5241e09671
Upgrade to Rust Edition 2024 (#17967)
# Objective

- Fixes #17960

## Solution

- Followed the [edition upgrade
guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)

## Testing

- CI

---

## Summary of Changes

### Documentation Indentation

When using lists in documentation, proper indentation is now linted for.
This means subsequent lines within the same list item must start at the
same indentation level as the item.

```rust
/* Valid */
/// - Item 1
///   Run-on sentence.
/// - Item 2
struct Foo;

/* Invalid */
/// - Item 1
///     Run-on sentence.
/// - Item 2
struct Foo;
```

### Implicit `!` to `()` Conversion

`!` (the never return type, returned by `panic!`, etc.) no longer
implicitly converts to `()`. This is particularly painful for systems
with `todo!` or `panic!` statements, as they will no longer be functions
returning `()` (or `Result<()>`), making them invalid systems for
functions like `add_systems`. The ideal fix would be to accept functions
returning `!` (or rather, _not_ returning), but this is blocked on the
[stabilisation of the `!` type
itself](https://doc.rust-lang.org/std/primitive.never.html), which is
not done.

The "simple" fix would be to add an explicit `-> ()` to system
signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`).
However, this is _also_ banned, as there is an existing lint which (IMO,
incorrectly) marks this as an unnecessary annotation.

So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ...
}` closuers into variables and give the variable an explicit type (e.g.,
`fn()`).

```rust
// Valid
let system: fn() = || todo!("Not implemented yet!");
app.add_systems(..., system);

// Invalid
app.add_systems(..., || todo!("Not implemented yet!"));
```

### Temporary Variable Lifetimes

The order in which temporary variables are dropped has changed. The
simple fix here is _usually_ to just assign temporaries to a named
variable before use.

### `gen` is a keyword

We can no longer use the name `gen` as it is reserved for a future
generator syntax. This involved replacing uses of the name `gen` with
`r#gen` (the raw-identifier syntax).

### Formatting has changed

Use statements have had the order of imports changed, causing a
substantial +/-3,000 diff when applied. For now, I have opted-out of
this change by amending `rustfmt.toml`

```toml
style_edition = "2021"
```

This preserves the original formatting for now, reducing the size of
this PR. It would be a simple followup to update this to 2024 and run
`cargo fmt`.

### New `use<>` Opt-Out Syntax

Lifetimes are now implicitly included in RPIT types. There was a handful
of instances where it needed to be added to satisfy the borrow checker,
but there may be more cases where it _should_ be added to avoid
breakages in user code.

### `MyUnitStruct { .. }` is an invalid pattern

Previously, you could match against unit structs (and unit enum
variants) with a `{ .. }` destructuring. This is no longer valid.

### Pretty much every use of `ref` and `mut` are gone

Pattern binding has changed to the point where these terms are largely
unused now. They still serve a purpose, but it is far more niche now.

### `iter::repeat(...).take(...)` is bad

New lint recommends using the more explicit `iter::repeat_n(..., ...)`
instead.

## Migration Guide

The lifetimes of functions using return-position impl-trait (RPIT) are
likely _more_ conservative than they had been previously. If you
encounter lifetime issues with such a function, please create an issue
to investigate the addition of `+ use<...>`.

## Notes

- Check the individual commits for a clearer breakdown for what
_actually_ changed.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-24 03:54:47 +00:00
JoshValjosh
2953db7f8f
impl Eq/PartialEq for MeshMaterial{2|3}d (#17990)
# Objective

`Eq`/`PartialEq` are currently implemented for `MeshMaterial{2|3}d` only
through the derive macro. Since we don't have perfect derive yet, the
impls are only present for `M: Eq` and `M: PartialEq`. On the other
hand, I want to be able to compare material components for my toy
reactivity project.

## Solution

Switch to manual `Eq`/`PartialEq` impl.

## Testing

Boy I hope this didn't break anything!
2025-02-23 23:58:10 +00:00
aloucks
8122b35ce2
Fix window freezing when dragged or resized on Windows (#18004)
# Objective

Fixes #17488

## Solution

The world update logic happened in the the `about_to_wait` winit window
callback, but this is is not correct as (1) the winit documentation
states that the callback should not be used for that purpose and (2) the
callback is not fired when the window is resized or being dragged.
However, that callback was used in #11245 to fix an iOS bug (which
caused the regression). The solution presented here is a workaround
until the event loop code can be re-written.

## Testing

I confirmed that the `eased_motion` example continued to be animated
when dragging or resizing the window.


https://github.com/user-attachments/assets/ffaf0abf-4cd7-479b-83e9-e1850aaf3513
2025-02-23 23:56:10 +00:00
JaySpruce
283654cf4d
Small Commands error handling cleanup (#17904)
- Remove references to the short-lived `CommandError` type.
- Add a sentence to the explanation of error handlers.
- Clean up spacing/linebreaks.
- Use `where` notation for command-related trait `impl`s to make the big
ones easier to parse.
2025-02-23 22:41:43 +00:00
AlephCubed
726d8ac4b0
Added top level reflect_documentation feature flag. (#17892)
Fixes #17811.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2025-02-23 21:21:50 +00:00
AlephCubed
5f86668bbb
Renamed EventWriter::send methods to write. (#17977)
Fixes #17856.

## Migration Guide
- `EventWriter::send` has been renamed to `EventWriter::write`.
- `EventWriter::send_batch` has been renamed to
`EventWriter::write_batch`.
- `EventWriter::send_default` has been renamed to
`EventWriter::write_default`.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-02-23 21:18:52 +00:00
Aevyrie
dba1f7a7b6
Parallel Transform Propagation (#17840)
# Objective

- Make transform propagation faster.

## Solution

- Work sharing worker threads
- Parallel tree traversal excluding leaves
- Second cache friendly wide pass over all leaves
- 3-10x faster than main

## Testing

- Tracy
- Caldera hotel is showing 3-7x faster on my M4 Max. Timing for bevy's
existing transform system shifts wildly run to run, so I don't know that
I would advertise a particular number. But this implementation is faster
in a... statistically significant way.

![image](https://github.com/user-attachments/assets/b4a48fc6-86b8-4b9c-8c5e-5b746c1d163b)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2025-02-23 20:43:09 +00:00
Patrick Walton
ad3817cc1b
Reallocate materials when they change. (#17979)
PR #17898 regressed this, causing much of #17970. This commit fixes the
issue by freeing and reallocating materials in the
`MaterialBindGroupAllocator` on change. Note that more efficiency is
possible, but I opted for the simple approach because (1) we should fix
this bug ASAP; (2) I'd like #17965 to land first, because that unlocks
the biggest potential optimization, which is not recreating the bind
group if it isn't necessary to do so.
2025-02-22 08:19:43 +00:00
Patrick Walton
465306bc5e
Reextract a mesh on the next frame if its material couldn't be prepared on the frame we first encountered it. (#17963)
We might not be able to prepare a material on the first frame we
encounter a mesh using it for various reasons, including that the
material hasn't been loaded yet or that preparing the material is
exceeding the per-frame cap on number of bytes to load. When this
happens, we currently try to find the material in the
`MaterialBindGroupAllocator`, fail, and then fall back to group 0, slot
0, the default `MaterialBindGroupId`, which is obviously incorrect.
Worse, we then fail to dirty the mesh and reextract it when we *do*
finish preparing the material, so the mesh will continue to be rendered
with an incorrect material.

This patch fixes both problems. In `collect_meshes_for_gpu_building`, if
we fail to find a mesh's material in the `MeshBindGroupAllocator`, then
we detect that case, bail out, and add it to a list,
`MeshesToReextractNextFrame`. On subsequent frames, we process all the
meshes in `MeshesToReextractNextFrame` as though they were changed. This
ensures both that we don't render a mesh if its material hasn't been
loaded and that we start rendering the mesh once its material does load.

This was first noticed in the intermittent Pixel Eagle failures in the
`testbed_3d` patch in #17898, although the problem has actually existed
for some time. I believe it just so happened that the changes to the
allocator in that PR caused the problem to appear more commonly than it
did before.
2025-02-22 08:19:25 +00:00
Patrick Walton
fffe623297
Fix bugs in the new non-bindless mesh material allocator. (#17980)
This patch fixes two bugs in the new non-bindless material allocator
that landed in PR #17898:

1. A debug assertion to prevent double frees had been flipped: we
checked to see whether the slot was empty before freeing, while we
should have checked to see whether the slot was full.

2. The non-bindless allocator returned `None` when querying a slab that
hadn't been prepared yet instead of returning a handle to that slab.
This resulted in a 1-frame delay when modifying materials. In the
`animated_material` example, this resulted in the meshes never showing
up at all, because that example changes every material every frame.

Together with #17979, this patch locally fixes the problems with
`animated_material` on macOS that were reported in #17970.
2025-02-22 06:29:00 +00:00
Rob Parrett
9046859ca8
Fix 1x1 dds textures being interpreted as 1-dimensional (#17890)
# Objective

Fixes #8615

## Solution

Bevy currently interprets 1x1 dds textures as 1-dimensional. I think it
might be more common for game engines to assume two dimensions in this
ambiguous case. [citation needed]

I reworked the dimension choosing logic to only use 1d if there's a
dimension > 1, and assume 2d otherwise. I kept the assumption that
compressed textures are probably 2d.

## Testing

Modified `sprite.rs` to use `Tex_0012_0.dds` from the linked issue.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-22 01:59:51 +00:00
DragonGamesStudios
a7cb061d6c
Use fully qualified syntax in assertions. (#17936)
# Objective

Fix #17924 

## Solution

Use fully qualified syntax (`usize::from` rather than `.into()`).

## Testing

Ran a build for the platform specified in the issue.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2025-02-22 01:58:54 +00:00
Carter Anderson
f3b2139e92
Only despawn scene entities still in the hierarchy (#17938)
Fixes #17883

# Objective + Solution

When doing normal scene root entity despawns (which are notably now
recursive), do not despawn instanced entities that are no longer in the
hierarchy.

(I would not classify this as a bug, but rather a behavior change)

## Migration Guide

If you previously relied on scene entities no longer in the hierarchy
being despawned when the scene root is despawned , use
`SceneSpawner::despawn_instance()` instead.
2025-02-22 01:53:08 +00:00
Christian Hughes
052b9d8261
Fix issue with define_label! instantiation in a 3rd party crate (#17958)
# Objective

Calling `define_label!` in a `no_std` 3rd party crate currently requires
the user to import `Box` themselves due to a non-fully-specified
reference to `Box`.

## Solution

Add a fully specified path for `Box` in the one location necessary, to
match all of the other cases.
2025-02-21 06:13:36 +00:00
Patrick Walton
4880a231de
Implement occlusion culling for directional light shadow maps. (#17951)
Two-phase occlusion culling can be helpful for shadow maps just as it
can for a prepass, in order to reduce vertex and alpha mask fragment
shading overhead. This patch implements occlusion culling for shadow
maps from directional lights, when the `OcclusionCulling` component is
present on the entities containing the lights. Shadow maps from point
lights are deferred to a follow-up patch. Much of this patch involves
expanding the hierarchical Z-buffer to cover shadow maps in addition to
standard view depth buffers.

The `scene_viewer` example has been updated to add `OcclusionCulling` to
the directional light that it creates.

This improved the performance of the rend3 sci-fi test scene when
enabling shadows.
2025-02-21 05:56:15 +00:00
Patrick Walton
28441337bb
Use global binding arrays for bindless resources. (#17898)
Currently, Bevy's implementation of bindless resources is rather
unusual: every binding in an object that implements `AsBindGroup` (most
commonly, a material) becomes its own separate binding array in the
shader. This is inefficient for two reasons:

1. If multiple materials reference the same texture or other resource,
the reference to that resource will be duplicated many times. This
increases `wgpu` validation overhead.

2. It creates many unused binding array slots. This increases `wgpu` and
driver overhead and makes it easier to hit limits on APIs that `wgpu`
currently imposes tight resource limits on, like Metal.

This PR fixes these issues by switching Bevy to use the standard
approach in GPU-driven renderers, in which resources are de-duplicated
and passed as global arrays, one for each type of resource.

Along the way, this patch introduces per-platform resource limits and
bumps them from 16 resources per binding array to 64 resources per bind
group on Metal and 2048 resources per bind group on other platforms.
(Note that the number of resources per *binding array* isn't the same as
the number of resources per *bind group*; as it currently stands, if all
the PBR features are turned on, Bevy could pack as many as 496 resources
into a single slab.) The limits have been increased because `wgpu` now
has universal support for partially-bound binding arrays, which mean
that we no longer need to fill the binding arrays with fallback
resources on Direct3D 12. The `#[bindless(LIMIT)]` declaration when
deriving `AsBindGroup` can now simply be written `#[bindless]` in order
to have Bevy choose a default limit size for the current platform.
Custom limits are still available with the new
`#[bindless(limit(LIMIT))]` syntax: e.g. `#[bindless(limit(8))]`.

The material bind group allocator has been completely rewritten. Now
there are two allocators: one for bindless materials and one for
non-bindless materials. The new non-bindless material allocator simply
maintains a 1:1 mapping from material to bind group. The new bindless
material allocator maintains a list of slabs and allocates materials
into slabs on a first-fit basis. This unfortunately makes its
performance O(number of resources per object * number of slabs), but the
number of slabs is likely to be low, and it's planned to become even
lower in the future with `wgpu` improvements. Resources are
de-duplicated with in a slab and reference counted. So, for instance, if
multiple materials refer to the same texture, that texture will exist
only once in the appropriate binding array.

To support these new features, this patch adds the concept of a
*bindless descriptor* to the `AsBindGroup` trait. The bindless
descriptor allows the material bind group allocator to probe the layout
of the material, now that an array of `BindGroupLayoutEntry` records is
insufficient to describe the group. The `#[derive(AsBindGroup)]` has
been heavily modified to support the new features. The most important
user-facing change to that macro is that the struct-level `uniform`
attribute, `#[uniform(BINDING_NUMBER, StandardMaterial)]`, now reads
`#[uniform(BINDLESS_INDEX, MATERIAL_UNIFORM_TYPE,
binding_array(BINDING_NUMBER)]`, allowing the material to specify the
binding number for the binding array that holds the uniform data.

To make this patch simpler, I removed support for bindless
`ExtendedMaterial`s, as well as field-level bindless uniform and storage
buffers. I intend to add back support for these as a follow-up. Because
they aren't in any released Bevy version yet, I figured this was OK.

Finally, this patch updates `StandardMaterial` for the new bindless
changes. Generally, code throughout the PBR shaders that looked like
`base_color_texture[slot]` now looks like
`bindless_2d_textures[material_indices[slot].base_color_texture]`.

This patch fixes a system hang that I experienced on the [Caldera test]
when running with `caldera --random-materials --texture-count 100`. The
time per frame is around 19.75 ms, down from 154.2 ms in Bevy 0.14: a
7.8× speedup.

[Caldera test]: https://github.com/DGriffin91/bevy_caldera_scene
2025-02-21 05:55:36 +00:00
Zachary Harrold
6bcb2b633b
Remove unused #[must_used] (#17959)
# Objective

- Fixed CI compilation failure on Rust Nightly 1.87 due to [this
PR](https://github.com/rust-lang/rust/pull/136923)

## Solution

- Removed unused `#[must_use]`

## Testing

- cargo +nightly check --target wasm32-unknown-unknown -Z
build-std=std,panic_abort
2025-02-21 05:39:16 +00:00
Patrick Walton
8de6b16e9d
Implement occlusion culling for the deferred rendering pipeline. (#17934)
Deferred rendering currently doesn't support occlusion culling. This PR
implements it in a straightforward way, mirroring what we already do for
the non-deferred pipeline.

On the rend3 sci-fi base test scene, this resulted in roughly a 2×
speedup when applied on top of my other patches. For that scene, it was
useful to add another option, `--add-light`, which forces the addition
of a shadow-casting light, to the scene viewer, which I included in this
patch.
2025-02-20 12:54:27 +00:00
Patrick Walton
f15437e4dc
Rewrite the multidrawable batch set builder for performance. (#17923)
This commit restructures the multidrawable batch set builder for better
performance in various ways:

* The bin traversal is optimized to make the best use of the CPU cache.

* The inner loop that iterates over the bins, which is the hottest part
of `batch_and_prepare_binned_render_phase`, has been shrunk as small as
possible.

* Where possible, multiple elements are added to or reserved from GPU
buffers as a batch instead of one at a time.

* Methods that LLVM wasn't inlining have been marked `#[inline]` where
doing so would unlock optimizations.

This code has also been refactored to avoid duplication between the
logic for indexed and non-indexed meshes via the introduction of a
`MultidrawableBatchSetPreparer` object.

Together, this improved the `batch_and_prepare_binned_render_phase` time
on Caldera by approximately 2×.

Eventually, we should optimize the batchable-but-not-multidrawable and
unbatchable logic as well, but these meshes are much rarer, so in the
interests of keeping this patch relatively small I opted to leave those
to a follow-up.
2025-02-20 11:45:47 +00:00
Máté Homolya
9e11e96a59
Fix false positive GPU frustum culling (#17939)
# Objective

Fix incorrect mesh culling where objects (particularly directional
shadows) were being incorrectly culled during the early preprocessing
phase. The issue manifested specifically on Apple M1 GPUs but not on
newer devices like the M4. The bug was in the
`view_frustum_intersects_obb` function, where including the w component
(plane distance) in the dot product calculations led to false positive
culling results. This caused objects to be incorrectly culled before
shadow casting could begin.

## Issue Details
The problem of missing shadows is reproducible on Apple M1 GPUs as of
this commit (bisected):

```
00722b8d0 Make indirect drawing opt-out instead of opt-in, enabling multidraw by default. (#16757)
```

and as recent as this commit:

```
c818c9214 Add option to animate materials in many_cubes (#17927)
```

- The frustum culling calculation incorrectly included the w component
(plane distance) when transforming basis vectors
- The relative radius calculation should only consider directional
transformation (xyz), not positional information (w)
- This caused false positive culling specifically on M1 devices likely
due to different device-specific floating-point behavior
- When objects were incorrectly culled, `early_instance_count` never
incremented, leading to missing geometry in the shadow pass

## Testing

- Tested on M1 and M4 devices to verify the fix
- Verified shadows and geometry render correctly on both platforms
- Confirmed the solution matches the existing Rust implementation's
behavior for calculating the relative radius:
c818c92143/crates/bevy_render/src/primitives/mod.rs (L77-L87)
- The fix resolves a mathematical error in the frustum culling
calculation while maintaining correct culling behavior across all
platforms.

---

## Showcase

`c818c9214`
<img width="1284" alt="c818c9214"
src="https://github.com/user-attachments/assets/fe1c7ea9-b13d-422e-b12d-f1cd74475213"
/>

`mate-h/frustum-cull-fix`
<img width="1283" alt="frustum-cull-fix"
src="https://github.com/user-attachments/assets/8a9ccb2a-64b6-4d5e-a17d-ac4798da5b51"
/>
2025-02-20 05:35:21 +00:00
Frank
ed62e59114
Shader validation enum (#17824)
# Objective

Make checked vs unchecked shaders configurable
Fixes #17786 

## Solution

Added `ValidateShaders` enum to `Shader` and added
`create_and_validate_shader_module` to `RenderDevice`

## Testing

I tested the shader examples locally and they all worked. I'd like to
write a few tests to verify but am unsure how to start.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-20 04:06:46 +00:00
Patrick Walton
73970d0c12
Don't mark newly-hidden meshes invisible until all visibility-determining systems run. (#17922)
The `check_visibility` system currently follows this algorithm:

1. Store all meshes that were visible last frame in the
`PreviousVisibleMeshes` set.

2. Determine which meshes are visible. For each such visible mesh,
remove it from `PreviousVisibleMeshes`.

3. Mark all meshes that remain in `PreviousVisibleMeshes` as invisible.

This algorithm would be correct if the `check_visibility` were the only
system that marked meshes visible. However, it's not: the shadow-related
systems `check_dir_light_mesh_visibility` and
`check_point_light_mesh_visibility` can as well. This results in the
following sequence of events for meshes that are in a shadow map but
*not* visible from a camera:

A. `check_visibility` runs, finds that no camera contains these meshes,
   and marks them hidden, which sets the changed flag.

B. `check_dir_light_mesh_visibility` and/or
   `check_point_light_mesh_visibility` run, discover that these meshes
   are visible in the shadow map, and marks them as visible, again
   setting the `ViewVisibility` changed flag.

C. During the extraction phase, the mesh extraction system sees that
   `ViewVisibility` is changed and re-extracts the mesh.

This is inefficient and results in needless work during rendering.

This patch fixes the issue in two ways:

* The `check_dir_light_mesh_visibility` and
`check_point_light_mesh_visibility` systems now remove meshes that they
discover from `PreviousVisibleMeshes`.

* Step (3) above has been moved from `check_visibility` to a separate
system, `mark_newly_hidden_entities_invisible`. This system runs after
all visibility-determining systems, ensuring that
`PreviousVisibleMeshes` contains only those meshes that truly became
invisible on this frame.

This fix dramatically improves the performance of [the Caldera
benchmark], when combined with several other patches I've submitted.

[the Caldera benchmark]:
https://github.com/DGriffin91/bevy_caldera_scene
2025-02-18 09:35:22 +00:00
Patrick Walton
0517b9621b
Fix motion vector computation after #17688. (#17717)
PR #17688 broke motion vector computation, and therefore motion blur,
because it enabled retention of `MeshInputUniform`s, and
`MeshInputUniform`s contain the indices of the previous frame's
transform and the previous frame's skinned mesh joint matrices. On frame
N, if a `MeshInputUniform` is retained on GPU from the previous frame,
the `previous_input_index` and `previous_skin_index` would refer to the
indices for frame N - 2, not the index for frame N - 1.

This patch fixes the problems. It solves these issues in two different
ways, one for transforms and one for skins:

1. To fix transforms, this patch supplies the *frame index* to the
shader as part of the view uniforms, and specifies which frame index
each mesh's previous transform refers to. So, in the situation described
above, the frame index would be N, the previous frame index would be N -
1, and the `previous_input_frame_number` would be N - 2. The shader can
now detect this situation and infer that the mesh has been retained, and
can therefore conclude that the mesh's transform hasn't changed.

2. To fix skins, this patch replaces the explicit `previous_skin_index`
with an invariant that the index of the joints for the current frame and
the index of the joints for the previous frame are the same. This means
that the `MeshInputUniform` never has to be updated even if the skin is
animated. The downside is that we have to copy joint matrices from the
previous frame's buffer to the current frame's buffer in
`extract_skins`.

The rationale behind (2) is that we currently have no mechanism to
detect when joints that affect a skin have been updated, short of
comparing all the transforms and setting a flag for
`extract_meshes_for_gpu_building` to consume, which would regress
performance as we want `extract_skins` and
`extract_meshes_for_gpu_building` to be able to run in parallel.

To test this change, use `cargo run --example motion_blur`.
2025-02-18 09:34:19 +00:00
Patrick Walton
5e569af2d0
Make the specialized pipeline cache two-level. (#17915)
Currently, the specialized pipeline cache maps a (view entity, mesh
entity) tuple to the retained pipeline for that entity. This causes two
problems:

1. Using the view entity is incorrect, because the view entity isn't
stable from frame to frame.

2. Switching the view entity to a `RetainedViewEntity`, which is
necessary for correctness, significantly regresses performance of
`specialize_material_meshes` and `specialize_shadows` because of the
loss of the fast `EntityHash`.

This patch fixes both problems by switching to a *two-level* hash table.
The outer level of the table maps each `RetainedViewEntity` to an inner
table, which maps each `MainEntity` to its pipeline ID and change tick.
Because we loop over views first and, within that loop, loop over
entities visible from that view, we hoist the slow lookup of the view
entity out of the inner entity loop.

Additionally, this patch fixes a bug whereby pipeline IDs were leaked
when removing the view. We still have a problem with leaking pipeline
IDs for deleted entities, but that won't be fixed until the specialized
pipeline cache is retained.

This patch improves performance of the [Caldera benchmark] from 7.8×
faster than 0.14 to 9.0× faster than 0.14, when applied on top of the
global binding arrays PR, #17898.

[Caldera benchmark]: https://github.com/DGriffin91/bevy_caldera_scene
2025-02-18 07:23:33 +00:00
Patrick Walton
8976a45199
Retain skins from frame to frame. (#17818)
Currently, Bevy rebuilds the buffer containing all the transforms for
joints every frame, during the extraction phase. This is inefficient in
cases in which many skins are present in the scene and their joints
don't move, such as the Caldera test scene.

To address this problem, this commit switches skin extraction to use a
set of retained GPU buffers with allocations managed by the offset
allocator. I use fine-grained change detection in order to determine
which skins need updating. Note that the granularity is on the level of
an entire skin, not individual joints. Using the change detection at
that level would yield poor performance in common cases in which an
entire skin is animated at once. Also, this patch yields additional
performance from the fact that changing joint transforms no longer
requires the skinned mesh to be re-extracted.

Note that this optimization can be a double-edged sword. In
`many_foxes`, fine-grained change detection regressed the performance of
`extract_skins` by 3.4x. This is because every joint is updated every
frame in that example, so change detection is pointless and is pure
overhead. Because the `many_foxes` workload is actually representative
of animated scenes, this patch includes a heuristic that disables
fine-grained change detection if the number of transformed entities in
the frame exceeds a certain fraction of the total number of joints.
Currently, this threshold is set to 25%. Note that this is a crude
heuristic, because it doesn't distinguish between the number of
transformed *joints* and the number of transformed *entities*; however,
it should be good enough to yield the optimum code path most of the
time.

Finally, this patch fixes a bug whereby skinned meshes are actually
being incorrectly retained if the buffer offsets of the joints of those
skinned meshes changes from frame to frame. To fix this without
retaining skins, we would have to re-extract every skinned mesh every
frame. Doing this was a significant regression on Caldera. With this PR,
by contrast, mesh joints stay at the same buffer offset, so we don't
have to update the `MeshInputUniform` containing the buffer offset every
frame. This also makes PR #17717 easier to implement, because that PR
uses the buffer offset from the previous frame, and the logic for
calculating that is simplified if the previous frame's buffer offset is
guaranteed to be identical to that of the current frame.

On Caldera, this patch reduces the time spent in `extract_skins` from
1.79 ms to near zero. On `many_foxes`, this patch regresses the
performance of `extract_skins` by approximately 10%-25%, depending on
the number of foxes. This has only a small impact on frame rate.
2025-02-18 00:56:04 +00:00
Patrick Walton
8f36106f9e
Split out the IndirectParametersMetadata into CPU-populated and GPU-populated buffers. (#17863)
The GPU can fill out many of the fields in `IndirectParametersMetadata`
using information it already has:

* `early_instance_count` and `late_instance_count` are always
initialized to zero.

* `mesh_index` is already present in the work item buffer as the
`input_index` of the first work item in each batch.

This patch moves these fields to a separate buffer, the *GPU indirect
parameters metadata* buffer. That way, it avoids having to write them on
CPU during `batch_and_prepare_binned_render_phase`. This effectively
reduces the number of bits that that function must write per mesh from
160 to 64 (in addition to the 64 bits per mesh *instance*).

Additionally, this PR refactors `UntypedPhaseIndirectParametersBuffers`
to add another layer, `MeshClassIndirectParametersBuffers`, which allows
abstracting over the buffers corresponding indexed and non-indexed
meshes. This patch doesn't make much use of this abstraction, but
forthcoming patches will, and it's overall a cleaner approach.

This didn't seem to have much of an effect by itself on
`batch_and_prepare_binned_render_phase` time, but subsequent PRs
dependent on this PR yield roughly a 2× speedup.
2025-02-18 00:53:44 +00:00
Robert Swain
8e783d347f
Sweep old entities from 2D binned render phases (#17903)
# Objective

- #17787 removed sweeping of binned render phases from 2D by accident
due to them not using the `BinnedRenderPhasePlugin`.
- Fixes #17885 

## Solution

- Schedule `sweep_old_entities` in `QueueSweep` like
`BinnedRenderPhasePlugin` does, but for 2D where that plugin is not
used.

## Testing

Tested with the modified `shader_defs` example in #17885 .
2025-02-17 19:31:56 +00:00
AlephCubed
45c266658b
Fixed bevy_image and bevy_gltf failing to compile with some features. (#17887)
Fixes #17290.
<details>
  <summary>Compilation errors before fix</summary>

`cargo clippy --tests --all-features --package bevy_image`:
```rust
error[E0061]: this function takes 7 arguments but 6 arguments were supplied
   --> crates/bevy_core_pipeline/src/tonemapping/mod.rs:451:5
    |
451 |     Image::from_buffer(
    |     ^^^^^^^^^^^^^^^^^^
...
454 |         bytes,
    |         ----- argument #1 of type `std::string::String` is missing
    |
note: associated function defined here
   --> /Users/josiahnelson/Desktop/Programming/Rust/bevy/crates/bevy_image/src/image.rs:930:12
    |
930 |     pub fn from_buffer(
    |            ^^^^^^^^^^^
help: provide the argument
    |
451 |     Image::from_buffer(/* std::string::String */, bytes, image_type, CompressedImageFormats::NONE, false, image_sampler, RenderAssetUsages::RENDER_WORLD)
    |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
`cargo clippy --tests --all-features --package bevy_gltf`:
```rust
error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_channel`
    --> crates/bevy_gltf/src/loader.rs:1343:13
     |
1343 |             specular_channel: specular.specular_channel,
     |             ^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_texture`
    --> crates/bevy_gltf/src/loader.rs:1345:13
     |
1345 |             specular_texture: specular.specular_texture,
     |             ^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_tint_channel`
    --> crates/bevy_gltf/src/loader.rs:1351:13
     |
1351 |             specular_tint_channel: specular.specular_color_channel,
     |             ^^^^^^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_tint_texture`
    --> crates/bevy_gltf/src/loader.rs:1353:13
     |
1353 |             specular_tint_texture: specular.specular_color_texture,
     |             ^^^^^^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others
```
</details>
2025-02-17 05:10:13 +00:00
Rob Parrett
4045b91091
Fix dds feature enabling bevy_gltf (#17888)
# Objective

Fixes #17022

## Solution

Only enable `bevy_gltf/dds` if `bevy_gltf` is already enabled.

## Testing

Tested with empty project

```toml
[dependencies]
bevy = { version = "0.16.0-dev", path = "../bevy", default-features = false, features = [
    "dds",
] }
```

### Before

```
 cargo tree --depth 1 -i bevy_gltf
bevy_gltf v0.16.0-dev (/Users/robparrett/src/bevy/crates/bevy_gltf)
└── bevy_internal v0.16.0-dev (/Users/robparrett/src/bevy/crates/bevy_internal)
```

### After

```
 cargo tree --depth 1 -i bevy_gltf
warning: nothing to print.

To find dependencies that require specific target platforms, try to use option `--target all` first, and then narrow your search scope accordingly.
```
2025-02-17 03:33:17 +00:00
Alice Cecile
be3c6f7578
Improve the docs for ChildOf and Children (#17886)
# Context

Renaming `Parent` to `ChildOf` in #17247 has been contentious. While
those users concerns are valid (especially around legibility of code
IMO!), @cart [has
decided](https://discord.com/channels/691052431525675048/749335865876021248/1340434322833932430)
to stick with the new name.

> In general this conversation is unsurprising to me, as it played out
essentially the same way when I asked for opinions in my PR. There are
strong opinions on both sides. Everyone is right in their own way.
> 
> I chose ChildOf for the following reasons:
> 
> 1. I think it derives naturally from the system we have built, the
concepts we have chosen, and how we generally name the types that
implement a trait in Rust. This is the name of the type implementing
Relationship. We are adding that Relationship component to a given
entity (whether it "is" the relationship or "has" the relationship is
kind of immaterial ... we are naming the relationship that it "is" or
"has"). What is the name of the relationship that a child has to its
parent? It is a "child" of the parent of course!
> 2. In general the non-parent/child relationships I've seen in the wild
generally benefit from (or need to) use the naming convention in (1)
(aka calling the Relationship the name of the relationship the entity
has). Many relationships don't have an equivalent to the Parent/Child
name concept.
> 3. I do think we could get away with using (1) for pretty much
everything else and special casing Parent/Children. But by embracing the
naming convention, we help establish that this is in fact a pattern, and
we help prime people to think about these things in a consistent way.
Consistency and predictability is a generally desirable property. And
for something as divisive and polarizing as relationship naming, I think
drawing a hard line in the sand is to the benefit of the community as a
whole.
> 4. I believe the fact that we dont see as much of the XOf naming style
elsewhere is to our benefit. When people see things in that style, they
are primed to think of them as relationships (after some exposure to
Bevy and the ecosystem). I consider this a useful hint.
> 5. Most of the practical confusion from using ChildOf seems to be from
calling the value of the target field we read from the relationship
child_of. The name of the target field should be parent (we could even
consider renaming child_of.0 to child_of.parent for clarity). I suspect
that existing Bevy users renaming their existing code will feel the most
friction here, as this requires a reframing. Imo it is natural and
expected to receive pushback from these users hitting this case.

## Objective

The new documentation doesn't do a particularly good job at quickly
explaining the meaning of each component or how to work with them;
making a tricky migration more painful and slowing down new users as
they learn about some of the most fundamental types in Bevy.

## Solution

1. Clearly explain what each component does in the very first line,
assuming no background knowledge. This is the first relationships that
99% of users will encounter, so explaining that they are relationships
is unhelpful as an introduction.
2. Add doc aliases for the rejected `IsParent`/`IsChild`/`Parent` names,
to improve autocomplete and doc searching.
3. Do some assorted docs cleanup while we're here.

---------

Co-authored-by: Eagster <79881080+ElliottjPierce@users.noreply.github.com>
2025-02-17 01:46:11 +00:00
JaySpruce
ee44560523
Add EntityDoesNotExistError, replace cases of Entity as an error, do some easy Resultification (#17855)
## Objective
There's no general error for when an entity doesn't exist, and some
methods are going to need one when they get Resultified. The closest
thing is `EntityFetchError`, but that error has a slightly more specific
purpose.

## Solution
- Added `EntityDoesNotExistError`.
  - Contains `Entity` and `EntityDoesNotExistDetails`.
- Changed `EntityFetchError` and `QueryEntityError`:
- Changed `NoSuchEntity` variant to wrap `EntityDoesNotExistError` and
renamed the variant to `EntityDoesNotExist`.
- Renamed `EntityFetchError` to `EntityMutableFetchError` to make its
purpose clearer.
- Renamed `TryDespawnError` to `EntityDespawnError` to make it more
general.
- Changed `World::inspect_entity` to return `Result<[ok],
EntityDoesNotExistError>` instead of panicking.
- Changed `World::get_entity` and `WorldEntityFetch::fetch_ref` to
return `Result<[ok], EntityDoesNotExistError>` instead of `Result<[ok],
Entity>`.
- Changed `UnsafeWorldCell::get_entity` to return
`Result<UnsafeEntityCell, EntityDoesNotExistError>` instead of
`Option<UnsafeEntityCell>`.

## Migration Guide
- `World::inspect_entity` now returns `Result<impl Iterator<Item =
&ComponentInfo>, EntityDoesNotExistError>` instead of `impl
Iterator<Item = &ComponentInfo>`.
- `World::get_entity` now returns `EntityDoesNotExistError` as an error
instead of `Entity`. You can still access the entity's ID through the
error's `entity` field.
- `UnsafeWorldCell::get_entity` now returns `Result<UnsafeEntityCell,
EntityDoesNotExistError>` instead of `Option<UnsafeEntityCell>`.
2025-02-16 21:59:46 +00:00
Patrick Walton
137878ac35
Replace BufferVec<PreprocessWorkItem> with RawBufferVec<PreprocessWorkItem>. (#17862)
Appending to these vectors is performance-critical in
`batch_and_prepare_binned_render_phase`, so `RawBufferVec`, which
doesn't have the overhead of `encase`, is more appropriate.
2025-02-16 19:59:29 +00:00
Patrick Walton
7801ed315f
Don't delete the buffers that batch building writes into every frame. (#17841)
The `collect_buffers_for_phase` system tries to reuse these buffers, but
its efforts are stymied by the fact that
`clear_batched_gpu_instance_buffers` clears the containing hash table
and therefore frees the buffers. This patch makes
`clear_batched_gpu_instance_buffers` stop doing that so that the
allocations can be reused.
2025-02-16 19:58:03 +00:00
Chris Russell
794bf6a332
Move implementations of Query methods from QueryState to Query. (#17822)
# Objective

Simplify the API surface by removing duplicated functionality between
`Query` and `QueryState`.

Reduce the amount of `unsafe` code required in `QueryState`.  

This is a follow-up to #15858.

## Solution

Move implementations of `Query` methods from `QueryState` to `Query`.
Instead of the original methods being on `QueryState`, with `Query`
methods calling them by passing the individual parameters, the original
methods are now on `Query`, with `QueryState` methods calling them by
constructing a `Query`.

This also adds two `_inner` methods that were missed in #15858:
`iter_many_unique_inner` and `single_inner`.

One goal here is to be able to deprecate and eventually remove many of
the methods on `QueryState`, reducing the overall API surface. (I
expected to do that in this PR, but this change was large enough on its
own!) Now that the `QueryState` methods each consist of a simple
expression like `self.query(world).get_inner(entity)`, a future PR can
deprecate some or all of them with simple migration instructions.

The other goal is to reduce the amount of `unsafe` code. The current
implementation of a read-only method like `QueryState::get` directly
calls the `unsafe fn get_unchecked_manual` and needs to repeat the proof
that `&World` has enough access. With this change, `QueryState::get` is
entirely safe code, with the proof that `&World` has enough access done
by the `query()` method and shared across all read-only operations.

## Future Work

The next step will be to mark the `QueryState` methods as
`#[deprecated]` and migrate callers to the methods on `Query`.
2025-02-16 19:57:43 +00:00
Chris Russell
0a32450715
Support using FilteredResources with ReflectResource. (#15624)
# Objective

Support accessing resources using reflection when using
`FilteredResources` in a dynamic system. This is similar to how
components can be queried using reflection when using
`FilteredEntityRef|Mut`.

## Solution

Change `ReflectResource` from taking `&World` and `&mut World` to taking
`impl Into<FilteredResources>` and `impl Into<FilteredResourcesMut>`,
similar to how `ReflectComponent` takes `impl Into<FilteredEntityRef>`
and `impl Into<FilteredEntityMut>`. There are `From` impls that ensure
code passing `&World` and `&mut World` continues to work as before.

## Migration Guide

If you are manually creating a `ReflectComponentFns` struct, the
`reflect` function now takes `FilteredResources` instead `&World`, and
there is a new `reflect_mut` function that takes `FilteredResourcesMut`.
2025-02-16 19:56:19 +00:00
Máté Homolya
d7fd00a8b9
Bump Rust tracy client version (#17867)
# Objective

- Fix the tracy debugger working with the latest version of bevy.
- Broken experience for users of the latest version of the tracy
profiler.


![image](https://github.com/user-attachments/assets/03a5937f-0bcb-438b-95dc-c904f76eb203)


## Solution

- Bump the dependencies of tracy and recompile , works well with the
latest tracy version.
- Used the matrix available at
https://github.com/nagisa/rust_tracy_client

## Testing

- Tested changes using the tracy GUI client and running a few examples
with `--features "trace_tracy"`

---

## Showcase

Screenshot shows tracy profiler v0.11.1

<img width="1651" alt="Screenshot 2025-02-14 at 6 57 10 PM"
src="https://github.com/user-attachments/assets/835575a6-db44-4abb-ac68-18a23e937c19"
/>
2025-02-15 21:07:40 +00:00
sam edelsten
7935c7e95f
Update picking docs to include position space (#17859)
# Objective

Add reference to reported position space in picking backend docs.

Fixes #17844 

## Solution

Add explanatory docs to the implementation notes of each picking
backend.

## Testing

`cargo r -p ci -- doc-check` & `cargo r -p ci -- lints`
2025-02-15 19:08:12 +00:00
Alexandra
253cc6a77b
Add TypeRegistry::register_by_val (#17817)
# Objective

It is impossible to register a type with `TypeRegistry::register` if the
type is unnameable (in the current scope).

## Solution

Add `TypeRegistry::register_by_val` which mirrors std's `size_of_val`
and friends.

## Testing

There's a doc test (unrelated but there seem to be some pre-existing
broken doc links in `bevy_reflect`).
2025-02-15 19:07:01 +00:00
Patrick Walton
3c9e696faa
Actually add objects to the scene buffers in sorted render phases. (#17849)
There was nonsense code in `batch_and_prepare_sorted_render_phase` that
created temporary buffers to add objects to instead of using the correct
ones. I think this was debug code. This commit removes that code in
favor of writing to the actual buffers.

Closes #17846.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-14 15:01:27 +00:00
Patrick Walton
6b837dd297
Remove prepasses from the render world when they're removed from the main world. (#17565)
This makes switching rendering modes in `deferred_rendering` work again.

Closes #16679.
2025-02-14 06:43:35 +00:00
Alice Cecile
0f1c75796b
Fill out some missing docs for bevy_assets (#17829)
# Objective

`bevy_assets` has long been unapproachable for contributors and users.
More and better documentation would help that.

We're gradually moving towards globally denying missing docs (#3492)! 
However, writing all of the hundreds of missing doc strings in a single
go will be miserable to review.

## Solution

Remove the allow for missing docs temporarily, and then pick some easy
missing doc warnings largely at random to tackle.

Stop when the change set is starting to feel intimidating.
2025-02-13 21:08:09 +00:00
Patrick Walton
101fcaa619
Combine output_index and indirect_parameters_index into one field in PreprocessWorkItem. (#17853)
The `output_index` field is only used in direct mode, and the
`indirect_parameters_index` field is only used in indirect mode.
Consequently, we can combine them into a single field, reducing the size
of `PreprocessWorkItem`, which
`batch_and_prepare_{binned,sorted}_render_phase` must construct every
frame for every mesh instance, from 96 bits to 64 bits.
2025-02-13 20:10:14 +00:00
Vic
05e61d64f5
implement par_iter_many and par_iter_many_unique (#17815)
# Objective

Continuation of #16547.

We do not yet have parallel versions of `par_iter_many` and
`par_iter_many_unique`. It is currently very painful to try and use
parallel iteration over entity lists. Even if a list is not long, each
operation might still be very expensive, and worth parallelizing.
Plus, it has been requested several times!

## Solution

Once again, we implement what we lack!

These parallel iterators collect their input entity list into a
`Vec`/`UniqueEntityVec`, then chunk that over the available threads,
inspired by the original `par_iter`.

Since no order guarantee is given to the caller, we could sort the input
list according to `EntityLocation`, but that would likely only be worth
it for very large entity lists.

There is some duplication which could likely be improved, but I'd like
to leave that for a follow-up.

## Testing

The doc tests on `for_each_init` of `QueryParManyIter` and
`QueryParManyUniqueIter`.
2025-02-13 19:49:41 +00:00
Alice Cecile
96a4028862
Improve clarity of existing bevy_assets documentation (#17830)
# Objective

While surveying the state of documentation for bevy_assets, I noticed a
few minor issues.

## Solution

Revise the docs to focus on clear explanations of core ideas and
cross-linking related objects.
2025-02-13 19:49:25 +00:00
ickshonpe
5ec59cf0b9
Add NodeImageMode to the UI prelude (#17848)
# Objective

Add `NodeImageMode` to `bevy_ui::prelude`.
2025-02-13 19:48:45 +00:00
Rob Parrett
2760692f88
Update typos to 1.29.6 (#17850)
# Objective

Update typos, fix new typos.

1.29.6 was just released to fix an
[issue](https://github.com/crate-ci/typos/issues/1228) where January's
corrections were not included in the binaries for the last release.

Reminder: typos can be tossed in the monthly [non-critical corrections
issue](https://github.com/crate-ci/typos/issues/1221).

## Solution

I chose to allow `implementors`, because a good argument seems to be
being made [here](https://github.com/crate-ci/typos/issues/1226) and
there is now a PR to address that.

## Discussion

Should I exclude `bevy_mikktspace`?

At one point I think we had an informal policy of "don't mess with
mikktspace until https://github.com/bevyengine/bevy/pull/9050 is merged"
but it doesn't seem like that is likely to be merged any time soon.

I think these particular corrections in mikktspace are fine because
- The same typo mistake seems to have been fixed in that PR
- The entire file containing these corrections was deleted in that PR

## Typo of the Month

correspindong -> corresponding
2025-02-13 19:44:47 +00:00
sam edelsten
610fe5109c
Update HitData position docs (#17833)
# Objective

Updates the now inaccurate position docs
Fixes #17832 

## Solution

From
`The position of the intersection in the world, if the data is available
from the backend.`
To
`The position reported by the backend, if the data is available.
Position data may be in any space (e.g. World space, Screen space, Local
space), specified by the backend providing it.`

## Testing

uhh reading :)
2025-02-13 06:20:57 +00:00
Patrick Walton
0ede857103
Build batches across phases in parallel. (#17764)
Currently, invocations of `batch_and_prepare_binned_render_phase` and
`batch_and_prepare_sorted_render_phase` can't run in parallel because
they write to scene-global GPU buffers. After PR #17698,
`batch_and_prepare_binned_render_phase` started accounting for the
lion's share of the CPU time, causing us to be strongly CPU bound on
scenes like Caldera when occlusion culling was on (because of the
overhead of batching for the Z-prepass). Although I eventually plan to
optimize `batch_and_prepare_binned_render_phase`, we can obtain
significant wins now by parallelizing that system across phases.

This commit splits all GPU buffers that
`batch_and_prepare_binned_render_phase` and
`batch_and_prepare_sorted_render_phase` touches into separate buffers
for each phase so that the scheduler will run those phases in parallel.
At the end of batch preparation, we gather the render phases up into a
single resource with a new *collection* phase. Because we already run
mesh preprocessing separately for each phase in order to make occlusion
culling work, this is actually a cleaner separation. For example, mesh
output indices (the unique ID that identifies each mesh instance on GPU)
are now guaranteed to be sequential starting from 0, which will simplify
the forthcoming work to remove them in favor of the compute dispatch ID.

On Caldera, this brings the frame time down to approximately 9.1 ms with
occlusion culling on.

![Screenshot 2025-02-08
210720](https://github.com/user-attachments/assets/44bed500-e323-4786-b40c-828b75bc7d3f)
2025-02-13 00:02:20 +00:00
Chris Russell
62c1812e72
Shorten the 'world lifetime returned from QueryLens::query(). (#17694)
# Objective

Fix unsoundness introduced by #15858. `QueryLens::query()` would hand
out a `Query` with the full `'w` lifetime, and the new `_inner` methods
would let the results outlive the `Query`. This could be used to create
aliasing mutable references, like

```rust
fn bad<'w>(mut lens: QueryLens<'w, EntityMut>, entity: Entity) {
    let one: EntityMut<'w> = lens.query().get_inner(entity).unwrap();
    let two: EntityMut<'w> = lens.query().get_inner(entity).unwrap();
    assert!(one.entity() == two.entity());
}
```

Fixes #17693 

## Solution

Restrict the `'world` lifetime in the `Query` returned by
`QueryLens::query()` to `'_`, the lifetime of the borrow of the
`QueryLens`.

The model here is that `Query<'w, 's, D, F>` and `QueryLens<'w, D, F>`
have permission to access their components for the lifetime `'w`. So
going from `&'a mut QueryLens<'w>` to `Query<'w, 'a>` would borrow the
permission only for the `'a` lifetime, but incorrectly give it out for
the full `'w` lifetime.

To handle any cases where users were calling `get_inner()` or
`iter_inner()` on the `Query` and expecting the full `'w` lifetime, we
introduce a new `QueryLens::query_inner()` method. This is only valid
for `ReadOnlyQueryData`, so it may safely hand out a copy of the
permission for the full `'w` lifetime. Since `get_inner()` and
`iter_inner()` were only valid on `ReadOnlyQueryData` prior to #15858,
that should cover any uses that relied on the longer lifetime.

## Migration Guide

Users of `QueryLens::query()` who were calling `get_inner()` or
`iter_inner()` will need to replace the call with
`QueryLens::query_inner()`.
2025-02-12 22:41:02 +00:00
Patrick Walton
5ff7062c1c
Switch bins from parallel key/value arrays to IndexMaps. (#17819)
Conceptually, bins are ordered hash maps. We currently implement these
as a list of keys with an associated hash map. But we already have a
data type that implements ordered hash maps directly: `IndexMap`. This
patch switches Bevy to use `IndexMap`s for bins. Because we're memory
bound, this doesn't affect performance much, but it is cleaner.
2025-02-12 22:39:04 +00:00
Andreas Monitzer
267a0d003c
Add ComponentId-taking functions to Entity{Ref,Mut}Except to mirror FilteredEntity{Ref,Mut} (#17800)
# Objective

Related to #17784. The ticket is actually about just getting rid of
`Entity{Ref,Mut}Except` in favor of `FilteredEntity{Ref,Mut}`, but I got
told the unification of Entity types is a bigger endeavor that has been
going on for a while now (as the "Pointing Fingers" working group) and I
should just add the functions I actually need in the meantime.

## Solution

This PR adds all of the functions necessary to access components by
TypeId or ComponentId instead of static types.

## Testing

> Did you test these changes? If so, how?

Haven't tested it yet, but the changes are mostly copy/paste from other
implementations in the same file, since there is a lot of duplicated
functionality there.

## Not a Migration Guide

There shouldn't be any breaking changes, it's just a few new functions
on existing types.

I had to shuffle around the lifetimes in `From<&EntityMutExcept<'a, B>>
for EntityRefExcept<'a, B>` (originally it was `From<&'a
EntityMutExcept<'_, B>> for EntityRefExcept<'_, B>`) to make the borrow
checker happy, but I don't think that this should have an impact on user
code (correct me if I'm wrong).
2025-02-12 18:34:35 +00:00
JMS55
2fd4cc4937
Meshlet texture atomics (#17765)
* Use texture atomics rather than buffer atomics for the visbuffer
(haven't tested perf on a raster-heavy scene yet)
* Unfortunately to clear the visbuffer we now need a compute pass to
clear it. Using wgpu's clear_texture function internally uses a buffer
-> image copy that's insanely expensive. Ideally it should be using
vkCmdClearColorImage, which I've opened an issue for
https://github.com/gfx-rs/wgpu/issues/7090. For now we'll have to stick
with a custom compute pass and all the extra code that brings.
* Faster resolve depth pass by discarding 0 depth pixels instead of
redundantly writing zero (2x faster for big depth textures like shadow
views)
2025-02-12 18:15:43 +00:00
JMS55
15b795d7d6
Use unchecked shaders for better performance (#17767)
# Objective
- Wgpu has some expensive code it injects into shaders to avoid the
possibility of things like infinite loops. Generally our shaders are
written by users who won't do this, so it just makes our shaders perform
worse.

## Solution

- Turn off the checks.
- We could try to conditionally keep them, but that complicates the code
and 99.9% of users won't want this.

## Migration Guide

- Bevy no longer turns on wgpu's runtime safety checks
https://docs.rs/wgpu/latest/wgpu/struct.ShaderRuntimeChecks.html. If you
were using Bevy with untrusted shaders, please file an issue.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-12 06:16:52 +00:00
Vic
153ce468ef
implement iterators that yield UniqueEntitySlice (#17796)
# Objective

Continuation of #17589 and #16547.

Slices have several methods that return iterators which themselves yield
slices, which we have not yet implemented.
An example use is `par_iter_many` style logic.

## Solution

Their implementation is rather straightforward, we simply delegate all
impls to `[T]`.
The resulting iterator types need their own wrappers in the form of
`UniqueEntitySliceIter` and `UniqueEntitySliceIterMut`.

We also add three free functions that cast slices of entity slices to
slices of `UniqueEntitySlice`.
These three should be sufficient, though infinite nesting is achievable
with a trait (like `TrustedEntityBorrow` works over infinite reference
nesting), should the need ever arise.
2025-02-12 03:59:56 +00:00
Mads Marquart
94deca81bf
Use target_abi = "sim" instead of ios_simulator feature (#17702)
## Objective

Get rid of a redundant Cargo feature flag.

## Solution

Use the built-in `target_abi = "sim"` instead of a custom Cargo feature
flag, which is set for the iOS (and visionOS and tvOS) simulator. This
has been stable since Rust 1.78.

In the future, some of this may become redundant if Wgpu implements
proper supper for the iOS Simulator:
https://github.com/gfx-rs/wgpu/issues/7057

CC @mockersf who implemented [the original
fix](https://github.com/bevyengine/bevy/pull/10178).

## Testing

- Open mobile example in Xcode.
- Launch the simulator.
- See that no errors are emitted.
- Remove the code cfg-guarded behind `target_abi = "sim"`.
- See that an error now happens.

(I haven't actually performed these steps on the latest `main`, because
I'm hitting an unrelated error (EDIT: It was
https://github.com/bevyengine/bevy/pull/17637). But tested it on
0.15.0).

---

## Migration Guide

> If you're using a project that builds upon the mobile example, remove
the `ios_simulator` feature from your `Cargo.toml` (Bevy now handles
this internally).
2025-02-11 23:01:26 +00:00
Patrick Walton
85b366a8a2
Cache MeshInputUniform indices in each RenderBin. (#17772)
Currently, we look up each `MeshInputUniform` index in a hash table that
maps the main entity ID to the index every frame. This is inefficient,
cache unfriendly, and unnecessary, as the `MeshInputUniform` index for
an entity remains the same from frame to frame (even if the input
uniform changes). This commit changes the `IndexSet` in the `RenderBin`
to an `IndexMap` that maps the `MainEntity` to `MeshInputUniformIndex`
(a new type that this patch adds for more type safety).

On Caldera with parallel `batch_and_prepare_binned_render_phase`, this
patch improves that function from 3.18 ms to 2.42 ms, a 31% speedup.
2025-02-11 22:38:52 +00:00
Patrick Walton
ce433955e6
Don't relocate the meshes when mesh slabs grow. (#17793)
Currently, when a mesh slab overflows, we recreate the allocator and
reinsert all the meshes that were in it in an arbitrary order. This can
result in the meshes moving around. Before `MeshInputUniform`s were
retained, this was slow but harmless, because the `MeshInputUniform`
that contained the positions of the vertex and index data in the slab
would be recreated every frame. However, with mesh retention, there's no
guarantee that the `MeshInputUniform`, which could be cached from the
previous frame, will reflect the new position of the mesh data within
the buffer if that buffer happened to grow. This manifested itself as
seeming mesh data corruption when adding many meshes dynamically to the
scene.

There are three possible ways that I could have fixed this that I can
see:

1. Invalidate and rebuild all the `MeshInputUniform`s belonging to all
meshes in a slab when that mesh grows.

2. Introduce a second layer of indirection so that the
`MeshInputUniform` points to a *mesh allocation table* that contains the
current locations of the data of each mesh.

3. Avoid moving meshes when reallocating the buffer.

To be efficient, option (1) would require scanning meshes to see if
their positions changed, a la
`mark_meshes_as_changed_if_their_materials_changed`. Option (2) would
add more runtime indirection and would require additional bookkeeping on
the part of the allocator.

Therefore, this PR chooses option (3), which was remarkably simple to
implement. The key is that the offset allocator happens to allocate
addresses from low addresses to high addresses. So all we have to do is
to *conceptually* allocate the full 512 MiB mesh slab as far as the
offset allocator is concerned, and grow the underlying backing store
from 1 MiB to 512 MiB as needed. In other words, the allocator now
allocates *virtual* GPU memory, and the actual backing slab resizes to
fit the virtual memory. This ensures that the location of mesh data
remains constant for the lifetime of the mesh asset, and we can remove
the code that reinserts meshes one by one when the slab grows in favor
of a single buffer copy.

Closes #17766.
2025-02-11 22:38:26 +00:00
François Mockers
7a62a4f604
gate get_tag behind ndef MESHLET_MESH_MATERIAL_PASS (#17809)
# Objective

- Fixes #17797 

## Solution

- `mesh` in `bevy_pbr::mesh_bindings` is behind a `ifndef
MESHLET_MESH_MATERIAL_PASS`. also gate `get_tag` which uses this `mesh`

## Testing

- Run the meshlet example
2025-02-11 22:36:17 +00:00
RobWalt
aa8793f6b4
Add ways to configure EasingFunction::Steps via new StepConfig (#17752)
# Objective

- In #17743, attention was raised to the fact that we supported an
unusual kind of step easing function. The author of the fix kindly
provided some links to standards used in CSS. It would be desirable to
support generally agreed upon standards so this PR here tries to
implement an extra configuration option of the step easing function
- Resolve #17744

## Solution

- Introduce `StepConfig`
- `StepConfig` can configure both the number of steps and the jumping
behavior of the function
- `StepConfig` replaces the raw `usize` parameter of the
`EasingFunction::Steps(usize)` construct.
- `StepConfig`s default jumping behavior is `end`, so in that way it
follows #17743

## Testing

- I added a new test per `JumpAt` jumping behavior. These tests
replicate the visuals that can be found at
https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function/steps#description

## Migration Guide

- `EasingFunction::Steps` now uses a `StepConfig` instead of a raw
`usize`. You can replicate the previous behavior by replaceing
`EasingFunction::Steps(10)` with
`EasingFunction::Steps(StepConfig::new(10))`.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-11 22:19:01 +00:00
ickshonpe
98dcee2853
UI text extraction refactor (#17805)
## Objective

There's no need for the `span_index` and `color` variables in
`extract_text_shadows` and `extract_text_sections` and we can remove one
of the span index comparisons since text colors are only set per
section.

## Testing

<img width="454" alt="trace"
src="https://github.com/user-attachments/assets/3109d1df-0817-46c2-9889-0459ac93a42c"
/>
2025-02-11 22:18:47 +00:00
Jean Mertz
7d8504f30e
feat(ecs): implement fallible observer systems (#17731)
This commit builds on top of the work done in #16589 and #17051, by
adding support for fallible observer systems.

As with the previous work, the actual results of the observer system are
suppressed for now, but the intention is to provide a way to handle
errors in a global way.

Until then, you can use a `PipeSystem` to manually handle results.

---------

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-02-11 22:15:43 +00:00
Periwink
d6725d3b1b
Expose method to update the internal ticks of Ref and Mut (#17716)
## What problem does this solve or what need does it fill?

There are some situations
(https://github.com/bevyengine/bevy/issues/13735) where the ticks that
are present inside `Ref` are incorrect, for example if `Ref` is created
outside of a `SystemParam`.
I still want to use `Ref` because it has convenient `is_added` and
`is_changed` methods.

My current solution is to build my own `Ref` by copy-pasting most the
bevy code to do that via something like
```rust
/// This method is necessary because there is no easy way to 
pub(crate) fn get_ref<C: Component>(
    world: &World,
    entity: Entity,
    last_run: Tick,
    this_run: Tick,
) -> Ref<C> {
    unsafe {
        let component_id = world
            .components()
            .get_id(TypeId::of::<C>())
            .unwrap_unchecked();
        let world = world.as_unsafe_world_cell_readonly();
        let entity_cell = world.get_entity(entity).unwrap_unchecked();
        get_component_and_ticks(
            world,
            component_id,
            C::STORAGE_TYPE,
            entity,
            entity_cell.location(),
        )
        .map(|(value, cells, _caller)| {
            Ref::new(
                value.deref::<C>(),
                cells.added.deref(),
                cells.changed.deref(),
                last_run,
                this_run,
                #[cfg(feature = "track_location")]
                _caller.deref(),
            )
        })
        .unwrap_unchecked()
    }
}

// Utility function to return
#[inline]
unsafe fn get_component_and_ticks(
    world: UnsafeWorldCell<'_>,
    component_id: ComponentId,
    storage_type: StorageType,
    entity: Entity,
    location: EntityLocation,
) -> Option<(Ptr<'_>, TickCells<'_>, MaybeUnsafeCellLocation<'_>)> {
    match storage_type {
        StorageType::Table => {
            let table = unsafe { world.storages().tables.get(location.table_id) }?;

            // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
            Some((
                table.get_component(component_id, location.table_row)?,
                TickCells {
                    added: table
                        .get_added_tick(component_id, location.table_row)
                        .unwrap_unchecked(),
                    changed: table
                        .get_changed_tick(component_id, location.table_row)
                        .unwrap_unchecked(),
                },
                #[cfg(feature = "track_location")]
                table
                    .get_changed_by(component_id, location.table_row)
                    .unwrap_unchecked(),
                #[cfg(not(feature = "track_location"))]
                (),
            ))
        }
        StorageType::SparseSet => {
            let storage = unsafe { world.storages() }.sparse_sets.get(component_id)?;
            storage.get_with_ticks(entity)
        }
    }
}
```

It would be very convenient if instead bevy exposed a way to create a
`Ref` object with custom `last_run` and `this_run` ticks.
This PR does this by exposing a function to overwrite the `last_run` and
`this_run` ticks.
(Same with `Mut`)

I am ok with marking the method unsafe or risky if it's deemed to risky
for end-users.
2025-02-11 19:00:13 +00:00
sam edelsten
5eff6e80e1
Add relative position reporting to UI picking (#17681)
# Objective

Add position reporting to `HitData` sent from the UI picking backend.

## Solution

Add the computed normalized relative cursor position to `hit_data`
alongside the `Entity`.

The position reported in `HitData` is normalized relative to the node,
with `(0.,0.,0.)` at the top left and `(1., 1., 0.)` in the bottom
right. Coordinates are relative to the entire node, not just the visible
region.

`HitData` needs a `Vec3` so I just extended with 0.0. I considered
inserting the `depth` here but thought it would be redundant.

I also considered putting the screen space position in the `normal`
field of `HitData`, but that would require renaming of the field or a
separate data structure.

## Testing

Tested with mouse on X11 with entities that have `Node` components.

---

## Showcase

```rs
// Get click position relative to node
fn hit_position(trigger: Trigger<Pointer<Click>>) {
    let hit_pos = trigger.event.hit.position.expect("no position");
    info!("{}", hit_pos);
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-11 18:38:13 +00:00
Jean Mertz
fd67ca7eb0
feat(ecs): configurable error handling for fallible systems (#17753)
You can now configure error handlers for fallible systems. These can be
configured on several levels:

- Globally via `App::set_systems_error_handler`
- Per-schedule via `Schedule::set_error_handler`
- Per-system via a piped system (this is existing functionality)

The default handler of panicking on error keeps the same behavior as
before this commit.

The "fallible_systems" example demonstrates the new functionality.

This builds on top of #17731, #16589, #17051.

---------

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-02-11 18:36:08 +00:00
raldone01
fb0e5c484f
Fix failing proc macros when depending on bevy through dev and normal dependencies. (#17795)
This is a follow up fix for #17330 and fixes #17780.
There was a logic error in the ambiguity detection of
`cargo-manifest-proc-macros`.
`cargo-manifest-proc-macros` now has a test for this case to prevent the
issue in the future.

I also opted to hard fail if the `cargo-manifest-proc-macros` crate
fails. That way the error is more obvious and easier to fix and
diagnose.

## Testing

- The reproducer:
https://github.com/bevyengine/bevy_editor_prototypes/pull/178 works for
me using these fixes.
2025-02-11 18:28:15 +00:00
Alice Cecile
fcc77fe3d6
Allow users to register their own disabling components / default query filters (#17768)
# Objective

Currently, default query filters, as added in #13120 / #17514 are
hardcoded to only use a single query filter.

This is limiting, as multiple distinct disabling components can serve
important distinct roles. I ran into this limitation when experimenting
with a workflow for prefabs, which don't represent the same state as "an
entity which is temporarily nonfunctional".

## Solution

1. Change `DefaultQueryFilters` to store a SmallVec of ComponentId,
rather than an Option.
2. Expose methods on `DefaultQueryFilters`, `World` and `App` to
actually configure this.
3. While we're here, improve the docs, write some tests, make use of
FromWorld and make some method names more descriptive.

## Follow-up

I'm not convinced that supporting sparse set disabling components is
useful, given the hit to iteration performance and runtime checks
incurred. That's disjoint from this PR though, so I'm not doing it here.
The existing warnings are fine for now.

## Testing

I've added both a doc test and an mid-level unit test to verify that
this works!
2025-02-11 18:25:32 +00:00
Lucas Franca
5e9da923f9
Add links to the types on the documentation of GltfAssetLabel (#17791)
# Objective

Allow quick jump to definition of types of GlTFs labeled assets.

## Solution

Add links to the types refered on the docs of `GltfAssetLabel`

## Testing

Ran `cargo run -p ci`
2025-02-11 01:30:41 +00:00
person93
575f66504b
Silence deprecation warning in Bundle derive macro (#17369) (#17790)
# Objective

- Fixes #17369

## Solution

- Add `#[allow(deprecated)]` to the generated code.
2025-02-11 00:56:09 +00:00
Emerson Coskey
83370e0a25
Use dual-source blending for rendering the sky (#17672)
# Objective

Since previously we only had the alpha channel available, we stored the
mean of the transmittance in the aerial view lut, resulting in a grayer
fog than should be expected.

## Solution

- Calculate transmittance to scene in `render_sky` with two samples from
the transmittance lut
- use dual-source blending to effectively have per-component alpha
blending
2025-02-10 23:53:53 +00:00
Patrick Walton
69db29efb9
Sweep bins after queuing so as to only sweep them once. (#17787)
Currently, we *sweep*, or remove entities from bins when those entities
became invisible or changed phases, during `queue_material_meshes` and
similar phases. This, however, is wrong, because `queue_material_meshes`
executes once per material type, not once per phase. This could result
in sweeping bins multiple times per phase, which can corrupt the bins.
This commit fixes the issue by moving sweeping to a separate system that
runs after queuing.

This manifested itself as entities appearing and disappearing seemingly
at random.

Closes #17759.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2025-02-10 23:15:35 +00:00
charlotte
a861452d68
Add user supplied mesh tag (#17648)
# Objective

Because of mesh preprocessing, users cannot rely on
`@builtin(instance_index)` in order to reference external data, as the
instance index is not stable, either from frame to frame or relative to
the total spawn order of mesh instances.

## Solution

Add a user supplied mesh index that can be used for referencing external
data when drawing instanced meshes.

Closes #13373

## Testing

Benchmarked `many_cubes` showing no difference in total frame time.

## Showcase



https://github.com/user-attachments/assets/80620147-aafc-4d9d-a8ee-e2149f7c8f3b

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-02-10 22:38:13 +00:00
Greeble
71b22397da
Expand EasingCurve documentation (#17778)
# Objective

- Expand the documentation for `EasingCurve`.
- I suspect this might have avoided the confusion in
https://github.com/bevyengine/bevy/pull/17711.
- Also add a shortcut for simple cases.

## Solution

- Added various examples and extra context.
- Implemented `Curve<T>` for `EaseFunction`.
- This means `EasingCurve::new(0.0, 1.0, EaseFunction::X)` can be
shortened to `EaseFunction::X`.
    - In some cases this will be a minor performance improvement.
    - Added test to confirm they're the same.
- ~~Added some benchmarks for bonus points.~~


## Side Notes

- I would have liked to rename `EaseFunction` to `EaseFn` for brevity,
but that would be a breaking change and maybe controversial.
    - Also suspect `EasingCurve` should be `EaseCurve`, but say la vee.
- Benchmarks show that calling `EaseFunction::Smoothstep` is still
slower than calling `smoothstep` directly.
- I think this is because the compiler refuses to inline
`EaseFunction::eval`.
- I don't see any good solution - might need a whole different
interface.

## Testing

```sh
cargo test --package bevy_math

cargo doc --package bevy_math
./target/doc/bevy_math/curve/easing/struct.EasingCurve.html

cargo bench --package benches --bench math -- easing
```
2025-02-10 22:37:27 +00:00
ickshonpe
359cd432c0
UI clipping update function comments fix (#17785)
# Objective
Fix for the comments for the clipping rects update function which
references `Overflow` variants that no longer exist.
2025-02-10 22:35:12 +00:00
jf908
f27e00b197
Derive Reflect on Skybox (#17781)
# Objective

- Derive Reflect on Skybox component

## Solution

- Derive Reflect on Skybox component
2025-02-10 22:24:23 +00:00
Lege19
3978ba9783
Allowed creating uninitialized images (for use as storage textures) (#17760)
# Objective
https://github.com/bevyengine/bevy/issues/17746
## Solution
- Change `Image.data` from being a `Vec<u8>` to a `Option<Vec<u8>>`
- Added functions to help with creating images
## Testing

- Did you test these changes? If so, how?
All current tests pass
Tested a variety of existing examples to make sure they don't crash
(they don't)
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Linux x86 64-bit NixOS 
---
## Migration Guide
Code that directly access `Image` data will now need to use unwrap or
handle the case where no data is provided.
Behaviour of new_fill slightly changed, but not in a way that is likely
to affect anything. It no longer panics and will fill the whole texture
instead of leaving black pixels if the data provided is not a nice
factor of the size of the image.

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-02-10 22:22:07 +00:00
fschlee
db0356517e
CosmicBuffer is a public type but not not used or accessible in any public API (#17748)
# Objective

Currently
[CosmicBuffer](https://docs.rs/bevy/latest/bevy/text/struct.CosmicBuffer.html)
is a public type with a public field that is not used or accessible in
any public API. Since it is prominently shown in the docs it is the
obvious place to start when trying to access `cosmic_string` features
such as for mapping between screen coordinates and positions in the
displayed text.
The only place `CosmicBuffer` is currently used is as a field of
`ComputedTextBlock`, where a comment explains why the field is private:

    /// Buffer for managing text layout and creating [`TextLayoutInfo`].
    ///
/// This is private because buffer contents are always refreshed from
ECS state when writing glyphs to
/// `TextLayoutInfo`. If you want to control the buffer contents
manually or use the `cosmic-text`
/// editor, then you need to not use `TextLayout` and instead manually
implement the conversion to
    /// `TextLayoutInfo`.
    #[reflect(ignore)]
    pub(crate) buffer: CosmicBuffer,
    
Unfortunately this comment does not appear in the docs, so a user
looking for a way to access `CosmicBuffer` will not find it unless they
check the source code.
Also there does not seem to be any alternative way to map between screen
coordinates and positions in the displayed text, which would be highly
useful for things like text edit widgets or tool tips. The reasons given
for making the field private only apply for mutable access, so
non-mutable access would presumably be fine.
## Solution

I added a getter to `ComputedTextBlock`, and added the explanation for
why there is no mutable access in the comment:

/// Accesses the underling buffer which can be used for `cosmic-text`
APIs such as accessing layout information
    /// or calculating a cursor position.
    ///
/// Mutable access not offered because changes would be overwritten
during the automated layout calculation.
/// If you want to control the buffer contents manually or use the
`cosmic-text`
/// editor, then you need to not use `TextLayout` and instead manually
implement the conversion to
    /// `TextLayoutInfo`.
	pub fn get_buffer(&self) -> &CosmicBuffer {
		&self.buffer
	}

## Testing

I tested that the getter could be used to map from screen coordinates to
string positions by creating a rudimentary text edit widget and trying
it out.

## Alternatives
An alternative to making `CosmicBuffer` accessible would be to make the
type private so that no one wastes time looking for a way of accessing
it, and adding additional methods to `ComputedTextBlock` that make use
of the buffer as implementation detail and offer access to currently
inaccessible functionality.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-02-10 22:19:12 +00:00
François Mockers
4fe57767fc
make bevy math publishable (#17727)
# Objective

- bevy_math fails to publish because of the self dev-dependency
- it's used to enable the `approx` feature in tests

## Solution

- Don't specify a version in the dev-dependency. dependencies without a
version are ignored by cargo when publishing
- Gate all the tests that depend on the `approx` feature so that it
doesn't fail to compile when not enabled
- Also gate an import that wasn't used without `bevy_reflect`

## Testing

- with at least cargo 1.84: `cargo package -p bevy_math`
- `cd target/package/bevy_math_* && cargo test`
2025-02-10 22:15:53 +00:00
Chris Russell
c34a2c2fba
Query::get_many should not check for duplicates (#17724)
# Objective

Restore the behavior of `Query::get_many` prior to #15858.  

When passed duplicate `Entity`s, `get_many` is supposed to return
results for all of them, since read-only queries don't alias. However,
#15858 merged the implementation with `get_many_mut` and caused it to
return `QueryEntityError::AliasedMutability`.

## Solution

Introduce a new `Query::get_many_readonly` method that consumes the
`Query` like `get_many_inner`, but that is constrained to `D:
ReadOnlyQueryData` so that it can skip the aliasing check. Implement
`Query::get_many` in terms of that new method. Add a test, and a comment
explaining why it doesn't match the pattern of the other `&self`
methods.
2025-02-10 22:07:15 +00:00
urben1680
7f9588d4c6
Fix documentation of Entities::get (#17721)
This method returns `None` if `meta.location.archetype_id` is
`ArchetypeId::INVALID`.
`EntityLocation::INVALID.archetype_id` is `ArchetypeId::INVALID`.
Therefore this method cannot return `Some(EntityLocation::INVALID)`.
Linking to it in the docs is futile anyway as that constant is not
public.
2025-02-10 22:05:05 +00:00
colepoirier
84359514bd
Add scroll functionality to bevy_picking (#17704)
# Objective

`bevy_picking` currently does not support scroll events.

## Solution

This pr adds a new event type for scroll, and updates the default input
system for mouse pointers to read and emit this event.

## Testing

- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

I haven't tested these changes, if the reviewers can advise me how to do
so I'd appreciate it!
2025-02-10 22:03:38 +00:00
mgi388
2660ddc4c5
Support decibels in bevy_audio::Volume (#17605)
# Objective

- Allow users to configure volume using decibels by changing the
`Volume` type from newtyping an `f32` to an enum with `Linear` and
`Decibels` variants.
- Fixes #9507.
- Alternative reworked version of closed #9582.

## Solution

Compared to https://github.com/bevyengine/bevy/pull/9582, this PR has
the following main differences:

1. It uses the term "linear scale" instead of "amplitude" per
https://github.com/bevyengine/bevy/pull/9582/files#r1513529491.
2. Supports `ops` for doing `Volume` arithmetic. Can add two volumes,
e.g. to increase/decrease the current volume. Can multiply two volumes,
e.g. to get the “effective” volume of an audio source considering global
volume.

[requested and blessed on Discord]:
https://discord.com/channels/691052431525675048/749430447326625812/1318272597003341867

## Testing

- Ran `cargo run --example soundtrack`.
- Ran `cargo run --example audio_control`.
- Ran `cargo run --example spatial_audio_2d`.
- Ran `cargo run --example spatial_audio_3d`.
- Ran `cargo run --example pitch`.
- Ran `cargo run --example decodable`.
- Ran `cargo run --example audio`.

---

## Migration Guide

Audio volume can now be configured using decibel values, as well as
using linear scale values. To enable this, some types and functions in
`bevy_audio` have changed.

- `Volume` is now an enum with `Linear` and `Decibels` variants.

Before:

```rust
let v = Volume(1.0);
```

After:

```rust
let volume = Volume::Linear(1.0);
let volume = Volume::Decibels(0.0); // or now you can deal with decibels if you prefer
```

- `Volume::ZERO` has been renamed to the more semantically correct
`Volume::SILENT` because `Volume` now supports decibels and "zero
volume" in decibels actually means "normal volume".
- The `AudioSinkPlayback` trait's volume-related methods now deal with
`Volume` types rather than `f32`s. `AudioSinkPlayback::volume()` now
returns a `Volume` rather than an `f32`. `AudioSinkPlayback::set_volume`
now receives a `Volume` rather than an `f32`. This affects the
`AudioSink` and `SpatialAudioSink` implementations of the trait. The
previous `f32` values are equivalent to the volume converted to linear
scale so the `Volume:: Linear` variant should be used to migrate between
`f32`s and `Volume`.
- The `GlobalVolume::new` function now receives a `Volume` instead of an
`f32`.

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-02-10 21:26:43 +00:00
Chris Russell
eee7fd5b3e
Encapsulate cfg(feature = "track_location") in a type. (#17602)
# Objective

Eliminate the need to write `cfg(feature = "track_location")` every time
one uses an API that may use location tracking. It's verbose, and a
little intimidating. And it requires code outside of `bevy_ecs` that
wants to use location tracking needs to either unconditionally enable
the feature, or include conditional compilation of its own. It would be
good for users to be able to log locations when they are available
without needing to add feature flags to their own crates.

Reduce the number of cases where code compiles with the `track_location`
feature enabled, but not with it disabled, or vice versa. It can be hard
to remember to test it both ways!

Remove the need to store a `None` in `HookContext` when the
`track_location` feature is disabled.

## Solution

Create an `MaybeLocation<T>` type that contains a `T` if the
`track_location` feature is enabled, and is a ZST if it is not. The
overall API is similar to `Option`, but whether the value is `Some` or
`None` is set at compile time and is the same for all values.

Default `T` to `&'static Location<'static>`, since that is the most
common case.

Remove all `cfg(feature = "track_location")` blocks outside of the
implementation of that type, and instead call methods on it.

When `track_location` is disabled, `MaybeLocation` is a ZST and all
methods are `#[inline]` and empty, so they should be entirely removed by
the compiler. But the code will still be visible to the compiler and
checked, so if it compiles with the feature disabled then it should also
compile with it enabled, and vice versa.

## Open Questions

Where should these types live? I put them in `change_detection` because
that's where the existing `MaybeLocation` types were, but we now use
these outside of change detection.

While I believe that the compiler should be able to remove all of these
calls, I have not actually tested anything. If we want to take this
approach, what testing is required to ensure it doesn't impact
performance?

## Migration Guide

Methods like `Ref::changed_by()` that return a `&'static
Location<'static>` will now be available even when the `track_location`
feature is disabled, but they will return a new `MaybeLocation` type.
`MaybeLocation` wraps a `&'static Location<'static>` when the feature is
enabled, and is a ZST when the feature is disabled.

Existing code that needs a `&Location` can call `into_option().unwrap()`
to recover it. Many trait impls are forwarded, so if you only need
`Display` then no changes will be necessary.

If that code was conditionally compiled, you may instead want to use the
methods on `MaybeLocation` to remove the need for conditional
compilation.

Code that constructs a `Ref`, `Mut`, `Res`, or `ResMut` will now need to
provide location information unconditionally. If you are creating them
from existing Bevy types, you can obtain a `MaybeLocation` from methods
like `Table::get_changed_by_slice_for()` or
`ComponentSparseSet::get_with_ticks`. Otherwise, you will need to store
a `MaybeLocation` next to your data and use methods like `as_ref()` or
`as_mut()` to obtain wrapped references.
2025-02-10 21:21:20 +00:00
andriyDev
f17644879d
Remove labeled_assets from LoadedAsset and ErasedLoadedAsset (#15481)
# Objective

Fixes #15417.

## Solution

- Remove the `labeled_assets` fields from `LoadedAsset` and
`ErasedLoadedAsset`.
- Created new structs `CompleteLoadedAsset` and
`CompleteErasedLoadedAsset` to hold the `labeled_subassets`.
- When a subasset is `LoadContext::finish`ed, it produces a
`CompleteLoadedAsset`.
- When a `CompleteLoadedAsset` is added to a `LoadContext` (as a
subasset), their `labeled_assets` are merged, reporting any overlaps.

One important detail to note: nested subassets with overlapping names
could in theory have been used in the past for the purposes of asset
preprocessing. Even though there was no way to access these "shadowed"
nested subassets, asset preprocessing does get access to these nested
subassets. This does not seem like a case we should support though. It
is confusing at best.

## Testing

- This is just a refactor.

---

## Migration Guide

- Most uses of `LoadedAsset` and `ErasedLoadedAsset` should be replaced
with `CompleteLoadedAsset` and `CompleteErasedLoadedAsset` respectively.
2025-02-10 21:06:37 +00:00
charlotte
232824c009
Fix meshlets when bindless disabled. (#17770)
# Objective

https://github.com/bevyengine/bevy/pull/16966 tried to fix a bug where
`slot` wasn't passed to `parallaxed_uv` when not running under bindless,
but failed to account for meshlets. This surfaces on macOS where
bindless is disabled.

## Solution

Lift the slot variable out of the bindless condition so it's always
available.
2025-02-10 09:46:10 +00:00
ickshonpe
300fe4db4d
Store UI render target info locally per node (#17579)
# Objective

It's difficult to understand or make changes to the UI systems because
of how each system needs to individually track changes to scale factor,
windows and camera targets in local hashmaps, particularly for new
contributors. Any major change inevitably introduces new scale factor
bugs.

Instead of per-system resolution we can resolve the camera target info
for all UI nodes in a system at the start of `PostUpdate` and then store
it per-node in components that can be queried with change detection.

Fixes #17578
Fixes #15143

## Solution

Store the UI render target's data locally per node in a component that
is updated in `PostUpdate` before any other UI systems run.

This component can be then be queried with change detection so that UI
systems no longer need to have knowledge of cameras and windows and
don't require fragile custom change detection solutions using local
hashmaps.

## Showcase
Compare `measure_text_system` from main (which has a bug the causes it
to use the wrong scale factor when a node's camera target changes):
```
pub fn measure_text_system(
    mut scale_factors_buffer: Local<EntityHashMap<f32>>,
    mut last_scale_factors: Local<EntityHashMap<f32>>,
    fonts: Res<Assets<Font>>,
    camera_query: Query<(Entity, &Camera)>,
    default_ui_camera: DefaultUiCamera,
    ui_scale: Res<UiScale>,
    mut text_query: Query<
        (
            Entity,
            Ref<TextLayout>,
            &mut ContentSize,
            &mut TextNodeFlags,
            &mut ComputedTextBlock,
            Option<&UiTargetCamera>,
        ),
        With<Node>,
    >,
    mut text_reader: TextUiReader,
    mut text_pipeline: ResMut<TextPipeline>,
    mut font_system: ResMut<CosmicFontSystem>,
) {
    scale_factors_buffer.clear();

    let default_camera_entity = default_ui_camera.get();

    for (entity, block, content_size, text_flags, computed, maybe_camera) in &mut text_query {
        let Some(camera_entity) = maybe_camera
            .map(UiTargetCamera::entity)
            .or(default_camera_entity)
        else {
            continue;
        };
        let scale_factor = match scale_factors_buffer.entry(camera_entity) {
            Entry::Occupied(entry) => *entry.get(),
            Entry::Vacant(entry) => *entry.insert(
                camera_query
                    .get(camera_entity)
                    .ok()
                    .and_then(|(_, c)| c.target_scaling_factor())
                    .unwrap_or(1.0)
                    * ui_scale.0,
            ),
        };

        if last_scale_factors.get(&camera_entity) != Some(&scale_factor)
            || computed.needs_rerender()
            || text_flags.needs_measure_fn
            || content_size.is_added()
        {
            create_text_measure(
                entity,
                &fonts,
                scale_factor.into(),
                text_reader.iter(entity),
                block,
                &mut text_pipeline,
                content_size,
                text_flags,
                computed,
                &mut font_system,
            );
        }
    }
    core::mem::swap(&mut *last_scale_factors, &mut *scale_factors_buffer);
}
```

with `measure_text_system` from this PR (which always uses the correct
scale factor):
```
pub fn measure_text_system(
    fonts: Res<Assets<Font>>,
    mut text_query: Query<
        (
            Entity,
            Ref<TextLayout>,
            &mut ContentSize,
            &mut TextNodeFlags,
            &mut ComputedTextBlock,
            Ref<ComputedNodeTarget>,
        ),
        With<Node>,
    >,
    mut text_reader: TextUiReader,
    mut text_pipeline: ResMut<TextPipeline>,
    mut font_system: ResMut<CosmicFontSystem>,
) {
    for (entity, block, content_size, text_flags, computed, computed_target) in &mut text_query {
        // Note: the ComputedTextBlock::needs_rerender bool is cleared in create_text_measure().
        if computed_target.is_changed()
            || computed.needs_rerender()
            || text_flags.needs_measure_fn
            || content_size.is_added()
        {
            create_text_measure(
                entity,
                &fonts,
                computed_target.scale_factor.into(),
                text_reader.iter(entity),
                block,
                &mut text_pipeline,
                content_size,
                text_flags,
                computed,
                &mut font_system,
            );
        }
    }
}
```

## Testing

I removed an alarming number of tests from the `layout` module but they
were mostly to do with the deleted camera synchronisation logic. The
remaining tests should all pass now.

The most relevant examples are `multiple_windows` and `split_screen`,
the behaviour of both should be unchanged from main.

---------

Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-10 07:27:58 +00:00
Carter Anderson
ea578415e1
Improved Spawn APIs and Bundle Effects (#17521)
## Objective

A major critique of Bevy at the moment is how boilerplatey it is to
compose (and read) entity hierarchies:

```rust
commands
    .spawn(Foo)
    .with_children(|p| {
        p.spawn(Bar).with_children(|p| {
            p.spawn(Baz);
        });
        p.spawn(Bar).with_children(|p| {
            p.spawn(Baz);
        });
    });
```

There is also currently no good way to statically define and return an
entity hierarchy from a function. Instead, people often do this
"internally" with a Commands function that returns nothing, making it
impossible to spawn the hierarchy in other cases (direct World spawns,
ChildSpawner, etc).

Additionally, because this style of API results in creating the
hierarchy bits _after_ the initial spawn of a bundle, it causes ECS
archetype changes (and often expensive table moves).

Because children are initialized after the fact, we also can't count
them to pre-allocate space. This means each time a child inserts itself,
it has a high chance of overflowing the currently allocated capacity in
the `RelationshipTarget` collection, causing literal worst-case
reallocations.

We can do better!

## Solution

The Bundle trait has been extended to support an optional
`BundleEffect`. This is applied directly to World immediately _after_
the Bundle has fully inserted. Note that this is
[intentionally](https://github.com/bevyengine/bevy/discussions/16920)
_not done via a deferred Command_, which would require repeatedly
copying each remaining subtree of the hierarchy to a new command as we
walk down the tree (_not_ good performance).

This allows us to implement the new `SpawnRelated` trait for all
`RelationshipTarget` impls, which looks like this in practice:

```rust
world.spawn((
    Foo,
    Children::spawn((
        Spawn((
            Bar,
            Children::spawn(Spawn(Baz)),
        )),
        Spawn((
            Bar,
            Children::spawn(Spawn(Baz)),
        )),
    ))
))
```

`Children::spawn` returns `SpawnRelatedBundle<Children, L:
SpawnableList>`, which is a `Bundle` that inserts `Children`
(preallocated to the size of the `SpawnableList::size_hint()`).
`Spawn<B: Bundle>(pub B)` implements `SpawnableList` with a size of 1.
`SpawnableList` is also implemented for tuples of `SpawnableList` (same
general pattern as the Bundle impl).

There are currently three built-in `SpawnableList` implementations:

```rust
world.spawn((
    Foo,
    Children::spawn((
        Spawn(Name::new("Child1")),   
        SpawnIter(["Child2", "Child3"].into_iter().map(Name::new),
        SpawnWith(|parent: &mut ChildSpawner| {
            parent.spawn(Name::new("Child4"));
            parent.spawn(Name::new("Child5"));
        })
    )),
))
```

We get the benefits of "structured init", but we have nice flexibility
where it is required!

Some readers' first instinct might be to try to remove the need for the
`Spawn` wrapper. This is impossible in the Rust type system, as a tuple
of "child Bundles to be spawned" and a "tuple of Components to be added
via a single Bundle" is ambiguous in the Rust type system. There are two
ways to resolve that ambiguity:

1. By adding support for variadics to the Rust type system (removing the
need for nested bundles). This is out of scope for this PR :)
2. Using wrapper types to resolve the ambiguity (this is what I did in
this PR).

For the single-entity spawn cases, `Children::spawn_one` does also
exist, which removes the need for the wrapper:

```rust
world.spawn((
    Foo,
    Children::spawn_one(Bar),
))
```

## This works for all Relationships

This API isn't just for `Children` / `ChildOf` relationships. It works
for any relationship type, and they can be mixed and matched!

```rust
world.spawn((
    Foo,
    Observers::spawn((
        Spawn(Observer::new(|trigger: Trigger<FuseLit>| {})),
        Spawn(Observer::new(|trigger: Trigger<Exploded>| {})),
    )),
    OwnerOf::spawn(Spawn(Bar))
    Children::spawn(Spawn(Baz))
))
```

## Macros

While `Spawn` is necessary to satisfy the type system, we _can_ remove
the need to express it via macros. The example above can be expressed
more succinctly using the new `children![X]` macro, which internally
produces `Children::spawn(Spawn(X))`:

```rust
world.spawn((
    Foo,
    children![
        (
            Bar,
            children![Baz],
        ),
        (
            Bar,
            children![Baz],
        ),
    ]
))
```

There is also a `related!` macro, which is a generic version of the
`children!` macro that supports any relationship type:

```rust
world.spawn((
    Foo,
    related!(Children[
        (
            Bar,
            related!(Children[Baz]),
        ),
        (
            Bar,
            related!(Children[Baz]),
        ),
    ])
))
```

## Returning Hierarchies from Functions

Thanks to these changes, the following pattern is now possible:

```rust
fn button(text: &str, color: Color) -> impl Bundle {
    (
        Node {
            width: Val::Px(300.),
            height: Val::Px(100.),
            ..default()
        },
        BackgroundColor(color),
        children![
            Text::new(text),
        ]
    )
}

fn ui() -> impl Bundle {
    (
        Node {
            width: Val::Percent(100.0),
            height: Val::Percent(100.0),
            ..default(),
        },
        children![
            button("hello", BLUE),
            button("world", RED),
        ]
    )
}

// spawn from a system
fn system(mut commands: Commands) {
    commands.spawn(ui());
}

// spawn directly on World
world.spawn(ui());
```

## Additional Changes and Notes

* `Bundle::from_components` has been split out into
`BundleFromComponents::from_components`, enabling us to implement
`Bundle` for types that cannot be "taken" from the ECS (such as the new
`SpawnRelatedBundle`).
* The `NoBundleEffect` trait (which implements `BundleEffect`) is
implemented for empty tuples (and tuples of empty tuples), which allows
us to constrain APIs to only accept bundles that do not have effects.
This is critical because the current batch spawn APIs cannot efficiently
apply BundleEffects in their current form (as doing so in-place could
invalidate the cached raw pointers). We could consider allocating a
buffer of the effects to be applied later, but that does have
performance implications that could offset the balance and value of the
batched APIs (and would likely require some refactors to the underlying
code). I've decided to be conservative here. We can consider relaxing
that requirement on those APIs later, but that should be done in a
followup imo.
* I've ported a few examples to illustrate real-world usage. I think in
a followup we should port all examples to the `children!` form whenever
possible (and for cases that require things like SpawnIter, use the raw
APIs).
* Some may ask "why not use the `Relationship` to spawn (ex:
`ChildOf::spawn(Foo)`) instead of the `RelationshipTarget` (ex:
`Children::spawn(Spawn(Foo))`)?". That _would_ allow us to remove the
`Spawn` wrapper. I've explicitly chosen to disallow this pattern.
`Bundle::Effect` has the ability to create _significant_ weirdness.
Things in `Bundle` position look like components. For example
`world.spawn((Foo, ChildOf::spawn(Bar)))` _looks and reads_ like Foo is
a child of Bar. `ChildOf` is in Foo's "component position" but it is not
a component on Foo. This is a huge problem. Now that `Bundle::Effect`
exists, we should be _very_ principled about keeping the "weird and
unintuitive behavior" to a minimum. Things that read like components
_should be the components they appear to be".

## Remaining Work

* The macros are currently trivially implemented using macro_rules and
are currently limited to the max tuple length. They will require a
proc_macro implementation to work around the tuple length limit.

## Next Steps

* Port the remaining examples to use `children!` where possible and raw
`Spawn` / `SpawnIter` / `SpawnWith` where the flexibility of the raw API
is required.

## Migration Guide

Existing spawn patterns will continue to work as expected.

Manual Bundle implementations now require a `BundleEffect` associated
type. Exisiting bundles would have no bundle effect, so use `()`.
Additionally `Bundle::from_components` has been moved to the new
`BundleFromComponents` trait.

```rust
// Before
unsafe impl Bundle for X {
    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self {
    }
    /* remaining bundle impl here */
}

// After
unsafe impl Bundle for X {
    type Effect = ();
    /* remaining bundle impl here */
}

unsafe impl BundleFromComponents for X {
    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self {
    }
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Emerson Coskey <emerson@coskey.dev>
2025-02-09 23:32:56 +00:00
newclarityex
c679b861d8
adds example for local defaults (#17751)
# Objective
Solves https://github.com/bevyengine/bevy/issues/17747.

## Solution

- Adds an example for creating a default value for Local.

## Testing

- Example code compiles and passes assertions.
2025-02-09 22:02:35 +00:00
raldone01
1b7db895b7
Harden proc macro path resolution and add integration tests. (#17330)
This pr uses the `extern crate self as` trick to make proc macros behave
the same way inside and outside bevy.

# Objective

- Removes noise introduced by `crate as` in the whole bevy repo.
- Fixes #17004.
- Hardens proc macro path resolution.

## TODO

- [x] `BevyManifest` needs cleanup.
- [x] Cleanup remaining `crate as`.
- [x] Add proper integration tests to the ci.

## Notes

- `cargo-manifest-proc-macros` is written by me and based/inspired by
the old `BevyManifest` implementation and
[`bkchr/proc-macro-crate`](https://github.com/bkchr/proc-macro-crate).
- What do you think about the new integration test machinery I added to
the `ci`?
  More and better integration tests can be added at a later stage.
The goal of these integration tests is to simulate an actual separate
crate that uses bevy. Ideally they would lightly touch all bevy crates.

## Testing

- Needs RA test
- Needs testing from other users
- Others need to run at least `cargo run -p ci integration-test` and
verify that they work.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-09 19:45:45 +00:00
JMS55
669d139c13
Upgrade to wgpu v24 (#17542)
Didn't remove WgpuWrapper. Not sure if it's needed or not still.

## Testing

- Did you test these changes? If so, how? Example runner
- Are there any parts that need more testing? Web (portable atomics
thingy?), DXC.

## Migration Guide
- Bevy has upgraded to [wgpu
v24](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2400-2025-01-15).
- When using the DirectX 12 rendering backend, the new priority system
for choosing a shader compiler is as follows:
- If the `WGPU_DX12_COMPILER` environment variable is set at runtime, it
is used
- Else if the new `statically-linked-dxc` feature is enabled, a custom
version of DXC will be statically linked into your app at compile time.
- Else Bevy will look in the app's working directory for
`dxcompiler.dll` and `dxil.dll` at runtime.
- Else if they are missing, Bevy will fall back to FXC (not recommended)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-09 19:40:53 +00:00
SilentSpaceTraveller
0b11b1f37e
deps: bump notify-debouncer-full to remove unmaintained crate (#17741)
# Objective

Fix #16477.

## Solution
- Remove temporary silence introduced in #16763 
- bump version of `notify-debouncer-full` to remove transitive
dependency on `instant` crate.
2025-02-09 17:56:01 +00:00
François Mockers
7400e7adfd
Cleanup publish process (#17728)
# Objective

- publish script copy the license files to all subcrates, meaning that
all publish are dirty. this breaks git verification of crates
- the order and list of crates to publish is manually maintained,
leading to error. cargo 1.84 is more strict and the list is currently
wrong

## Solution

- duplicate all the licenses to all crates and remove the
`--allow-dirty` flag
- instead of a manual list of crates, get it from `cargo package
--workspace`
- remove the `--no-verify` flag to... verify more things?
2025-02-09 17:46:19 +00:00
charlotte
af6629cbe9
Move specialize_* to QueueMeshes. (#17719)
# Objective

Things were breaking post-cs.

## Solution

`specialize_mesh_materials` must run after
`collect_meshes_for_gpu_building`. Therefore, its placement in the
`PrepareAssets` set didn't make sense (also more generally). To fix, we
put this class of system in ~`PrepareResources`~ `QueueMeshes`, although
it potentially could use a more descriptive location. We may want to
review the placement of `check_views_need_specialization` which is also
currently in `PrepareAssets`.
2025-02-09 14:13:42 +00:00
Pēteris Pakalns
2d62026912
main_transparent_pass_2d render node command encoding parallelization (#17735)
# Objective

- Add command encoding parallelization to transparent 2d pass render
node.
- Improves https://github.com/bevyengine/bevy/issues/17733

## Solution

Using functionality added in
https://github.com/bevyengine/bevy/pull/9172

## Testing

- Tested in personal project where multiple cameras are rendered with
objects rendered in transparent 2d pass.
2025-02-09 14:12:33 +00:00
Patrick Walton
556b750782
Set late indirect parameter offsets every frame again. (#17736)
PR #17684 broke occlusion culling because it neglected to set the
indirect parameter offsets for the late mesh preprocessing stage if the
work item buffers were already set. This PR moves the update of those
values to a new function, `init_work_item_buffers`, which is
unconditionally called for every phase every frame.

Note that there's some complexity in order to handle the case in which
occlusion culling was enabled on one frame and disabled on the next, or
vice versa. This was necessary in order to make the occlusion culling
toggle in the `occlusion_culling` example work again.
2025-02-09 06:02:39 +00:00
Patrick Walton
9f9373c7d9
Fix shadow retention by keying off the RetainedViewEntity, not the light's render world entity. (#17749)
Right now, we key the cached light change ticks off the `LightEntity`.
This uses the render world entity, which isn't stable between frames.
Thus in practice few shadows are retained from frame to frame. This PR
fixes the issue by keying off the `RetainedViewEntity` instead, which is
designed to be stable from frame to frame.
2025-02-09 05:52:17 +00:00
Patrick Walton
7fc122ad16
Retain bins from frame to frame. (#17698)
This PR makes Bevy keep entities in bins from frame to frame if they
haven't changed. This reduces the time spent in `queue_material_meshes`
and related functions to near zero for static geometry. This patch uses
the same change tick technique that #17567 uses to detect when meshes
have changed in such a way as to require re-binning.

In order to quickly find the relevant bin for an entity when that entity
has changed, we introduce a new type of cache, the *bin key cache*. This
cache stores a mapping from main world entity ID to cached bin key, as
well as the tick of the most recent change to the entity. As we iterate
through the visible entities in `queue_material_meshes`, we check the
cache to see whether the entity needs to be re-binned. If it doesn't,
then we mark it as clean in the `valid_cached_entity_bin_keys` bit set.
If it does, then we insert it into the correct bin, and then mark the
entity as clean. At the end, all entities not marked as clean are
removed from the bins.

This patch has a dramatic effect on the rendering performance of most
benchmarks, as it effectively eliminates `queue_material_meshes` from
the profile. Note, however, that it generally simultaneously regresses
`batch_and_prepare_binned_render_phase` by a bit (not by enough to
outweigh the win, however). I believe that's because, before this patch,
`queue_material_meshes` put the bins in the CPU cache for
`batch_and_prepare_binned_render_phase` to use, while with this patch,
`batch_and_prepare_binned_render_phase` must load the bins into the CPU
cache itself.

On Caldera, this reduces the time spent in `queue_material_meshes` from
5+ ms to 0.2ms-0.3ms. Note that benchmarking on that scene is very noisy
right now because of https://github.com/bevyengine/bevy/issues/17535.

![Screenshot 2025-02-05
153458](https://github.com/user-attachments/assets/e55f8134-b7e3-4b78-a5af-8d83e1e213b7)
2025-02-08 20:13:33 +00:00
Rob Parrett
f3d8eb8956
Fix rounding in steps easing function (#17743)
# Objective

While working on #17742, I noticed that the `Steps` easing function
looked a bit suspicious.


![image](https://github.com/user-attachments/assets/be8f07e4-2079-461f-8c23-56d4b689aed9)

Comparing to the options available in
[css](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function/steps#description):


![image](https://github.com/user-attachments/assets/2c351519-c87f-483f-b5ff-63a9ee7b7b51)

It is "off the charts," so probably not what users are expecting.

## Solution

Use `floor` when rounding to match the default behavior (jump-end, top
right) in css.

<img width="100" alt="image"
src="https://github.com/user-attachments/assets/1ec46270-72f2-4227-87e4-03de881548ab"
/>


## Testing

I had to modify an existing test that was testing against the old
behavior. This function and test were introduced in #14788 and I didn't
see any discussion about the rounding there.

`cargo run --example easing_functions`

## Migration Guide

<!-- Note to editors: this should be adjusted if 17744 is addressed, and
possibly combined with the notes from the PR that fixes it. -->

`EaseFunction::Steps` now behaves like css's default, "jump-end." If you
were relying on the old behavior, we plan on providing it. See
https://github.com/bevyengine/bevy/issues/17744.
2025-02-08 18:33:46 +00:00
SpecificProtagonist
7c2d54c93f
EaseFunction svg graphs in doc (#17461)
# Objective

The docs of `EaseFunction` don't visualize the different functions,
requiring you to check out the Bevy repo and running the
`easing_function` example.

## Solution

- Add tool to generate suitable svg graphs. This only needs to be re-run
when adding new ease functions.
- works with all themes
- also add missing easing functions to example.

---

## Showcase

![Graphs](https://i.imgur.com/V2oTEUq.png)

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-02-08 09:52:39 +00:00
Patrick Walton
bcfc086f3d
Include the material bind group in the shadow batch set key. (#17738)
Right now, meshes aren't grouped together based on the bindless texture
slab when drawing shadows. This manifests itself as flickering in
Bistro. I believe that there are two causes of this:

1. Alpha masked shadows may try to sample from the wrong texture,
causing the alpha mask to appear and disappear.

2. Objects may try to sample from the blank textures that we pad out the
bindless slabs with, causing them to vanish intermittently.

This commit fixes the issue by including the material bind group ID as
part of the shadow batch set key, just as we do for the prepass and main
pass.
2025-02-08 07:43:45 +00:00
ickshonpe
6ed3c3274f
Missing UI glpyhs fix (#17729)
# Objective

Fixes #17718

## Solution

Schedule `text_system` before `AssetEvents`.

I guess what was happening here is that glyphs weren't shown because
`text_system` was running before `AssetEevents` and so `prepare_uinodes`
never recieves the the asset modified event about the glyph texture
atlas image.
2025-02-07 19:41:18 +00:00
Carter Anderson
3c8fae2390
Improved Entity Mapping and Cloning (#17687)
Fixes #17535

Bevy's approach to handling "entity mapping" during spawning and cloning
needs some work. The addition of
[Relations](https://github.com/bevyengine/bevy/pull/17398) both
[introduced a new "duplicate entities" bug when spawning scenes in the
scene system](#17535) and made the weaknesses of the current mapping
system exceedingly clear:

1. Entity mapping requires _a ton_ of boilerplate (implement or derive
VisitEntities and VisitEntitesMut, then register / reflect MapEntities).
Knowing the incantation is challenging and if you forget to do it in
part or in whole, spawning subtly breaks.
2. Entity mapping a spawned component in scenes incurs unnecessary
overhead: look up ReflectMapEntities, create a _brand new temporary
instance_ of the component using FromReflect, map the entities in that
instance, and then apply that on top of the actual component using
reflection. We can do much better.

Additionally, while our new [Entity cloning
system](https://github.com/bevyengine/bevy/pull/16132) is already pretty
great, it has some areas we can make better:

* It doesn't expose semantic info about the clone (ex: ignore or "clone
empty"), meaning we can't key off of that in places where it would be
useful, such as scene spawning. Rather than duplicating this info across
contexts, I think it makes more sense to add that info to the clone
system, especially given that we'd like to use cloning code in some of
our spawning scenarios.
* EntityCloner is currently built in a way that prioritizes a single
entity clone
* EntityCloner's recursive cloning is built to be done "inside out" in a
parallel context (queue commands that each have a clone of
EntityCloner). By making EntityCloner the orchestrator of the clone we
can remove internal arcs, improve the clarity of the code, make
EntityCloner mutable again, and simplify the builder code.
* EntityCloner does not currently take into account entity mapping. This
is necessary to do true "bullet proof" cloning, would allow us to unify
the per-component scene spawning and cloning UX, and ultimately would
allow us to use EntityCloner in place of raw reflection for scenes like
`Scene(World)` (which would give us a nice performance boost: fewer
archetype moves, less reflection overhead).

## Solution

### Improved Entity Mapping

First, components now have first-class "entity visiting and mapping"
behavior:

```rust
#[derive(Component, Reflect)]
#[reflect(Component)]
struct Inventory {
    size: usize,
    #[entities]
    items: Vec<Entity>,
}
```

Any field with the `#[entities]` annotation will be viewable and
mappable when cloning and spawning scenes.

Compare that to what was required before!

```rust
#[derive(Component, Reflect, VisitEntities, VisitEntitiesMut)]
#[reflect(Component, MapEntities)]
struct Inventory {
    #[visit_entities(ignore)]
    size: usize,
    items: Vec<Entity>,
}
```

Additionally, for relationships `#[entities]` is implied, meaning this
"just works" in scenes and cloning:

```rust
#[derive(Component, Reflect)]
#[relationship(relationship_target = Children)]
#[reflect(Component)]
struct ChildOf(pub Entity);
```

Note that Component _does not_ implement `VisitEntities` directly.
Instead, it has `Component::visit_entities` and
`Component::visit_entities_mut` methods. This is for a few reasons:

1. We cannot implement `VisitEntities for C: Component` because that
would conflict with our impl of VisitEntities for anything that
implements `IntoIterator<Item=Entity>`. Preserving that impl is more
important from a UX perspective.
2. We should not implement `Component: VisitEntities` VisitEntities in
the Component derive, as that would increase the burden of manual
Component trait implementors.
3. Making VisitEntitiesMut directly callable for components would make
it easy to invalidate invariants defined by a component author. By
putting it in the `Component` impl, we can make it harder to call
naturally / unavailable to autocomplete using `fn
visit_entities_mut(this: &mut Self, ...)`.

`ReflectComponent::apply_or_insert` is now
`ReflectComponent::apply_or_insert_mapped`. By moving mapping inside
this impl, we remove the need to go through the reflection system to do
entity mapping, meaning we no longer need to create a clone of the
target component, map the entities in that component, and patch those
values on top. This will make spawning mapped entities _much_ faster
(The default `Component::visit_entities_mut` impl is an inlined empty
function, so it will incur no overhead for unmapped entities).

### The Bug Fix

To solve #17535, spawning code now skips entities with the new
`ComponentCloneBehavior::Ignore` and
`ComponentCloneBehavior::RelationshipTarget` variants (note
RelationshipTarget is a temporary "workaround" variant that allows
scenes to skip these components. This is a temporary workaround that can
be removed as these cases should _really_ be using EntityCloner logic,
which should be done in a followup PR. When that is done,
`ComponentCloneBehavior::RelationshipTarget` can be merged into the
normal `ComponentCloneBehavior::Custom`).

### Improved Cloning

* `Option<ComponentCloneHandler>` has been replaced by
`ComponentCloneBehavior`, which encodes additional intent and context
(ex: `Default`, `Ignore`, `Custom`, `RelationshipTarget` (this last one
is temporary)).
* Global per-world entity cloning configuration has been removed. This
felt overly complicated, increased our API surface, and felt too
generic. Each clone context can have different requirements (ex: what a
user wants in a specific system, what a scene spawner wants, etc). I'd
prefer to see how far context-specific EntityCloners get us first.
* EntityCloner's internals have been reworked to remove Arcs and make it
mutable.
* EntityCloner is now directly stored on EntityClonerBuilder,
simplifying the code somewhat
* EntityCloner's "bundle scratch" pattern has been moved into the new
BundleScratch type, improving its usability and making it usable in
other contexts (such as future cross-world cloning code). Currently this
is still private, but with some higher level safe APIs it could be used
externally for making dynamic bundles
* EntityCloner's recursive cloning behavior has been "externalized". It
is now responsible for orchestrating recursive clones, meaning it no
longer needs to be sharable/clone-able across threads / read-only.
* EntityCloner now does entity mapping during clones, like scenes do.
This gives behavior parity and also makes it more generically useful.
* `RelatonshipTarget::RECURSIVE_SPAWN` is now
`RelationshipTarget::LINKED_SPAWN`, and this field is used when cloning
relationship targets to determine if cloning should happen recursively.
The new `LINKED_SPAWN` term was picked to make it more generically
applicable across spawning and cloning scenarios.

## Next Steps

* I think we should adapt EntityCloner to support cross world cloning. I
think this PR helps set the stage for that by making the internals
slightly more generalized. We could have a CrossWorldEntityCloner that
reuses a lot of this infrastructure.
* Once we support cross world cloning, we should use EntityCloner to
spawn `Scene(World)` scenes. This would yield significant performance
benefits (no archetype moves, less reflection overhead).

---------

Co-authored-by: eugineerd <70062110+eugineerd@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-06 22:13:41 +00:00
Zhixing Zhang
f2a65c2dd3
Schedule build pass (#11094)
# Objective

This is a follow up to #9822, which automatically adds sync points
during the Schedule build process.

However, the implementation in #9822 feels very "special case" to me. As
the number of things we want to do with the `Schedule` grows, we need a
modularized way to manage those behaviors. For example, in one of my
current experiments I want to automatically add systems to apply GPU
pipeline barriers between systems accessing GPU resources.

For dynamic modifications of the schedule, we mostly need these
capabilities:
- Storing custom data on schedule edges
- Storing custom data on schedule nodes
- Modify the schedule graph whenever it builds

These should be enough to allows us to add "hooks" to the schedule build
process for various reasons.

cc @hymm 

## Solution
This PR abstracts the process of schedule modification and created a new
trait, `ScheduleBuildPass`. Most of the logics in #9822 were moved to an
implementation of `ScheduleBuildPass`, `AutoInsertApplyDeferredPass`.

Whether a dependency edge should "ignore deferred" is now indicated by
the presence of a marker struct, `IgnoreDeferred`.

This PR has no externally visible effects. However, in a future PR I
propose to change the `before_ignore_deferred` and
`after_ignore_deferred` API into a more general form,
`before_with_options` and `after_with_options`.

```rs
schedule.add_systems(
    system.before_with_options(another_system, IgnoreDeferred)
);

schedule.add_systems(
    system.before_with_options(another_system, (
        IgnoreDeferred,
        AnyOtherOption {
            key: value
        }
    ))
);

schedule.add_systems(
    system.before_with_options(another_system, ())
);
```
2025-02-05 23:14:05 +00:00