Commit Graph

6847 Commits

Author SHA1 Message Date
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
Sludge
989f547080
Weak handle migration (#17695)
# Objective

- Make use of the new `weak_handle!` macro added in
https://github.com/bevyengine/bevy/pull/17384

## Solution

- Migrate bevy from `Handle::weak_from_u128` to the new `weak_handle!`
macro that takes a random UUID
- Deprecate `Handle::weak_from_u128`, since there are no remaining use
cases that can't also be addressed by constructing the type manually

## Testing

- `cargo run -p ci -- test`

---

## Migration Guide

Replace `Handle::weak_from_u128` with `weak_handle!` and a random UUID.
2025-02-05 22:44:20 +00:00
Rob Grindeland
0335f34561
Add missing return in default Relationship::on_insert impl (#17675)
# Objective

There was a bug in the default `Relationship::on_insert` implementation
that caused it to not properly handle entities targeting themselves in
relationships. The relationship component was properly removed, but it
would go on to add itself to its own target component.

## Solution

Added a missing `return` and a couple of tests
(`self_relationship_fails` failed on its second assert prior to this
PR).

## Testing

See above.
2025-02-05 21:26:16 +00:00
ElliottjPierce
1b2cf7d6cd
Isolate component registration (#17671)
# Objective

Progresses #17569. The end goal here is to synchronize component
registration. See the other PR for details for the motivation behind
that.

For this PR specifically, the objective is to decouple `Components` from
`Storages`. What components are registered etc should have nothing to do
with what Storages looks like. Storages should only care about what
entity archetypes have been spawned.

## Solution

Previously, this was used to create sparse sets for relevant components
when those components were registered. Now, we do that when the
component is inserted/spawned.

This PR proposes doing that in `BundleInfo::new`, but there may be a
better place.

## Testing

In theory, this shouldn't have changed any functionality, so no new
tests were created. I'm not aware of any examples that make heavy use of
sparse set components either.

## Migration Guide

- Remove storages from functions where it is no longer needed.
- Note that SparseSets are no longer present for all registered sparse
set components, only those that have been spawned.

---------

Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-02-05 19:59:30 +00:00
Zachary Harrold
d0c0bad7b4
Split Component::register_component_hooks into individual methods (#17685)
# Objective

- Fixes #17411

## Solution

- Deprecated `Component::register_component_hooks`
- Added individual methods for each hook which return `None` if the hook
is unused.

## Testing

- CI

---

## Migration Guide

`Component::register_component_hooks` is now deprecated and will be
removed in a future release. When implementing `Component` manually,
also implement the respective hook methods on `Component`.

```rust
// Before
impl Component for Foo {
    // snip
    fn register_component_hooks(hooks: &mut ComponentHooks) {
            hooks.on_add(foo_on_add);
    }
}

// After
impl Component for Foo {
    // snip
    fn on_add() -> Option<ComponentHook> {
            Some(foo_on_add)
    }
}
```

## Notes

I've chosen to deprecate `Component::register_component_hooks` rather
than outright remove it to ease the migration guide. While it is in a
state of deprecation, it must be used by
`Components::register_component_internal` to ensure users who haven't
migrated to the new hook definition scheme aren't left behind. For users
of the new scheme, a default implementation of
`Component::register_component_hooks` is provided which forwards the new
individual hook implementations.

Personally, I think this is a cleaner API to work with, and would allow
the documentation for hooks to exist on the respective `Component`
methods (e.g., documentation for `OnAdd` can exist on
`Component::on_add`). Ideally, `Component::on_add` would be the hook
itself rather than a getter for the hook, but it is the only way to
early-out for a no-op hook, which is important for performance.

## Migration Guide

`Component::register_component_hooks` has been deprecated. If you are
manually implementing the `Component` trait and registering hooks there,
use the individual methods such as `on_add` instead for increased
clarity.
2025-02-05 19:33:05 +00:00
Sludge
ff466a37df
Add weak_handle! convenience macro (#17384)
# Objective

- A common bevy pattern is to pre-allocate a weak `Handle` with a
static, random ID and fill it during `Plugin::build` via
`load_internal_asset!`
- This requires generating a random 128-bit number that is interpreted
as a UUID. This is much less convenient than generating a UUID directly,
and also, strictly speaking, error prone, since it often results in an
invalid UUIDv4 – they have to follow the pattern
`xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx`, where `x` is a random nibble (in
practice this doesn't matter, since the UUID is just interpreted as a
bag of bytes).

## Solution

- Add a `weak_handle!` macro that internally calls
[`uuid::uuid!`](https://docs.rs/uuid/1.12.0/uuid/macro.uuid.html) to
parse a UUID from a string literal.
- Now any random UUID generation tool can be used to generate an asset
ID, such as `uuidgen` or entering "uuid" in DuckDuckGo.

Previously:

```rust
const SHADER: Handle<Shader> = Handle::weak_from_u128(314685653797097581405914117016993910609);
```

After this PR:

```rust
const SHADER: Handle<Shader> = weak_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
```

Note that I did not yet migrate any of the existing uses. I can do that
if desired, but want to have some feedback first to avoid wasted effort.

## Testing

Tested via the included doctest.
2025-02-05 19:30:33 +00:00
ickshonpe
03ec6441a7
Basic UI text shadows (#17559)
# Objective

Basic `TextShadow` support. 

## Solution

New `TextShadow` component with `offset` and `color` fields. Just insert
it on a `Text` node to add a shadow.
New system `extract_text_shadows` handles rendering.

It's not "real" shadows just the text redrawn with an offset and a
different colour. Blur-radius support will need changes to the shaders
and be a lot more complicated, whereas this still looks okay and took a
couple of minutes to implement.

I added the `TextShadow` component to `bevy_ui` rather than `bevy_text`
because it only supports the UI atm.
We can add a `Text2d` version in a followup but getting the same effect
in `Text2d` is trivial even without official support.

---

## Showcase

<img width="122" alt="text_shadow"
src="https://github.com/user-attachments/assets/0333d167-c507-4262-b93b-b6d39e2cf3a4"
/>
<img width="136" alt="g"
src="https://github.com/user-attachments/assets/9b01d5d9-55c9-4af7-9360-a7b04f55944d"
/>
2025-02-05 19:29:37 +00:00
theotherphil
ca6b07c348
Fix a couple of doc typos (#17673)
# Objective

Fix two minor typos in bevy_picking docs.
2025-02-05 19:29:22 +00:00
couyit
03af547c28
Move Item and fetch to QueryData from WorldQuery (#17679)
# Objective

Fixes #17662

## Solution

Moved `Item` and `fetch` from `WorldQuery` to `QueryData`, and adjusted
their implementations accordingly.

Currently, documentation related to `fetch` is written under
`WorldQuery`. It would be more appropriate to move it to the `QueryData`
documentation for clarity.

I am not very experienced with making contributions. If there are any
mistakes or areas for improvement, I would appreciate any suggestions
you may have.

## Migration Guide

The `WorldQuery::Item` type and `WorldQuery::fetch` method have been
moved to `QueryData`, as they were not useful for `QueryFilter` types.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-02-05 18:46:18 +00:00
ickshonpe
6be11a8a42
Change GhostNode into a unit type (#17692)
# Objective

The feature gates for the `UiChildren` and `UiRootNodes` system params
make the unconstructable `GhostNode` `PhantomData` trick redundant.


## Solution

Remove the `GhostNode::new` method and change `GhostNode` into a unit
struct.

## Testing

```cargo run --example ghost_nodes```

still works
2025-02-05 18:44:37 +00:00
Chris Russell
6f39e44c48
Introduce methods on QueryState to obtain a Query (#15858)
# Objective

Simplify and expand the API for `QueryState`.  

`QueryState` has a lot of methods that mirror those on `Query`. These
are then multiplied by variants that take `&World`, `&mut World`, and
`UnsafeWorldCell`. In addition, many of them have `_manual` variants
that take `&QueryState` and avoid calling `update_archetypes()`. Not all
of the combinations exist, however, so some operations are not possible.

## Solution

Introduce methods to get a `Query` from a `QueryState`. That will reduce
duplication between the types, and ensure that the full `Query` API is
always available for `QueryState`.

Introduce methods on `Query` that consume the query to return types with
the full `'w` lifetime. This avoids issues with borrowing where things
like `query_state.query(&world).get(entity)` don't work because they
borrow from the temporary `Query`.

Finally, implement `Copy` for read-only `Query`s. `get_inner` and
`iter_inner` currently take `&self`, so changing them to consume `self`
would be a breaking change. By making `Query: Copy`, they can consume a
copy of `self` and continue to work.

The consuming methods also let us simplify the implementation of methods
on `Query`, by doing `fn foo(&self) { self.as_readonly().foo_inner() }`
and `fn foo_mut(&mut self) { self.reborrow().foo_inner() }`. That
structure makes it more difficult to accidentally extend lifetimes,
since the safe `as_readonly()` and `reborrow()` methods shrink them
appropriately. The optimizer is able to see that they are both identity
functions and inline them, so there should be no performance cost.

Note that this change would conflict with #15848. If `QueryState` is
stored as a `Cow`, then the consuming methods cannot be implemented, and
`Copy` cannot be implemented.

## Future Work

The next step is to mark the methods on `QueryState` as `#[deprecated]`,
and move the implementations into `Query`.

## Migration Guide

`Query::to_readonly` has been renamed to `Query::as_readonly`.
2025-02-05 18:33:15 +00:00
charlotte
2ea5e9b846
Cold Specialization (#17567)
# Cold Specialization

## Objective

An ongoing part of our quest to retain everything in the render world,
cold-specialization aims to cache pipeline specialization so that
pipeline IDs can be recomputed only when necessary, rather than every
frame. This approach reduces redundant work in stable scenes, while
still accommodating scenarios in which materials, views, or visibility
might change, as well as unlocking future optimization work like
retaining render bins.

## Solution

Queue systems are split into a specialization system and queue system,
the former of which only runs when necessary to compute a new pipeline
id. Pipelines are invalidated using a combination of change detection
and ECS ticks.

### The difficulty with change detection

Detecting “what changed” can be tricky because pipeline specialization
depends not only on the entity’s components (e.g., mesh, material, etc.)
but also on which view (camera) it is rendering in. In other words, the
cache key for a given pipeline id is a view entity/render entity pair.
As such, it's not sufficient simply to react to change detection in
order to specialize -- an entity could currently be out of view or could
be rendered in the future in camera that is currently disabled or hasn't
spawned yet.

### Why ticks?

Ticks allow us to ensure correctness by allowing us to compare the last
time a view or entity was updated compared to the cached pipeline id.
This ensures that even if an entity was out of view or has never been
seen in a given camera before we can still correctly determine whether
it needs to be re-specialized or not.

## Testing

TODO: Tested a bunch of different examples, need to test more.

## Migration Guide

TODO

- `AssetEvents` has been moved into the `PostUpdate` schedule.

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
2025-02-05 18:31:20 +00:00
Vic
be9b38e372
implement UniqueEntitySlice (#17589)
# Objective

Follow-up to #17549 and #16547.

A large part of `Vec`s usefulness is behind its ability to be sliced,
like sorting f.e., so we want the same to be possible for
`UniqueEntityVec`.

## Solution

Add a `UniqueEntitySlice` type. It is a wrapper around `[T]`, and itself
a DST.

Because `mem::swap` has a `Sized` bound, DSTs cannot be swapped, and we
can freely hand out mutable subslices without worrying about the
uniqueness invariant of the backing collection!
`UniqueEntityVec` and the relevant `UniqueEntityIter`s now have methods
and trait impls that return `UniqueEntitySlice`s.
`UniqueEntitySlice` itself can deref into normal slices, which means we
can avoid implementing the vast majority of immutable slice methods.

Most of the remaining methods:
- split a slice/collection in further unique subsections/slices
- reorder the slice: `sort`, `rotate_*`, `swap`
- construct/deconstruct/convert pointer-like types: `Box`, `Arc`, `Rc`,
`Cow`
- are comparison trait impls

As this PR is already larger than I'd like, we leave several things to
follow-ups:
- `UniqueEntityArray` and the related slice methods that would return it
    - denoted by "chunk", "array_*" for iterators
- Methods that return iterators with `UniqueEntitySlice` as their item 
    - `windows`, `chunks` and `split` families
- All methods that are capable of actively mutating individual elements.
While they could be offered unsafely, subslicing makes their safety
contract weird enough to warrant its own discussion.
- `fill_with`, `swap_with_slice`, `iter_mut`, `split_first/last_mut`,
`select_nth_unstable_*`

Note that `Arc`, `Rc` and `Cow` are not fundamental types, so even if
they contain `UniqueEntitySlice`, we cannot write direct trait impls for
them.
On top of that, `Cow` is not a receiver (like `self: Arc<Self>` is) so
we cannot write inherent methods for it either.
2025-02-05 18:10:56 +00:00
Patrick Walton
69b2ae871c
Don't reallocate work item buffers every frame. (#17684)
We were calling `clear()` on the work item buffer table, which caused us
to deallocate all the CPU side buffers. This patch changes the logic to
instead just clear the buffers individually, but leave their backing
stores. This has two consequences:

1. To effectively retain work item buffers from frame to frame, we need
to key them off `RetainedViewEntity` values and not the render world
`Entity`, which is transient. This PR changes those buffers accordingly.

2. We need to clean up work item buffers that belong to views that went
away. Amusingly enough, we actually have a system,
`delete_old_work_item_buffers`, that tries to do this already, but it
wasn't doing anything because the `clear_batched_gpu_instance_buffers`
system already handled that. This patch actually makes the
`delete_old_work_item_buffers` system useful, by removing the clearing
behavior from `clear_batched_gpu_instance_buffers` and instead making
`delete_old_work_item_buffers` delete buffers corresponding to
nonexistent views.

On Bistro, this PR improves the performance of
`batch_and_prepare_binned_render_phase` from 61.2 us to 47.8 us, a 28%
speedup.

![Screenshot 2025-02-04
135542](https://github.com/user-attachments/assets/b0ecb551-f6c8-4677-8e4e-e39aa28115a3)
2025-02-05 17:37:24 +00:00
Patrick Walton
48049f7256
Don't mark a previous mesh transform as changed if it didn't actually change. (#17688)
This patch fixes a bug whereby we're re-extracting every mesh every
frame. It's a regression from PR #17413. The code in question has
actually been in the tree with this bug for quite a while; it's that
just the code didn't actually run unless the renderer considered the
previous view transforms necessary. Occlusion culling expanded the set
of circumstances under which Bevy computes the previous view transforms,
causing this bug to appear more often.

This patch fixes the issue by checking to see if the previous transform
of a mesh actually differs from the current transform before copying the
current transform to the previous transform.
2025-02-05 17:35:19 +00:00
Zachary Harrold
642e016aef
Bump to uuid 1.13.1 and enable js on wasm targets (#17689)
# Objective

- Fixes CI failure due to `uuid` 1.13 using the new version of
`getrandom` which requires using a new API to work on Wasm.

## Solution

- Based on [`uuid` 1.13 release
notes](https://github.com/uuid-rs/uuid/releases/tag/1.13.0) I've enabled
the `js` feature on `wasm32`. This will need to be revisited once #17499
is up for review
- Updated minimum `uuid` version to 1.13.1, which fixes a separate issue
with `target_feature = atomics` on `wasm`.

## Testing

- `cargo check --target wasm32-unknown-unknown`
2025-02-05 06:05:32 +00:00
charlotte
8c7f1b34d3
Fix text-2d. (#17674)
# Objective

Fix text 2d. Fixes https://github.com/bevyengine/bevy/issues/17670

## Solution

Evidently there's a 1:N extraction going on here that requires using the
render entity rather than main entity.

## Testing

Text 2d example
2025-02-04 21:32:14 +00:00
Patrick Walton
18c4050dd2
Make batch_and_prepare_binned_render_phase only record information about the first batch in each batch set. (#17680)
Data for the other batches is only accessed by the GPU, not the CPU, so
it's a waste of time and memory to store information relating to those
other batches.

On Bistro, this reduces time spent in
`batch_and_prepare_binned_render_phase` from 85.9 us to 61.2 us, a 40%
speedup.

![Screenshot 2025-02-04
093315](https://github.com/user-attachments/assets/eb00db93-a260-44f9-9ae0-4e90b0697138)
2025-02-04 19:26:36 +00:00
Alice Cecile
0ca9d6968a
Improve docs for WorldQuery (#17654)
# Objective

While working on #17649, I found the docs for `WorldQuery` and the
related traits frustratingly vague.

## Solution

Clarify them and add some more tangible advice.

Also fix a copy-pasted typo in related comments.

---------

Co-authored-by: James O'Brien <james.obrien@drafly.net>
2025-02-03 22:13:42 +00:00
Mincong Lu
29d0ef6f3a
Added try_map_unchanged. (#17653)
# Objective

Allow mapping `Mut` to another value while returning a custom error on
failure.

## Solution

Added `try_map_unchanged` to `Mut` which returns a `Result` instead of
`Option` .
2025-02-03 22:03:39 +00:00
Johannes Ringler
bdf60d6933
Warnings and docs for exponential denormalization in rotate functions (alternative to #17604) (#17646)
# Objective

- When obtaining an axis from the transform and putting that into
`Transform::rotate_axis` or `Transform::rotate_axis_local`, floating
point errors could accumulate exponentially, resulting in denormalized
rotation.
- This is an alternative to and closes #17604, due to lack of consent
around this in the [discord
discussion](https://discord.com/channels/691052431525675048/1203087353850364004/1334232710658392227)
- Closes #16480 

## Solution

- Add a warning of this issue and a recommendation to normalize to the
API docs.
- Add a runtime warning that checks for denormalized axis in debug mode,
with a reference to the API docs.
2025-02-03 22:02:12 +00:00
Chris Russell
2d66099f3d
Fix access checks for DeferredWorld as SystemParam. (#17616)
# Objective

Prevent unsound uses of `DeferredWorld` as a `SystemParam`. It is
currently unsound because it does not check for existing access, and
because it incorrectly registers filtered access.

## Solution

Have `DeferredWorld` panic if a previous parameter has conflicting
access.

Have `DeferredWorld` update `archetype_component_access` so that the
multi-threaded executor sees the access.

Fix `FilteredAccessSet::read_all()` and `write_all()` to correctly add a
`FilteredAccess` with no filter so that `Query` is able to detect the
conflicts.

Remove redundant `read_all()` call, since `write_all()` already declares
read access.

Remove unnecessary `set_has_deferred()` call, since `<DeferredWorld as
SystemParam>::apply_deferred()` does nothing. Previously we were
inserting unnecessary `apply_deferred` systems in the schedule.

## Testing

Added unit tests for systems where `DeferredWorld` conflicts with a
`Query` in the same system.
2025-02-03 21:58:07 +00:00
Erick Z
b978b13a7b
Implementing Reflect on *MeshBuilder types (#17600)
# Objective

- Most of the `*MeshBuilder` classes are not implementing `Reflect`

## Solution

- Implementing `Reflect` for all `*MeshBuilder` were is possible.
- Make sure all `*MeshBuilder` implements `Default`.
- Adding new `MeshBuildersPlugin` that registers all `*MeshBuilder`
types.

## Testing

- `cargo run -p ci`
- Tested some examples like `3d_scene` just in case something was
broken.
2025-02-03 21:53:51 +00:00
Máté Homolya
f22ea72db0
Atmosphere LUT parameterization improvements (#17555)
# Objective

- Fix the atmosphere LUT parameterization in the aerial -view and
sky-view LUTs
- Correct the light accumulation according to a ray-marched reference
- Avoid negative values of the sun disk illuminance when the sun disk is
below the horizon

## Solution

- Adding a Newton's method iteration to `fast_sqrt` function
- Switched to using `fast_acos_4` for better precision of the sun angle
towards the horizon (view mu angle = 0)
- Simplified the function for mapping to and from the Sky View UV
coordinates by removing an if statement and correctly apply the method
proposed by the [Hillarie
paper](https://sebh.github.io/publications/egsr2020.pdf) detailed in
section 5.3 and 5.4.
- Replaced the `ray_dir_ws.y` term with a shadow factor in the
`sample_sun_illuminance` function that correctly approximates the sun
disk occluded by the earth from any view point

## Testing

- Ran the atmosphere and SSAO examples to make sure the shaders still
compile and run as expected.

---

## Showcase

<img width="1151" alt="showcase-img"
src="https://github.com/user-attachments/assets/de875533-42bd-41f9-9fd0-d7cc57d6e51c"
/>

---------

Co-authored-by: Emerson Coskey <emerson@coskey.dev>
2025-02-03 21:52:11 +00:00
Joseph
721bb91987
Add basic debug checks for read-only UnsafeWorldCell (#17393)
# Objective

The method `World::as_unsafe_world_cell_readonly` is used to create an
`UnsafeWorldCell` which is only allowed to access world data immutably.
This can be tricky to use, as the data that an `UnsafeWorldCell` is
allowed to access exists only in documentation (you could think of it as
a "doc-time abstraction" rather than a "compile-time" abstraction). It's
quite easy to forget where a particular instance came from and attempt
to use it for mutable access, leading to instant, silent undefined
behavior.

## Solution

Add a debug-mode only flag to `UnsafeWorldCell` which tracks whether or
not the instance can be used to access world data mutably. This should
catch basic improper usages of `as_unsafe_world_cell_readonly`.

## Future work

There are a few ways that you can bypass the runtime checks introduced
by this PR:

* Any world accesses done via `UnsafeWorldCell::storages` are completely
invisible to these runtime checks. Unfortunately, `storages` constitutes
most of the world accesses used in the engine itself, so this PR will
mostly benefit downstream users of bevy.
* It's possible to call `get_resource_by_id`, and then convert the
returned `Ptr` to a `PtrMut` by calling `assert_unique`. In the future
we'll probably want to add a debug-mode only flag to `Ptr` which tracks
whether or not it can be upgraded to a `PtrMut`. I didn't include this
change in this PR as those types are currently defined using macros
which makes it a bit tricky to modify their definitions.
* Any data accesses done through a mutable `UnsafeWorldCell` are
completely unchecked, meaning it's possible to unsoundly create multiple
mutable references to a single component, for example. In the future we
may want to store an `Access<>` set inside of the world's `Storages` to
add granular debug-mode runtime checks.

That said, I'd consider this PR to be a good first step towards adding
full runtime checks to `UnsafeWorldCell`.

## Testing

Added a few tests that basic invalid mutable world access result in a
panic.

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: Alice I Cecile <alice.i.cecile@gmail.com>
2025-02-03 21:46:39 +00:00
Rob Parrett
adcc80c43d
Improve TextSpan docs (#17415)
# Objective

Our
[`TextSpan`](https://docs.rs/bevy/latest/bevy/prelude/struct.TextSpan.html)
docs include a code example that does not actually "work." The code
silently does not render anything, and the `Text*Writer` helpers fail.

This seems to be by design, because we can't use `Text` or `Text2d` from
`bevy_ui` or `bevy_sprite` within docs in `bevy_text`. (Correct me if I
am wrong)

I have seen multiple users confused by these docs.

Also fixes #16794

## Solution

Remove the code example from `TextSpan`, and instead encourage users to
seek docs on `Text` or `Text2d`.

Add examples with nested `TextSpan`s in those areas.
2025-02-03 21:36:52 +00:00
ickshonpe
f62775235d
Revert #17631 (#17660)
# Objective

Revert #17631

After some more experimentation, realised it's not the right approach.
2025-02-03 19:01:15 +00:00
Alice Cecile
da5064889a
Add required serde_derive feature flag to bevy_ecs (#17651)
# Objective

```
cargo test --package bevy_ecs --lib --all-features
```

fails to compile, with output like

> error[E0433]: failed to resolve: could not find `Serialize` in `serde`
>    --> crates/bevy_ecs/src/entity/index_set.rs:14:69
>     |
> 14 | #[cfg_attr(feature = "serialize", derive(serde::Deserialize,
serde::Serialize))]
> | ^^^^^^^^^ could not find `Serialize` in `serde`
>     |
> note: found an item that was configured out
> -->
/home/alice/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.217/src/lib.rs:343:37
>     |
> 343 | pub use serde_derive::{Deserialize, Serialize};
>     |                                     ^^^^^^^^^
> note: the item is gated behind the `serde_derive` feature
> -->
/home/alice/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.217/src/lib.rs:341:7
>     |
> 341 | #[cfg(feature = "serde_derive")]
>     |       ^^^^^^^^^^^^^^^^^^^^^^^^


## Solution

Add the required feature flags and get bevy_ecs compiling standalone
corrctly.

## Testing

The command above now compiles succesfully. Note that several system
stepping tests are failing, and were not being tested in CI. That's a
different PR's problem though.
2025-02-03 03:19:57 +00:00
charlotte
aab39d5693
Move sprite batches to resource (#17636)
# Objective

Currently, `prepare_sprite_image_bind_group` spawns sprite batches onto
an individual representative entity of the batch. This poses significant
problems for multi-camera setups, since an entity may appear in multiple
phase instances.

## Solution

Instead, move batches into a resource that is keyed off the view and the
representative entity. Long term we should switch to mesh2d and use the
existing BinnedRenderPhase functionality rather than naively queueing
into transparent and doing our own ad-hoc batching logic.

Fixes #16867, #17351

## Testing

Tested repros in above issues.
2025-02-02 22:08:57 +00:00
NiseVoid
62285a47ba
Add simple Disabled marker (#17514)
# Objective

We have default query filters now, but there is no first-party marker
for entity disabling yet
Fixes #17458

## Solution

Add the marker, cool recursive features and/or potential hook changes
should be follow up work

## Testing

Added a unit test to check that the new marker is enabled by default
2025-02-02 21:42:25 +00:00
Periwink
75e8e8c0f6
Expose ObserverDescriptor fields (#17623)
# Objective

Expose accessor functions to the `ObserverDescriptor`, so that users can
use the `Observer` component to inspect what the observer is watching.
This would be useful for me, I don't think there's any reason to hide
these.
2025-02-02 20:10:37 +00:00
Lucas Franca
55283bb115
Revert "Fix rounding bug in camera projection (#16828)" (#17592)
This reverts commit ae522225cd.

# Objective

Fixes #16856

## Solution

Remove rounding from `OrthographicProjection::update`, which was causing
the center of the orthographic projection to be off center.

## Testing

Ran the examples mentioned on #16856 and code from #16773

## Showcase
`orthographic` example

![image](https://github.com/user-attachments/assets/d3bb1480-5908-4427-b1f2-af8a5c411745)

`projection_zoom` example

![image](https://github.com/user-attachments/assets/e560c81b-db8f-44f0-91f4-d6bae3ae7f32)

`camera_sub_view` example

![image](https://github.com/user-attachments/assets/615e9eb8-f4e5-406a-b98a-501f7d652145)

`custom_primitives` example

![image](https://github.com/user-attachments/assets/8fd7702e-07e7-47e3-9510-e247d268a3e7)

#16773 code

![image](https://github.com/user-attachments/assets/1b759e90-6c53-4279-987e-284518db034b)
2025-02-02 19:16:13 +00:00
mgi388
756948e311
Fix cursor hotspot out of bounds when flipping (#17571)
# Objective

- Fix off by one error introduced in
https://github.com/bevyengine/bevy/pull/17540 causing:

```
Cursor image StrongHandle<Image>{ id: Index(AssetIndex { generation: 0, index: 3 }), path: Some(cursors/kenney_crosshairPack/Tilesheet/crosshairs_tilesheet_white.png) } is invalid: The specified hotspot (64, 64) is outside the image bounds (64x64).
```

- First PR commit and run shows the bug:
https://github.com/bevyengine/bevy/actions/runs/13009405866/job/36283507530?pr=17571
- Second PR commit fixes it.

## Solution

- Hotspot coordinates are 0-indexed, so we need to subtract 1 from the
width and height.

## Testing

- Fix the tests which included the off-by-one error in their expected
values.
- Consolidate the tests into a single test for brevity.
- Test round trip transform to ensure we can "undo" to get back to the
original value.
- Add a specific bounds test.
- Ran the example again and observed there are no more error logs:
`cargo run --example custom_cursor_image --features=custom_cursor`.
2025-02-02 18:22:34 +00:00
Mathspy
469b218f20
Improve ergonomics of platform_support's Instant (#17577)
# Objective

- Make working with `bevy_time` more ergonomic in `no_std` environments.

Currently `bevy_time` expects the getter in environments where time
can't be obtained automatically via the instruction set or the standard
library to be of type `*mut fn() -> Duration`.
[`fn()`](https://doc.rust-lang.org/beta/std/primitive.fn.html) is
already a function pointer, so `*mut fn()` is a _pointer to a function
pointer_. This is harder to use and error prone since creating a pointer
out of something like `&mut fn() -> Duration` when the lifetime of the
reference isn't static will lead to an undefined behavior once the
reference is freed

## Solution

- Accept a `fn() -> Duration` instead

## Testing

- I made a whole game on the Playdate that relies on `bevy_time`
heavily, see:
[bevydate_time](1b4f02adcd/src/lib.rs (L510-L546))
for usage of the Instant's getter.

---

## Showcase

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


https://github.com/user-attachments/assets/f687847f-6b62-4322-95f3-c908ada3db30

</details>

## Migration Guide

This is a breaking change but it's not for people coming from Bevy v0.15

### Small thank you note
Thanks to my friend https://github.com/repnop for helping me understand
how to deal with function pointers in `unsafe` environments

Co-authored-by: Wesley Norris <repnop@repnop.dev>
2025-02-02 15:50:48 +00:00
Joona Aalto
9165fb020a
Implement Serialize/Deserialize for entity collections (#17620)
# Objective

Follow-up to #17615.

Bevy's entity collection types like `EntityHashSet` no longer implement
serde's `Serialize` and `Deserialize` after becoming newtypes instead of
type aliases in #16912. This broke some types that support serde for me
in Avian.

I also missed creating const constructors for `EntityIndexMap` and
`EntityIndexSet` in #17615. Oops!

## Solution

Implement `Serialize` and `Deserialize` for Bevy's entity collection
types, and add const constructors for `EntityIndexMap` and
`EntityIndexSet`.

I didn't implement `ReflectSerialize` or `ReflectDeserialize` here,
because I had some trouble fixing the resulting errors, and they were
not implemented previously either.
2025-02-02 15:42:36 +00:00
IceSentry
9c5ce33e1d
Use more headers in AsBindGroup docs (#17586)
# Objective

- Linking to a specific AsBindGroup attribute is hard because it doesn't
use any headers and all the docs is in a giant block

## Solution

- Make each attribute it's own sub-header so they can be easily linked

---

## Showcase

Here's what the rustdoc output looks like with this change


![image](https://github.com/user-attachments/assets/4987b03c-c75d-4a5f-89b7-0c356b61706a)

## Notes

I kept the bullet point so the text is still indented like before. Not
sure if we should keep that or not
2025-02-02 15:18:39 +00:00
Erick Z
416100a253
Fixing ValArithmeticError typo and unused variant (#17597)
# Objective

- `ValArithmeticError` contains a typo, and one of it's variants is not
used

## Solution

- Rename `NonEvaluateable::NonEvaluateable ` variant to
`NonEvaluateable::NonEvaluable`.
- Remove variant `ValArithmeticError:: NonIdenticalVariants`.

## Testing

- `cargo run -p ci`

---

## Migration Guide


- `ValArithmeticError::NonEvaluateable` has been renamed to
`NonEvaluateable::NonEvaluable`
- `ValArithmeticError::NonIdenticalVariants ` has been removed
2025-02-02 15:10:14 +00:00
RobWalt
a893c5d572
feat: impl Ease for Isometry[2/3]d (#17545)
# Objective

- We kind of missed out on implementing the `Ease` trait for some
objects like `Isometry2D` and `Isometry3D` even though it makes sense
and isn't that hard
- Fixes #17539

## Testing

- wrote some minimal tests
- ~~noticed that quat easing isn't working as expected yet~~ I just
confused degrees and radians once again 🙈
2025-02-02 15:07:35 +00:00
ickshonpe
89a1c49377
Fix Taffy viewport node leaks (#17596)
# Objective

For most UI node entities there's a 1-to-1 mapping from the entity to
its associated Taffy node. Root UI nodes are an exception though, their
corresponding Taffy node in the Taffy tree is also given a parent that
represents the viewport. These viewport Taffy nodes are not removed when
a root UI node is despawned.

Parenting of an existing root UI node with an associated viewport Taffy
node also results in the leak of the viewport node.

These tests fail if added to the `layout` module's tests on the main
branch:

```rust
    #[test]
    fn no_viewport_node_leak_on_root_despawned() {
        let (mut world, mut ui_schedule) = setup_ui_test_world();

        let ui_root_entity = world.spawn(Node::default()).id();

        // The UI schedule synchronizes Bevy UI's internal `TaffyTree` with the
        // main world's tree of `Node` entities.
        ui_schedule.run(&mut world);

        // Two taffy nodes are added to the internal `TaffyTree` for each root UI entity.
        // An implicit taffy node representing the viewport and a taffy node corresponding to the
        // root UI entity which is parented to the viewport taffy node.
        assert_eq!(
            world.resource_mut::<UiSurface>().taffy.total_node_count(),
            2
        );

        world.despawn(ui_root_entity);

        // The UI schedule removes both the taffy node corresponding to `ui_root_entity` and its
        // parent viewport node.
        ui_schedule.run(&mut world);

        // Both taffy nodes should now be removed from the internal `TaffyTree`
        assert_eq!(
            world.resource_mut::<UiSurface>().taffy.total_node_count(),
            0
        );
    }

    #[test]
    fn no_viewport_node_leak_on_parented_root() {
        let (mut world, mut ui_schedule) = setup_ui_test_world();

        let ui_root_entity_1 = world.spawn(Node::default()).id();
        let ui_root_entity_2 = world.spawn(Node::default()).id();

        ui_schedule.run(&mut world);

        // There are two UI root entities. Each root taffy node is given it's own viewport node parent,
        // so a total of four taffy nodes are added to the `TaffyTree` by the UI schedule.
        assert_eq!(
            world.resource_mut::<UiSurface>().taffy.total_node_count(),
            4
        );

        // Parent `ui_root_entity_2` onto `ui_root_entity_1` so now only `ui_root_entity_1` is a
        // UI root entity.
        world
            .entity_mut(ui_root_entity_1)
            .add_child(ui_root_entity_2);

        // Now there is only one root node so the second viewport node is removed by
        // the UI schedule.
        ui_schedule.run(&mut world);

        // There is only one viewport node now, so the `TaffyTree` contains 3 nodes in total.
        assert_eq!(
            world.resource_mut::<UiSurface>().taffy.total_node_count(),
            3
        );
    }
```

Fixes #17594

## Solution

Change the `UiSurface::entity_to_taffy` to map to `LayoutNode`s. A
`LayoutNode` has a `viewport_id: Option<taffy::NodeId>` field which is
the id of the corresponding implicit "viewport" node if the node is a
root UI node, otherwise it is `None`. When removing or parenting nodes
this field is checked and the implicit viewport node is removed if
present.

## Testing

There are two new tests in `bevy_ui::layout::tests` included with this
PR:
* `no_viewport_node_leak_on_root_despawned`
* `no_viewport_node_leak_on_parented_root`
2025-02-02 15:03:10 +00:00
ickshonpe
afef7d5797
queue_sprites comment fix (#17621)
# Objective

Fix this comment in `queue_sprites`:
```
// batch_range and dynamic_offset will be calculated in prepare_sprites.
```
`Transparent2d` no longer has a `dynamic_offset` field and the
`batch_range` is calculated in `prepare_sprite_image_bind_groups` now.
2025-02-02 14:49:12 +00:00
ickshonpe
74acb95ed3
anti-alias outside the edges of UI nodes, not across them (#17631)
# Objective

Fixes #17561

## Solution

The anti-aliasing function used by the UI fragment shader is this:
```wgsl
fn antialias(distance: f32) -> f32 {
    return saturate(0.5 - distance);      // saturate clamps between 0 and 1
}
```
The returned value is multiplied with the alpha channel value to get the
anti-aliasing effect.

The `distance` is a signed distance value. A positive `distance` means
we are outside the shape we're drawing and a negative `distance` means
we are on the inside.

So with `distance` at `0` (on the edge of the shape):
```
antialias(0) = saturate(0.5 - 0) = saturate(0.5) = 0.5
```
but we want it to be `1` at this point, so the entire interior of the
shape is given a solid colour, and then decrease as the signed distance
increases.

So in this PR we change it to:
```wgsl
fn antialias(distance: f32) -> f32 {
    return saturate(1. - distance);
}
```
Then:
```
antialias(-0.5) = saturate(1 - (-1)) = saturate(2) = 1
antialias(1) = saturate(1 - 0) = 1
antialias(0.5) = saturate(1 - 0.5) = 0.5
antialias(1) = saturate(1 - 1) = 0
```
as desired.

## Testing

```cargo run --example button```

On main:
<img width="400" alt="bleg" src="https://github.com/user-attachments/assets/314994cb-4529-479d-b179-18e5c25f75bc" />

With this PR:
<img width="400" alt="bbwhite" src="https://github.com/user-attachments/assets/072f481d-8b67-4fae-9a5f-765090d1713f" />

Modified the `button` example to draw a white background to make the bleeding more obvious.
2025-02-02 14:44:31 +00:00
Patrick Walton
7774a624c2
Fix Maya-exported rigs by not trying to topologically sort glTF nodes. (#17641)
The code added in #14343 seems to be trying to ensure that a `Handle`
for each glTF node exists by topologically sorting the directed graph of
glTF nodes containing edges from parent to child and from skin to joint.
Unfortunately, such a graph can contain cycles, as there's no guarantee
that joints are descendants of nodes with the skin. In particular, glTF
exported from Maya using the popular babylon.js export plugin create
skins attached to nodes that animate their parent nodes. This was
causing the topological sort code to enter an infinite loop.

Assuming that the intent of the topological sort is indeed to ensure
that `Handle`s exist for each glTF node before populating them, there's
a better mechanism for this: `LoadContext::get_label_handle`. This is
the documented way to obtain a handle for a node before populating it,
obviating the need for a topological sort. This patch replaces the
topological sort with a pre-pass that uses
`LoadContext::get_label_handle` to get handles for each `Node` before
populating them. This fixes the problem with Maya rigs, in addition to
making the code simpler and faster.
2025-02-02 13:53:55 +00:00
ElliottjPierce
361397fcac
Add a test for direct recursion in required components. (#17626)
I realized there wasn't a test for this yet and figured it would be
trivial to add. Why not? Unless there was a test for this, and I just
missed it?

I appreciate the unique error message it gives and wanted to make sure
it doesn't get broken at some point. Or worse, endlessly recurse.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-02 06:47:10 +00:00
François Mockers
e57f73207e
Smarter testbeds (#17573)
# Objective

- Improve CI when testing rendering by having smarter testbeds

## Solution

- CI testing no longer need a config file and will run with a default
config if not found
- It is now possible to give a name to a screenshot instead of just a
frame number
- 2d and 3d testbeds are now driven from code
  - a new system in testbed will watch for state changed
- on state changed, trigger a screenshot 100 frames after (so that the
scene has time to render) with the name of the scene
- when the screenshot is taken (`Captured` component has been removed),
switch scene
- this means less setup to run a testbed (no need for a config file),
screenshots have better names, and it's faster as we don't wait 100
frames for the screenshot to be taken

## Testing

- `cargo run --example testbed_2d --features bevy_ci_testing`
2025-01-31 22:38:39 +00:00
Sven Niederberger
fcd1847a48
Image::get_color_at and Image::set_color_at: Support 16-bit float values (#17550)
# Objective

- Also support `f16` values when getting and setting colors.

## Solution

- Use the `half` crate to work with `f16` until it's in stable Rust.
2025-01-31 00:36:11 +00:00
ickshonpe
ba1b0092e5
Extract UI nodes into a Vec (#17618)
# Objective

Extract UI nodes into a `Vec` instead of an `EntityHashMap`.

## Solution

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

## Showcase

Yellow this PR, Red main

```
cargo run --example many_buttons --release --features trace_tracy
```

`extract_uinode_background_colors`
<img width="448" alt="extract_uinode_background_colors"
src="https://github.com/user-attachments/assets/09c0f434-ab4f-4c0f-956a-cf31e9060061"
/>

`extract_uinode_images`
<img width="587" alt="extract_uinode_images"
src="https://github.com/user-attachments/assets/43246d7f-d22c-46d0-9a07-7e13d5379f56"
/>

`prepare_uinodes`
<img width="441" alt="prepare_uinodes_vec"
src="https://github.com/user-attachments/assets/cc9a7eac-60e9-42fa-8093-bce833a1c153"
/>
2025-01-30 23:25:07 +00:00
Joona Aalto
59697f9ccc
Make EntityHashMap::new and EntityHashSet::new const (#17615)
# Objective

#16912 turned `EntityHashMap` and `EntityHashSet` into proper newtypes
instead of type aliases. However, this removed the ability to create
these collections in const contexts; previously, you could use
`EntityHashSet::with_hasher(EntityHash)`, but it doesn't exist anymore.

## Solution

Make `EntityHashMap::new` and `EntityHashSet::new` const methods.
2025-01-30 17:40:06 +00:00
Chris Russell
7d68ac029e
Use the provided caller instead of Location::caller() in despawn_with_caller() (#17598)
# Objective

Pass the correct location to triggers when despawning entities.
`EntityWorldMut::despawn_with_caller()` currently passes
`Location::caller()` to some triggers instead of the `caller` parameter
it was passed. As `despawn_with_caller()` is not `#[track_caller]`, this
means the location will always be reported as `despawn_with_caller()`
itself.

## Solution

Pass `caller` instead of `Location::caller()`.
2025-01-30 04:50:17 +00:00
Jean Mertz
6bda03cc08
chore: impl PartialEq for bevy_ui::Text and bevy_text::TextColor (#17606)
Adding these allows using `DetectChangesMut::set_if_neq` to only update
the values when needed. Currently you need to get the inner values first
(`String` and `Color`), to do any equality checks.

---------

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-01-30 04:47:29 +00:00
Alexandru Scvorțov
909b02e9de
Fix link to states example (#17595)
Fixes the link to the states example.

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-29 21:44:55 +00:00
janis-bhm
f7c27b534a
Fixes #17508: bevy_color::Color constructor docs get docs matching underlying constructor (#17601)
# Objective

Fixes #17508

`bevy_color::Color` constructors don't have docs explaining the valid
range for the values passed.

## Solution

I've mostly copied the docs from the respective underlying type's docs,
because that seemed most consistent and accurate.
2025-01-29 18:21:23 +00:00
aecsocket
f232674291
Remove unnecessary PartialReflect bound on DeserializeWithRegistry (#17560)
# Objective

The new `DeserializeWithRegistry` trait in 0.15 was designed to be used
with reflection, and so has a `trait DeserializeWithRegistry:
PartialReflect` bound. However, this bound is not actually necessary for
the trait to function properly. And this `PartialReflect` bound already
exists on:
```rs
impl<T: PartialReflect + for<'de> DeserializeWithRegistry<'de>> FromType<T>
    for ReflectDeserializeWithRegistry
```
So there is no point in constraining the trait itself with this bound as
well.

This lets me use `DeserializeWithRegistry` with non-`Reflect` types,
which I want to do to avoid making a bunch of `FooDeserializer` structs
and `impl DeserializeSeed` on them.

## Solution

Removes this unnecessary bound.

## Testing

Trivial change, does not break compilation or `bevy_reflect` tests.

## Migration Guide

`DeserializeWithRegistry` types are no longer guaranteed to be
`PartialReflect` as well. If you were relying on this type bound, you
should add it to your own bounds manually.
```diff
- impl<T: DeserializeWithRegistry> Foo for T { .. }
+ impl<T: DeserializeWithRegistry + PartialReflect> Foo for T { .. }
```
2025-01-29 17:36:39 +00:00
Jean Mertz
b58eda01e2
feat(ecs): add EntityEntryCommands::entity() method chaining (#17580)
This allows you to continue chaining method calls after calling
`EntityCommands::entry`:

```rust
commands
    .entity(player.entity)
    .entry::<Level>()
    // Modify the component if it exists
    .and_modify(|mut lvl| lvl.0 += 1)
    // Otherwise insert a default value
    .or_insert(Level(0))
    // Return the EntityCommands for the entity
    .entity()
    // And continue chaining method calls
    .insert(Name::new("Player"));
```

---------

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-01-29 17:36:02 +00:00
ickshonpe
d4356062bf
UiSurface::upsert_node refactor (#8831)
# Objective

Simplify the `UiSurface::upsert_node` method by directly matching on
HashMap entry states.
2025-01-28 18:05:59 +00:00
ickshonpe
5bbcf646a7
Improved UI camera mapping (#17244)
# Objective

Two more optimisations for UI extraction:
* We only need to query for the camera's render entity when the target
camera changes. If the target camera is the same as for the previous UI
node we can use the previous render entity.
* The cheap checks for visibility and zero size should be performed
first before the camera queries.

## Solution
Add a new system param `UiCameraMap` that resolves the correct render
camera entity and only queries when necessary.

<img width="506" alt="tracee"
src="https://github.com/user-attachments/assets/f57d1e0d-f3a7-49ee-8287-4f01ffc8ba24"
/>

I don't like the `UiCameraMap` + `UiCameraMapper` implementation very
much, maybe someone else can suggest a better construction.

This is partly motivated by #16942 which adds further indirection and
these changes would ameliorate that performance regression.
2025-01-28 18:05:00 +00:00
ickshonpe
a80263a5bf
no-camera many_buttons argument, only emit UI camera warnings once (#17557)
# Objective

* Add a `no-camera` argument to the `many_buttons` stress test example.
* Only emit the UI "no camera found" warnings once.
2025-01-28 18:04:52 +00:00
Vic
b039bf6768
implement UniqueEntityVec (#17549)
# Objective

In #16547, we added `EntitySet`s/`EntitySetIterator`s. We can know
whenever an iterator only contains unique entities, however we do not
yet have the ability to collect and reuse these without either the
unsafe `UniqueEntityIter::from_iterator_unchecked`, or the expensive
`HashSet::from_iter`.
An important piece for being able to do this is a `Vec` that maintains
the uniqueness property, can be collected into, and is itself
`EntitySet`.

A lot of entity collections are already intended to be "unique", but
have no way of expressing that when stored, other than using an
aforementioned `HashSet`. Such a type helps by limiting or even removing
the need for unsafe on the user side when not using a validated `Set`
type, and makes it easier to interface with other infrastructure like
f.e. `RelationshipSourceCollection`s.

## Solution

We implement `UniqueEntityVec`. 

This is a wrapper around `Vec`, that only ever contains unique elements.
It mirrors the API of `Vec`, however restricts any mutation as to not
violate the uniqueness guarantee. Meaning:
- Any inherent method which can introduce new elements or mutate
existing ones is now unsafe, f.e.: `insert`, `retain_mut`
- Methods that are impossible to use safely are omitted, f.e.: `fill`,
`extend_from_within`

A handful of the unsafe methods can do element-wise mutation
(`retain_mut`, `dedup_by`), which can be an unwind safety hazard were
the element-wise operation to panic. For those methods, we require that
each individual execution of the operation upholds uniqueness, not just
the entire method as a whole.

To be safe for mutable usage, slicing and the associated slice methods
require a matching `UniqueEntitySlice` type , which we leave for a
follow-up PR.

Because this type will deref into the `UniqueEntitySlice` type, we also
offer the immutable `Vec` methods on this type (which only amount to a
handful). "as inner" functionality is covered by additional
`as_vec`/`as_mut_vec` methods + `AsRef`/`Borrow` trait impls.
Like `UniqueEntityIter::from_iterator_unchecked`, this type has a
`from_vec_unchecked` method as well.

The canonical way to safely obtain this type however is via
`EntitySetIterator::collect_set` or
`UniqueEntityVec::from_entity_set_iter`. Like mentioned in #17513, these
are named suboptimally until supertrait item shadowing arrives, since a
normal `collect` will still run equality checks.
2025-01-28 06:00:59 +00:00
Sven Niederberger
b25bbb79a0
Image::get_color_at_3d and Image::set_color_at_3d: Support 2D images with layers (#17548)
# Objective

This makes the `Image::get_color_at_3d` and `Image::set_color_at_3d`
methods work with 2D images with more than one layer.

## Solution

- The Z coordinate is interpreted as the layer number.

## Testing

- Added a test: `get_set_pixel_2d_with_layers`.
2025-01-28 05:58:37 +00:00
mgi388
e8cd12daf4
Automatically transform cursor hotspot user asks to flip cursor image (#17540)
# Objective

- As discussed in
https://github.com/bevyengine/bevy/issues/17276#issuecomment-2611203714,
we should transform the cursor's hotspot if the user is asking for the
image to be flipped.
- This becomes more important when a `scale` transform option exists.
It's harder for users to transform the hotspot themselves when using
`scale` because they'd need to look up the image to get its dimensions.
Instead, we let Bevy handle the hotspot transforms and make the
`hotspot` field the "original/source" hotspot.
- Refs #17276.

## Solution

- When the image needs to be transformed, also transform the hotspot. If
the image does not need to be transformed (i.e. fast path), no hotspot
transformation is applied.

## Testing

- Ran the example: `cargo run --example custom_cursor_image
--features=custom_cursor`.
- Add unit tests for the hotspot transform function.
- I also ran the example I have in my `bevy_cursor_kit` crate, which I
think is a good illustration of the reason for this PR.
- In the following videos, there is an arrow pointing up. The button
hover event fires as I move the mouse over it.
- When I press `Y`, the cursor flips. 
- In the first video, on `bevy@main` **before** this PR, notice how the
hotspot is wrong after flipping and no longer hovering the button. The
arrow head and hotspot are no longer synced.
- In the second video, on the branch of **this** PR, notice how the
hotspot gets flipped as soon as I press `Y` and the cursor arrow head is
in the correct position on the screen and still hovering the button.
Speaking back to the objective listed at the start: The user originally
defined the _source_ hotspot for the arrow. Later, they decide they want
to flip the cursor vertically: It's nice that Bevy can automatically
flip the _source_ hotspot for them at the same time it flips the
_source_ image.

First video (main):


https://github.com/user-attachments/assets/1955048c-2f85-4951-bfd6-f0e7cfef0cf8

Second video (this PR):


https://github.com/user-attachments/assets/73cb9095-ecb5-4bfd-af5b-9f772e92bd16
2025-01-28 05:49:46 +00:00
Luc
51bb4f08a9
expose OverflowAxis::Hidden as Overflow functions (#17528)
# Objective
expose `OverflowAxis::Hidden` as functions of `Overflow`, just as it is
done for `OverflowAxis::Hidden` and `OverflowAxis::Scroll`.
2025-01-28 05:34:50 +00:00
Lucas Franca
644efd6b03
Fix calculation of skybox rotation (#17476)
# Objective

Fixes #16628 

## Solution

Matrices were being applied in the wrong order.

## Testing

Ran `skybox` example with rotations applied to the `Skybox` on the `x`,
`y`, and `z` axis (one at a time).

e.g.
```rust
Skybox {
    image: skybox_handle.clone(),
    brightness: 1000.0,
    rotation: Quat::from_rotation_y(-45.0_f32.to_radians()),
}
```

## Showcase


[Screencast_20250121_151232.webm](https://github.com/user-attachments/assets/3df68714-f5f1-4d8c-8e08-cbab525a8bda)
2025-01-28 05:27:22 +00:00
berry
95174f3c6e
Fix docs mistake in bevy_ecs::world (#17336)
# Objective

- Correct a mistake in the rustdoc for bevy_ecs::world::World.

## Solution

- The rustdoc wrongly stated that "Each component can have up to one
instance of each component type.". This sentence should presumably be
"Each *Entity* can have up to one instance of each component type.".
Applying this change makes the prior sentence "Each [`Entity`] has a set
of components." redundant.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-01-28 05:20:31 +00:00
Sludge
581034a7e9
Reflect and register the wireframe materials (#17334)
# Objective

These were missing, but can trivially be reflected.

## Solution

Do that.
2025-01-28 05:19:34 +00:00
Brendon
99b0d574f9
Update render_resource gpu buffer doc comments (#17118)
Minor improvement to the render_resource doc comments; specifically, the
gpu buffer types
- makes them consistently reference each other
- reorders them to be alphabetical
- removes duplicated entries
2025-01-28 05:13:04 +00:00
poopy
15f00278e7
Rename ArgList::push methods to with and add new push methods which take &mut self (#16567)
# Objective

The `ArgList::push` family of methods consume `self` and return a new
`ArgList` which means they can't be used with `&mut ArgList` references.

```rust
fn foo(args: &mut ArgList) {
    args.push_owned(47_i32); // doesn't work :(
}
```

It's typical for `push` methods on other existing types to take `&mut
self`.

## Solution

Renamed the existing push methods to `with_arg`, `with_ref` etc and
added new `push` methods which take `&mut self`.

## Migration Guide

Uses of the `ArgList::push` methods should be replaced with the `with`
counterpart.

<details>

| old | new |
| --- | --- |
| push_arg | with_arg |
| push_ref | with_ref |
| push_mut | with_mut |
| push_owned | with_owned | 
| push_boxed | with_boxed |

</details>
2025-01-28 05:06:50 +00:00
Chris Russell
514a35c656
Share implementation of sort methods. (#16203)
# Objective

The various `Query::sort()` methods have a lot of duplicated code
between them, including some unsafe code. Reduce the duplication to make
the code easier to read and maintain.

## Solution

Extract the duplicated code to a private method, and pass in the sorting
strategy as a closure.

## Testing

I used `cargo-show-asm` to verify that the closures were inlined, but I
didn't run anything through a profiler. The `sort()` method itself even
had identical assembly before and after this change, although the others
did not.
2025-01-28 04:57:54 +00:00
ickshonpe
c0ccc87738
UI material border radius (#15171)
# Objective

I wrote a box shadow UI material naively thinking I could use the border
widths attribute to hold the border radius but it
doesn't work as the border widths are automatically set in the
extraction function. Need to send border radius to the shader seperately
for it to be viable.

## Solution

Add a `border_radius` vertex attribute to the ui material.

This PR also removes the normalization of border widths for custom UI
materials. The regular UI shader doesn't do this so it's a bit confusing
and means you can't use the logic from `ui.wgsl` in your custom UI
materials.

## Testing / Showcase

Made a change to the `ui_material` example to display border radius:

```cargo run --example ui_material```

<img width="569" alt="corners" src="https://github.com/user-attachments/assets/36412736-a9ee-4042-aadd-68b9cafb17cb" />
2025-01-28 04:54:48 +00:00
Patrick Walton
7aeb1c51a6
Disable clustered decals on Metal. (#17554)
Unfortunately, Apple platforms don't have enough texture bindings to
properly support clustered decals. This should be fixed once `wgpu` has
first-class bindless texture support. In the meantime, we disable them.

Closes #17553.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-27 05:39:07 +00:00
Patrick Walton
dda97880c4
Implement experimental GPU two-phase occlusion culling for the standard 3D mesh pipeline. (#17413)
*Occlusion culling* allows the GPU to skip the vertex and fragment
shading overhead for objects that can be quickly proved to be invisible
because they're behind other geometry. A depth prepass already
eliminates most fragment shading overhead for occluded objects, but the
vertex shading overhead, as well as the cost of testing and rejecting
fragments against the Z-buffer, is presently unavoidable for standard
meshes. We currently perform occlusion culling only for meshlets. But
other meshes, such as skinned meshes, can benefit from occlusion culling
too in order to avoid the transform and skinning overhead for unseen
meshes.

This commit adapts the same [*two-phase occlusion culling*] technique
that meshlets use to Bevy's standard 3D mesh pipeline when the new
`OcclusionCulling` component, as well as the `DepthPrepass` component,
are present on the camera. It has these steps:

1. *Early depth prepass*: We use the hierarchical Z-buffer from the
previous frame to cull meshes for the initial depth prepass, effectively
rendering only the meshes that were visible in the last frame.

2. *Early depth downsample*: We downsample the depth buffer to create
another hierarchical Z-buffer, this time with the current view
transform.

3. *Late depth prepass*: We use the new hierarchical Z-buffer to test
all meshes that weren't rendered in the early depth prepass. Any meshes
that pass this check are rendered.

4. *Late depth downsample*: Again, we downsample the depth buffer to
create a hierarchical Z-buffer in preparation for the early depth
prepass of the next frame. This step is done after all the rendering, in
order to account for custom phase items that might write to the depth
buffer.

Note that this patch has no effect on the per-mesh CPU overhead for
occluded objects, which remains high for a GPU-driven renderer due to
the lack of `cold-specialization` and retained bins. If
`cold-specialization` and retained bins weren't on the horizon, then a
more traditional approach like potentially visible sets (PVS) or low-res
CPU rendering would probably be more efficient than the GPU-driven
approach that this patch implements for most scenes. However, at this
point the amount of effort required to implement a PVS baking tool or a
low-res CPU renderer would probably be greater than landing
`cold-specialization` and retained bins, and the GPU driven approach is
the more modern one anyway. It does mean that the performance
improvements from occlusion culling as implemented in this patch *today*
are likely to be limited, because of the high CPU overhead for occluded
meshes.

Note also that this patch currently doesn't implement occlusion culling
for 2D objects or shadow maps. Those can be addressed in a follow-up.
Additionally, note that the techniques in this patch require compute
shaders, which excludes support for WebGL 2.

This PR is marked experimental because of known precision issues with
the downsampling approach when applied to non-power-of-two framebuffer
sizes (i.e. most of them). These precision issues can, in rare cases,
cause objects to be judged occluded that in fact are not. (I've never
seen this in practice, but I know it's possible; it tends to be likelier
to happen with small meshes.) As a follow-up to this patch, we desire to
switch to the [SPD-based hi-Z buffer shader from the Granite engine],
which doesn't suffer from these problems, at which point we should be
able to graduate this feature from experimental status. I opted not to
include that rewrite in this patch for two reasons: (1) @JMS55 is
planning on doing the rewrite to coincide with the new availability of
image atomic operations in Naga; (2) to reduce the scope of this patch.

A new example, `occlusion_culling`, has been added. It demonstrates
objects becoming quickly occluded and disoccluded by dynamic geometry
and shows the number of objects that are actually being rendered. Also,
a new `--occlusion-culling` switch has been added to `scene_viewer`, in
order to make it easy to test this patch with large scenes like Bistro.

[*two-phase occlusion culling*]:
https://medium.com/@mil_kru/two-pass-occlusion-culling-4100edcad501

[Aaltonen SIGGRAPH 2015]:

https://www.advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf

[Some literature]:

https://gist.github.com/reduz/c5769d0e705d8ab7ac187d63be0099b5?permalink_comment_id=5040452#gistcomment-5040452

[SPD-based hi-Z buffer shader from the Granite engine]:
https://github.com/Themaister/Granite/blob/master/assets/shaders/post/hiz.comp

## Migration guide

* When enqueuing a custom mesh pipeline, work item buffers are now
created with
`bevy::render::batching::gpu_preprocessing::get_or_create_work_item_buffer`,
not `PreprocessWorkItemBuffers::new`. See the
`specialized_mesh_pipeline` example.

## Showcase

Occlusion culling example:
![Screenshot 2025-01-15
175051](https://github.com/user-attachments/assets/1544f301-68a3-45f8-84a6-7af3ad431258)

Bistro zoomed out, before occlusion culling:
![Screenshot 2025-01-16
185425](https://github.com/user-attachments/assets/5114bbdf-5dec-4de9-b17e-7aa77e7b61ed)

Bistro zoomed out, after occlusion culling:
![Screenshot 2025-01-16
184949](https://github.com/user-attachments/assets/9dd67713-656c-4276-9768-6d261ca94300)

In this scene, occlusion culling reduces the number of meshes Bevy has
to render from 1591 to 585.
2025-01-27 05:02:46 +00:00
Patrick Walton
8620cd783c
Make the default directional light shadow cascade settings similar to those of other engines. (#17552)
Currently, our default maximum shadow cascade distance is 1000 m, which
is quite distant compared to that of Unity (150 m), Unreal Engine 5 (200
m), and Godot (100 m). I also adjusted the default first cascade far
bound to be 10 m, which matches that of Unity (10.05 m) and Godot (10
m). Together, these changes should improve the default sharpness of
shadows of directional lights for typical scenes.

## Migration Guide

* The default shadow cascade far distance has been changed from 1000 to
150, and the default first cascade far bound has been changed from 5 to
10, in order to be similar to the defaults of other engines.
2025-01-27 01:48:57 +00:00
Tim Overbeek
eb04f8a476
Simplify derive_from_world (#17534)
# Objective

simplify existing implementation

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2025-01-26 22:25:29 +00:00
AustinHellerRepo
1612d210fb
added Hash to MouseScrollUnit; (#17538)
# Objective

This allows for the usage of the MouseScrollUnit as a key to a HashSet
and HashMap. I have a need for this, but this basic functionality is
currently missing.

## Solution

Add the derive Hash attribute to the MouseScrollUnit type.

## Testing

- Did you test these changes? If so, how?
No, but I did perform a `cargo build`. My laptop is failing to run
`cargo test` without crashing.
- Are there any parts that need more testing?
If someone could run a `cargo test` for completeness, that would be
great but this is a trivial change.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
They simply need to ensure that the common Hash derive macro works as
expected for the basic MouseScrollUnit type.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Ubuntu 22.04
2025-01-26 22:24:50 +00:00
Jerome Humbert
499510489e
impl Eq + Hash for BindGroup/Layout (#17547)
# Objective

Implement `Eq` and `Hash` for the `BindGroup` and `BindGroupLayout`
wrappers.

## Solution

Implement based on the same assumption that the ID is unique, for
consistency with `PartialEq`.

## Testing

None; this should be straightforward. If there's an issue that would be
a design one.
2025-01-26 22:23:09 +00:00
Patrick Walton
1c765c9ae7
Add support for specular tints and maps per the KHR_materials_specular glTF extension. (#14069)
This commit allows specular highlights to be tinted with a color and for
the reflectance and color tint values to vary across a model via a pair
of maps. The implementation follows the [`KHR_materials_specular`] glTF
extension. In order to reduce the number of samplers and textures in the
default `StandardMaterial` configuration, the maps are gated behind the
`pbr_specular_textures` Cargo feature.

Specular tinting is currently unsupported in the deferred renderer,
because I didn't want to bloat the deferred G-buffers. A possible fix
for this in the future would be to make the G-buffer layout more
configurable, so that specular tints could be supported on an opt-in
basis. As an alternative, Bevy could force meshes with specular tints to
render in forward mode. Both of these solutions require some more
design, so I consider them out of scope for now.

Note that the map is a *specular* map, not a *reflectance* map. In Bevy
and Filament terms, the reflectance values in the specular map range
from [0.0, 0.5], rather than [0.0, 1.0]. This is an unfortunate
[`KHR_materials_specular`] specification requirement that stems from the
fact that glTF is specified in terms of a specular strength model, not
the reflectance model that Filament and Bevy use. A workaround, which is
noted in the `StandardMaterial` documentation, is to set the
`reflectance` value to 2.0, which spreads the specular map range from
[0.0, 1.0] as normal.

The glTF loader has been updated to parse the [`KHR_materials_specular`]
extension. Note that, unless the non-default `pbr_specular_textures` is
supplied, the maps are ignored. The `specularFactor` value is applied as
usual. Note that, as with the specular map, the glTF `specularFactor` is
twice Bevy's `reflectance` value.

This PR adds a new example, `specular_tint`, which demonstrates the
specular tint and map features. Note that this example requires the
[`KHR_materials_specular`] Cargo feature.

[`KHR_materials_specular`]:
https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular

## Changelog

### Added

* Specular highlights can now be tinted with the `specular_tint` field
in `StandardMaterial`.
* Specular maps are now available in `StandardMaterial`, gated behind
the `pbr_specular_textures` Cargo feature.
* The `KHR_materials_specular` glTF extension is now supported, allowing
for customization of specular reflectance and specular maps. Note that
the latter are gated behind the `pbr_specular_textures` Cargo feature.
2025-01-26 20:38:46 +00:00
Patrick Walton
fc831c390d
Implement basic clustered decal projectors. (#17315)
This commit adds support for *decal projectors* to Bevy, allowing for
textures to be projected on top of geometry. Decal projectors are
clusterable objects, just as punctual lights and light probes are. This
means that decals are only evaluated for objects within the conservative
bounds of the projector, and they don't require a second pass.

These clustered decals require support for bindless textures and as such
currently don't work on WebGL 2, WebGPU, macOS, or iOS. For an
alternative that doesn't require bindless, see PR #16600. I believe that
both contact projective decals in #16600 and clustered decals are
desirable to have in Bevy. Contact projective decals offer broader
hardware and driver support, while clustered decals don't require the
creation of bounding geometry.

A new example, `decal_projectors`, has been added, which demonstrates
multiple decals on a rotating object. The decal projectors can be scaled
and rotated with the mouse.

There are several limitations of this initial patch that can be
addressed in follow-ups:

1. There's no way to specify the Z-index of decals. That is, the order
in which multiple decals are blended on top of one another is arbitrary.
A follow-up could introduce some sort of Z-index field so that artists
can specify that some decals should be blended on top of others.

2. Decals don't take the normal of the surface they're projected onto
into account. Most decal implementations in other engines have a feature
whereby the angle between the decal projector and the normal of the
surface must be within some threshold for the decal to appear. Often,
artists can specify a fade-off range for a smooth transition between
oblique surfaces and aligned surfaces.

3. There's no distance-based fadeoff toward the end of the projector
range. Many decal implementations have this.

This addresses #2401.
 
## Showcase

![Screenshot 2025-01-11
052913](https://github.com/user-attachments/assets/8fabbafc-60fb-461d-b715-d7977e10fe1f)
2025-01-26 20:13:39 +00:00
Predko Silvestr
deb135c25c
Proportional scaling for the sprite's texture. (#17258)
# Objective

Bevy sprite image mode lacks proportional scaling for the underlying
texture. In many cases, it's required. For example, if it is desired to
support a wide variety of screens with a single texture, it's okay to
cut off some portion of the original texture.

## Solution

I added scaling of the texture during the preparation step. To fill the
sprite with the original texture, I scaled UV coordinates accordingly to
the sprite size aspect ratio and texture size aspect ratio. To fit
texture in a sprite the original `quad` is scaled and then the
additional translation is applied to place the scaled quad properly.


## Testing

For testing purposes could be used `2d/sprite_scale.rs`. Also, I am
thinking that it would be nice to have some tests for a
`crates/bevy_sprite/src/render/mod.rs:sprite_scale`.

---

## Showcase

<img width="1392" alt="image"
src="https://github.com/user-attachments/assets/c2c37b96-2493-4717-825f-7810d921b4bc"
/>
2025-01-24 18:24:02 +00:00
Vic
39a1e2b488
implement EntityIndexMap/Set (#17449)
# Objective

We do not have `EntityIndexMap`/`EntityIndexSet`.

Usual `HashMap`s/`HashSet`s do not guarantee any order, which can be
awkward for some use cases.
The `indexmap` versions remember insertion order, which then also
becomes their iteration order.
They can be thought of as a `HashTable` + `Vec`, which means fast
iteration and removal, indexing by index (not just key), and slicing!
Performance should otherwise be comparable.

## Solution

Because `indexmap` is structured to mirror `hashbrown`, it suffers the
same issue of not having the `Hasher` generic on their iterators. #16912
solved this issue for `EntityHashMap`/`EntityHashSet` with a wrapper
around the hashbrown version, so this PR does the same.

Hopefully these wrappers can be removed again in the future by having
`hashbrown`/`indexmap` adopt that generic in their iterators themselves!
2025-01-24 08:09:34 +00:00
spvky
40007cdb2e
Adds update interval config for FpsOverlayPlugin (#17489)
# Objective
Fixes #17487 

- Adds a new field `refresh_interval` to `FpsOverlayConfig` to allow the
user setting a minimum time before each refresh of the FPS display

## Solution

- Add `refresh_interval` to `FpsOverlayConfig`
- When updating the on screen text, check a duration of
`refresh_interval` has passed, if not, don't update the FPS counter

## Testing

- Created a new bevy project
- Included the `FpsOverlayPlugin` with the default `refresh_interval`
(100 ms)
- Included the `FpsOverlayPlugin` with an obnoxious `refresh_interval`
(2 seconds)
---

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-24 05:57:36 +00:00
Richard Jones
e20ac69cb3
Clarify docs for OnAdd, OnInsert, OnReplace, OnRemove triggers (#17512)
# Objective

- Trouble remembering the difference between `OnAdd` and `OnInsert` for
triggers. Would like a better doc for those triggers so it appears in my
editor tooltip.

## Solution

- Clarify docs for OnAdd, OnInsert, OnRemove, OnReplace. Based on
comments in the
[component_hook.rs](https://github.com/bevyengine/bevy/blob/main/examples/ecs/component_hooks.rs#L73)
example.


## Testing

- None, small doc fix.
2025-01-24 05:40:58 +00:00
Vic
94a238b0ef
implement FromEntitySetIterator (#17513)
# Objective

Some collections are more efficient to construct when we know that every
element is unique in advance.
We have `EntitySetIterator`s from #16547, but currently no API to safely
make use of them this way.

## Solution

Add `FromEntitySetIterator` as a subtrait to `FromIterator`, and
implement it for the `EntityHashSet`/`hashbrown::HashSet` types.
To match the normal `FromIterator`, we also add a
`EntitySetIterator::collect_set` method.
It'd be better if these methods could shadow `from_iter` and `collect`
completely, but https://github.com/rust-lang/rust/issues/89151 is needed
for that.

While currently only `HashSet`s implement this trait, future
`UniqueEntityVec`/`UniqueEntitySlice` functionality comes with more
implementors.

Because `HashMap`s are collected from tuples instead of singular types,
implementing this same optimization for them is more complex, and has to
be done separately.

## Showcase

This is basically a free speedup for collecting `EntityHashSet`s!

```rust
pub fn collect_milk_dippers(dippers: Query<Entity, (With<Milk>, With<Cookies>)>) {
    dippers.iter().collect_set::<EntityHashSet>();
    // or
    EntityHashSet::from_entity_set_iter(dippers);
}

---------

Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
2025-01-24 05:39:35 +00:00
mgi388
14ad25227b
Make CustomCursor variants CustomCursorImage/CustomCursorUrl structs (#17518)
# Objective

- Make `CustomCursor::Image` easier to work with by splitting the enum
variants off into `CustomCursorImage` and `CustomCursorUrl` structs and
deriving `Default` on those structs.
- Refs #17276.

## Testing

- Ran two examples: `cargo run --example custom_cursor_image
--features=custom_cursor` and `cargo run --example window_settings
--features=custom_cursor`
- CI.

---

## Migration Guide

The `CustomCursor` enum's variants now hold instances of
`CustomCursorImage` or `CustomCursorUrl`. Update your uses of
`CustomCursor` accordingly.
2025-01-24 05:39:04 +00:00
ickshonpe
e459dd94ec
Replace checks for empty uinodes (#17520)
# Objective

The `is_empty` checks that are meant to stop zero-sized uinodes from
being extracted are missing from `extract_uinode_background_colors`,
`extract_uinode_images` and `extract_ui_material_nodes`.

## Solution

Put them back.
2025-01-24 05:38:20 +00:00
Emerson Coskey
81a25bb0c7
Procedural atmospheric scattering (#16314)
Implement procedural atmospheric scattering from [Sebastien Hillaire's
2020 paper](https://sebh.github.io/publications/egsr2020.pdf). This
approach should scale well even down to mobile hardware, and is
physically accurate.

## Co-author: @mate-h 

He helped massively with getting this over the finish line, ensuring
everything was physically correct, correcting several places where I had
misunderstood or misapplied the paper, and improving the performance in
several places as well. Thanks!

## Credits

@aevyrie: helped find numerous bugs and improve the example to best show
off this feature :)

Built off of @mtsr's original branch, which handled the transmittance
lut (arguably the most important part)

## Showcase: 


![sunset](https://github.com/user-attachments/assets/2eee1f38-f66d-4772-bb72-163e13c719d8)

![twilight](https://github.com/user-attachments/assets/f7d358b6-898d-4df7-becc-188cd753102d)


## For followup

- Integrate with pcwalton's volumetrics code
- refactor/reorganize for better integration with other effects
- have atmosphere transmittance affect directional lights
- add support for generating skybox/environment map

---------

Co-authored-by: Emerson Coskey <56370779+EmersonCoskey@users.noreply.github.com>
Co-authored-by: atlv <email@atlasdostal.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Emerson Coskey <coskey@emerlabs.net>
Co-authored-by: Máté Homolya <mate.homolya@gmail.com>
2025-01-23 22:52:46 +00:00
Zachary Harrold
d9ba1af87c
Fix Typo in bevy_platform_support's spin Feature (#17516)
# Objective

- Fix typo in `spin/portable-atomic` feature.

## Solution

- Replace with `spin/portable_atomic`

## Testing

- CI

---

## Notes

This is a very annoying design choice the `spin` developers made.
Because the _crate_ is called `portable-atomic` and is optional, Cargo
automatically registers the feature `portable-atomic`. But the
maintainers use `portable_atomic` for their _feature_ which enables the
support. Sneaks through CI because it's a valid feature and will only
cause breakage on atomically challenged platforms (which we currently
aren't testing in CI).

Should we test atomically challenged in CI? Right now I don't think so,
at least not until we've made "normal" `no_std` CI better with the main
`bevy` crate as the test-case rather than each individual crate.
2025-01-23 21:47:21 +00:00
Zachary Harrold
9bc0ae33c3
Move hashbrown and foldhash out of bevy_utils (#17460)
# Objective

- Contributes to #16877

## Solution

- Moved `hashbrown`, `foldhash`, and related types out of `bevy_utils`
and into `bevy_platform_support`
- Refactored the above to match the layout of these types in `std`.
- Updated crates as required.

## Testing

- CI

---

## Migration Guide

- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::hash`:
  - `FixedState`
  - `DefaultHasher`
  - `RandomState`
  - `FixedHasher`
  - `Hashed`
  - `PassHash`
  - `PassHasher`
  - `NoOpHash`
- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::collections`:
  - `HashMap`
  - `HashSet`
- `bevy_utils::hashbrown` has been removed. Instead, import from
`bevy_platform_support::collections` _or_ take a dependency on
`hashbrown` directly.
- `bevy_utils::Entry` has been removed. Instead, import from
`bevy_platform_support::collections::hash_map` or
`bevy_platform_support::collections::hash_set` as appropriate.
- All of the above equally apply to `bevy::utils` and
`bevy::platform_support`.

## Notes

- I left `PreHashMap`, `PreHashMapExt`, and `TypeIdMap` in `bevy_utils`
as they might be candidates for micro-crating. They can always be moved
into `bevy_platform_support` at a later date if desired.
2025-01-23 16:46:08 +00:00
Zachary Harrold
04990fcd27
Move spin to bevy_platform_support out of other crates (#17470)
# Objective

- Contributes to #16877

## Solution

- Expanded `bevy_platform_support::sync` module to provide
API-compatible replacements for `std` items such as `RwLock`, `Mutex`,
and `OnceLock`.
- Removed `spin` from all crates except `bevy_platform_support`.

## Testing

- CI

---

## Notes

- The sync primitives, while verbose, entirely rely on `spin` for their
implementation requiring no `unsafe` and not changing the status-quo on
_how_ locks actually work within Bevy. This is just a refactoring to
consolidate the "hacks" and workarounds required to get a consistent
experience when either using `std::sync` or `spin`.
- I have opted to rely on `std::sync` for `std` compatible locks,
maintaining the status quo. However, now that we have these locks
factored out into the own module, it would be trivial to investigate
alternate locking backends, such as `parking_lot`.
- API for these locking types is entirely based on `std`. I have
implemented methods and types which aren't currently in use within Bevy
(e.g., `LazyLock` and `Once`) for the sake of completeness. As the
standard library is highly stable, I don't expect the Bevy and `std`
implementations to drift apart much if at all.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-23 05:27:02 +00:00
ickshonpe
dd2d84b342
Remove ViewVisibility from UI nodes (#17405)
# Objective

The UI can only target a single view and doesn't support `RenderLayers`,
so there doesn't seem to be any need for UI nodes to require
`ViewVisibility` and `VisibilityClass`.

Fixes #17400

## Solution

Remove the `ViewVisibility` and `VisibilityClass` component requires
from `Node` and change the visibility queries to only query for
`InheritedVisibility`.

## Testing

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

Yellow is this PR, red is main.

`bevy_render::view::visibility::reset_view_visibility`
<img width="531" alt="reset-view" src="https://github.com/user-attachments/assets/a44b215d-96bf-43ec-8669-31530ff98eae" />

`bevy_render::view::visibility::check_visibility`
<img width="445" alt="view_visibility" src="https://github.com/user-attachments/assets/fa111757-da91-434d-88e4-80bdfa29374f" />
2025-01-23 05:26:10 +00:00
Sven Niederberger
68c19defb6
Readback: Add support for texture depth/array layers (#17479)
# Objective

Fixes #16963

## Solution

I am - no pun intended - somewhat out of my depth here but this worked
in my testing. The validation error is gone and the data read from the
GPU looks sensible. I'd greatly appreciate if somebody more familiar
with the matter could double-check this.

## References

Relevant documentation in
[WebGPU](https://gpuweb.github.io/gpuweb/#gputexelcopybufferlayout) and
[wgpu](https://github.com/gfx-rs/wgpu/blob/v23/wgpu-types/src/lib.rs#L6350).

## Testing

<details><summary>Example code for testing</summary>
<p>

```rust
use bevy::{
    image::{self as bevy_image, TextureFormatPixelInfo},
    prelude::*,
    render::{
        render_asset::RenderAssetUsages,
        render_resource::{
            Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
        },
    },
};

fn main() {
    let mut app = App::new();
    app.add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, readback_system);
    app.run();
}

#[derive(Resource)]
struct ImageResource(Handle<Image>);

const TEXTURE_HEIGHT: u32 = 64;
const TEXTURE_WIDTH: u32 = 32;
const TEXTURE_LAYERS: u32 = 4;
const FORMAT: TextureFormat = TextureFormat::Rgba8Uint;

fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
    let layer_pixel_count = (TEXTURE_WIDTH * TEXTURE_HEIGHT) as usize;
    let layer_size = layer_pixel_count * FORMAT.pixel_size();
    let data: Vec<u8> = (0..TEXTURE_LAYERS as u8)
        .flat_map(|layer| (0..layer_size).map(move |_| layer))
        .collect();
    let image_size = data.len();
    println!("{image_size}");
    let image = Image {
        data,
        texture_descriptor: TextureDescriptor {
            label: Some("image"),
            size: Extent3d {
                width: TEXTURE_WIDTH,
                height: TEXTURE_HEIGHT,
                depth_or_array_layers: TEXTURE_LAYERS,
            },
            mip_level_count: 1,
            sample_count: 1,
            dimension: TextureDimension::D2,
            format: FORMAT,
            usage: TextureUsages::COPY_DST | TextureUsages::COPY_SRC,
            view_formats: &[],
        },
        sampler: bevy_image::ImageSampler::Default,
        texture_view_descriptor: None,
        asset_usage: RenderAssetUsages::RENDER_WORLD,
    };

    commands.insert_resource(ImageResource(images.add(image)));
}

fn readback_system(
    mut commands: Commands,
    keys: Res<ButtonInput<KeyCode>>,
    image: Res<ImageResource>,
) {
    if !keys.just_pressed(KeyCode::KeyR) {
        return;
    }

    commands
        .spawn(bevy::render::gpu_readback::Readback::Texture(
            image.0.clone(),
        ))
        .observe(
            |trigger: Trigger<bevy::render::gpu_readback::ReadbackComplete>,
             mut commands: Commands| {
                info!("readback complete");

                println!("{:#?}", &trigger.0);

                commands.entity(trigger.observer()).despawn();
            },
        );
}

```

</p>
</details>
2025-01-23 05:25:40 +00:00
Patrick Walton
56aa90240e
Only include distance fog in the PBR shader if the view uses it. (#17495)
Right now, we always include distance fog in the shader, which is
unfortunate as it's complex code and is rare. This commit changes it to
be a `#define` instead. I haven't confirmed that removing distance fog
meaningfully reduces VGPR usage, but it can't hurt.
2025-01-23 05:24:54 +00:00
Rob Parrett
17294eebb2
Update async-broadcast (#17500)
# Objective

Dependabot tried up update this earlier, but it was noticed that this
broke wasm builds. A new release has happened since then which includes
a fix for that.

Here's the
[changelog](https://github.com/smol-rs/async-broadcast/blob/master/CHANGELOG.md).

Closes #11830

## Solution

Use `async-broadcast` `0.7.2`.

## Testing

I ran a few some examples involving assets on macos / wasm.
2025-01-23 05:24:34 +00:00
Zachary Harrold
8e6bf0637b
Add no_std support to bevy_diagnostic (#17507)
# Objective

- Contributes to #15460

## Solution

- Added required features
- Switched from `tracing` to `log`
- Fixed imports

## Testing

- CI
2025-01-23 05:20:34 +00:00
Tim Overbeek
da57dfb62f
DeriveWorld for enums (#17496)
# Objective

Fixes #17457 

## Solution

#[derive(FromWorld)] now works with enums by specifying which variant
should be used.

## Showcase

```rust
#[Derive(FromWorld)]
enum Game {
    #[from_world]
    Playing, 
    Stopped
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-23 04:06:00 +00:00
Thierry Berger
fd2afeefda
Mesh::merge to return a Result (#17475)
# Objective

Make `Mesh::merge` more resilient to use.

Currently, it's difficult to make sure `Mesh::merge` will not panic
(we'd have to check if all attributes are compatible).

- I'd appreciate it for utility function to convert different mesh
representations such as:
https://github.com/dimforge/bevy_rapier/pull/628.

## Solution

- Make `Mesh::merge` return a `Result`.

## Testing

- It builds

## Migration Guide

- `Mesh::merge` now returns a `Result<(), MeshMergeError>`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Greeble <166992735+greeble-dev@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-23 04:05:36 +00:00
Zachary Harrold
9387fcfbf2
Add no_std Support to bevy_a11y (#17505)
# Objective

- Contributes to #15460

## Solution

- Add `std` feature gate
- Fixed partially used serialisation and reflection features.

## Testing

- CI
2025-01-23 03:52:47 +00:00
ickshonpe
434bbe6027
flex_basis doc comment fix (#17502)
# Objective

The doc comment for `Node::flex_basis` which refers to a`size` field
that was replaced by individual `width` and `height` fields sometime
ago.

## Solution

Refer to the individual fields instead.
2025-01-23 02:48:01 +00:00
Zachary Harrold
41e79ae826
Refactored ComponentHook Parameters into HookContext (#17503)
# Objective

- Make the function signature for `ComponentHook` less verbose

## Solution

- Refactored `Entity`, `ComponentId`, and `Option<&Location>` into a new
`HookContext` struct.

## Testing

- CI

---

## Migration Guide

Update the function signatures for your component hooks to only take 2
arguments, `world` and `context`. Note that because `HookContext` is
plain data with all members public, you can use de-structuring to
simplify migration.

```rust
// Before
fn my_hook(
    mut world: DeferredWorld,
    entity: Entity,
    component_id: ComponentId,
) { ... }

// After
fn my_hook(
    mut world: DeferredWorld,
    HookContext { entity, component_id, caller }: HookContext,
) { ... }
``` 

Likewise, if you were discarding certain parameters, you can use `..` in
the de-structuring:

```rust
// Before
fn my_hook(
    mut world: DeferredWorld,
    entity: Entity,
    _: ComponentId,
) { ... }

// After
fn my_hook(
    mut world: DeferredWorld,
    HookContext { entity, .. }: HookContext,
) { ... }
```
2025-01-23 02:45:24 +00:00
Zachary Harrold
c7ddec571d
Fix Time (#17504)
# Objective

- Fix issue @mockersf identified with `example-showcase` where time was
not being received correctly from the render world.

## Solution

- Refactored to ensure `TimeReceiver` is always cleared even if it isn't
being used in the main world.

## Testing

- `cargo run -p example-showcase -- --page 1 --per-page 1 run
--screenshot-frame 200 --fixed-frame-time 0.0125 --stop-frame 450
--in-ci --show-logs`
2025-01-23 02:44:16 +00:00
Rob Parrett
784a9d36bd
Add warning for font sizes <= 0.0 (#17501)
# Objective

Alternative to #9660, which is outdated since "required components"
landed.

Fixes #9655

## Solution

This is a different approach than the linked PR, slotting the warning
into an existing check for zero or negative font sizes in the text
pipeline.

## Testing

Replaced a font size with `0.0` in `examples/ui/text.rs`.

```
2025-01-22T23:26:08.239688Z  INFO bevy_winit::system: Creating new window App (0v1)
2025-01-22T23:26:08.617505Z  WARN bevy_text::pipeline: Text span 10v1 has a font size <= 0.0. Nothing will be displayed.
```
2025-01-23 02:43:59 +00:00
Zachary Harrold
d921fdc376
Add no_std Support to bevy_time (#17491)
# Objective

- Contributes to #15460

## Solution

- Switched `tracing` for `log` for the atomically challenged platforms
- Setup feature flags as required
- Added to `compile-check-no-std` CI task
- Made `crossbeam-channel` optional depending on `std`.

## Testing

- CI

---

## Notes

- `crossbeam-channel` provides a MPMC channel type which isn't readily
replicable in `no_std`, and is only used for a `bevy_render`
integration. As such, I've feature-gated the `TimeReceiver` and
`TimeSender` types.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-22 20:02:43 +00:00
SpecificProtagonist
f32a6fb205
Track callsite for observers & hooks (#15607)
# Objective

Fixes #14708

Also fixes some commands not updating tracked location.


## Solution

`ObserverTrigger` has a new `caller` field with the
`track_change_detection` feature;
hooks take an additional caller parameter (which is `Some(…)` or `None`
depending on the feature).

## Testing

See the new tests in `src/observer/mod.rs`

---

## Showcase

Observers now know from where they were triggered (if
`track_change_detection` is enabled):
```rust
world.observe(move |trigger: Trigger<OnAdd, Foo>| {
    println!("Added Foo from {}", trigger.caller());
});
```

## Migration

- hooks now take an additional `Option<&'static Location>` argument

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-22 20:02:39 +00:00
Zachary Harrold
5c43890d49
no_std Support for bevy_input_focus (#17490)
# Objective

- Contributes to #15460

## Solution

- Switched `tracing` for `log` for the atomically challenged platforms
- Setup feature flags as required
- Added to `compile-check-no-std` CI task

## Testing

- CI

---

## Notes

- _Very_ easy one this time. Most of the changes here are just feature
definitions and documentation within the `Cargo.toml`
2025-01-22 19:16:04 +00:00
Alexander Krivács Schrøder
d56536a672
Add reflection to the remaining glam Vec types (#17493)
# Objective

Add reflection support to more `glam` `Vec` types, specifically

* I8Vec2
* I8Vec3
* I8Vec4
* U8Vec2
* U8Vec3
* U8Vec4
* I16Vec2
* I16Vec3
* I16Vec4
* U16Vec2
* U16Vec3
* U16Vec4

I needed to do this because I'm using various of these in my Bevy types,
and due to the orphan rules, I can't make these impls locally.

## Solution

Used `impl_reflect!` like for the existing types.

## Testing

This should not require additional testing, though I have verified that
reflection now works for these types in my own project.
2025-01-22 18:48:34 +00:00
Patrick Walton
72ddac140a
Retain RenderMaterialInstances and RenderMeshMaterialIds from frame to frame. (#16985)
This commit makes Bevy use change detection to only update
`RenderMaterialInstances` and `RenderMeshMaterialIds` when meshes have
been added, changed, or removed. `extract_mesh_materials`, the system
that extracts these, now follows the pattern that
`extract_meshes_for_gpu_building` established.

This improves frame time of `many_cubes` from 3.9ms to approximately
3.1ms, which slightly surpasses the performance of Bevy 0.14.

(Resubmitted from #16878 to clean up history.)

![Screenshot 2024-12-17
182109](https://github.com/user-attachments/assets/dfb26e20-b314-4c67-a59a-dc9623fabb62)

---------

Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-22 03:35:46 +00:00
Luc
93e5e6cb95
fix double comment characters (#17484)
# Objective
- Improve docs by removing duplicate comment characters
- Fixes #17483

## Solution
- Replaced `/// ///` with `///`
2025-01-21 23:24:05 +00:00
JaySpruce
fe24652cc0
Change World::try_despawn and World::try_insert_batch to return Result (#17376)
## Objective

Most `try` methods on `World` return a `Result`, but `try_despawn` and
`try_insert_batch` don't. Since Bevy's error handling is advancing,
these should be brought in line.

## Solution

- Added `TryDespawnError` and `TryInsertBatchError`.
- `try_despawn`, `try_insert_batch`, and `try_insert_batch_if_new` now
return their respective errors.
- Fixed slightly incorrect behavior in `try_insert_batch_with_caller`.
- The method was always meant to continue with the rest of the batch if
an entity was missing, but that only worked after the first entity; if
the first entity was missing, the method would exit early. This has been
resolved.

## Migration Guide
- `World::try_despawn` now returns a `Result` rather than a `bool`.
- `World::try_insert_batch` and `World::try_insert_batch_if_new` now
return a `Result` where they previously returned nothing.
2025-01-21 23:21:32 +00:00
Alice Cecile
44ad3bf62b
Move Resource trait to its own file (#17469)
# Objective

`bevy_ecs`'s `system` module is something of a grab bag, and *very*
large. This is particularly true for the `system_param` module, which is
more than 2k lines long!

While it could be defensible to put `Res` and `ResMut` there (lol no
they're in change_detection.rs, obviously), it doesn't make any sense to
put the `Resource` trait there. This is confusing to navigate (and
painful to work on and review).

## Solution

- Create a root level `bevy_ecs/resource.rs` module to mirror
`bevy_ecs/component.rs`
- move the `Resource` trait to that module
- move the `Resource` derive macro to that module as well (Rust really
likes when you pun on the names of the derive macro and trait and put
them in the same path)
- fix all of the imports

## Notes to reviewers

- We could probably move more stuff into here, but I wanted to keep this
PR as small as possible given the absurd level of import changes.
- This PR is ground work for my upcoming attempts to store resource data
on components (resources-as-entities). Splitting this code out will make
the work and review a bit easier, and is the sort of overdue refactor
that's good to do as part of more meaningful work.

## Testing

cargo build works!

## Migration Guide

`bevy_ecs::system::Resource` has been moved to
`bevy_ecs::resource::Resource`.
2025-01-21 19:47:08 +00:00
Alice Cecile
85eceb022d
Add insert and remove recursive methods on EntityWorldMut and EntityCommands (#17463)
# Objective

While being able to quickly add / remove components down a tree is
broadly useful (material changing!), it's particularly necessary when
combined with the newly added #13120.

## Solution

Write four methods: covering both adding and removal on both
`EntityWorldMut` and `EntityCommands`.

These methods are generic over the `RelationshipTarget`, thanks to the
freshly merged relations 🎉

## Testing

I've added a simple unit test for these methods.

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2025-01-21 02:57:57 +00:00
AlephCubed
42b928b90e
Added helper methods to Bundles. (#17464)
Added `len`, `is_empty`, and `iter` methods to `Bundles`.

Separated out from #17331.

---------

Co-authored-by: shuo <shuoli84@gmail.com>
2025-01-21 02:19:02 +00:00
Alice Cecile
b34833f00c
Add an example teaching users about custom relationships (#17443)
# Objective

After #17398, Bevy now has relations! We don't teach users how to make /
work with these in the examples yet though, but we definitely should.

## Solution

- Add a simple abstract example that goes over defining, spawning,
traversing and removing a custom relations.
- ~~Add `Relationship` and `RelationshipTarget` to the prelude: the
trait methods are really helpful here.~~
- this causes subtle ambiguities with method names and weird compiler
errors. Not doing it here!
- Clean up related documentation that I referenced when writing this
example.

## Testing

`cargo run --example relationships`

## Notes to reviewers

1. Yes, I know that the cycle detection code could be more efficient. I
decided to reduce the caching to avoid distracting from the broader
point of "here's how you traverse relationships".
2. Instead of using an `App`, I've decide to use
`World::run_system_once` + system functions defined inside of `main` to
do something closer to literate programming.

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2025-01-20 23:17:38 +00:00
Carter Anderson
ba5e71f53d
Parent -> ChildOf (#17427)
Fixes #17412

## Objective

`Parent` uses the "has a X" naming convention. There is increasing
sentiment that we should use the "is a X" naming convention for
relationships (following #17398). This leaves `Children` as-is because
there is prevailing sentiment that `Children` is clearer than `ParentOf`
in many cases (especially when treating it like a collection).

This renames `Parent` to `ChildOf`.

This is just the implementation PR. To discuss the path forward, do so
in #17412.

## Migration Guide

- The `Parent` component has been renamed to `ChildOf`.
2025-01-20 22:13:29 +00:00
Andreas Monitzer
000c362de0
Include ReflectFromReflect in all dynamic data types. (#17453)
# Objective

Fixes #17416

## Solution

I just included ReflectFromReflect in all macros and implementations. I
think this should be ok, at least it compiles properly and does fix the
errors in my test code.

## Testing

I generated a DynamicMap and tried to convert it into a concrete
`HashMap` as a `Box<dyn Reflect>`. Without my fix, it doesn't work,
because this line panics:

```rust
let rfr = ty.data::<ReflectFromReflect>().unwrap();
```

where `ty` is the `TypeRegistration` for the (matching) `HashMap`.

I don't know why `ReflectFromReflect` wasn't included everywhere, I
assume that it was an oversight and not an architecture decision I'm not
aware of.

# Migration Guide

The hasher in reflected `HashMap`s and `HashSet`s now have to implement
`Default`. This is the case for the ones provided by Bevy already, and
is generally a sensible thing to do.
2025-01-20 22:08:24 +00:00
NiseVoid
de5486725d
Add DefaultQueryFilters (#13120)
# Objective

Some usecases in the ecosystems are blocked by the inability to stop
bevy internals and third party plugins from touching their entities.
However the specifics of a general purpose entity disabling system are
controversial and further complicated by hierarchies. We can partially
unblock these usecases with an opt-in approach: default query filters.

## Solution

- Introduce DefaultQueryFilters, these filters are automatically applied
to queries that don't otherwise mention the filtered component.
- End users and third party plugins can register default filters and are
responsible for handling entities they have hidden this way.
- Extra features can be left for after user feedback
- The default value could later include official ways to hide entities

---

## Changelog

- Add DefaultQueryFilters
2025-01-20 21:57:39 +00:00
SpecificProtagonist
a7051a4815
Diagnostics for label traits (#17441)
# Objective

Diagnostics for labels don't suggest how to best implement them.
```
error[E0277]: the trait bound `Label: ScheduleLabel` is not satisfied
   --> src/main.rs:15:35
    |
15  |     let mut sched = Schedule::new(Label);
    |                     ------------- ^^^^^ the trait `ScheduleLabel` is not implemented for `Label`
    |                     |
    |                     required by a bound introduced by this call
    |
    = help: the trait `ScheduleLabel` is implemented for `Interned<(dyn ScheduleLabel + 'static)>`
note: required by a bound in `bevy_ecs::schedule::Schedule::new`
   --> /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/schedule.rs:297:28
    |
297 |     pub fn new(label: impl ScheduleLabel) -> Self {
    |                            ^^^^^^^^^^^^^ required by this bound in `Schedule::new`
```

## Solution

`diagnostics::on_unimplemented` and `diagnostics::do_not_recommend`

## Showcase

New error message:
```
error[E0277]: the trait bound `Label: ScheduleLabel` is not satisfied
   --> src/main.rs:15:35
    |
15  |     let mut sched = Schedule::new(Label);
    |                     ------------- ^^^^^ the trait `ScheduleLabel` is not implemented for `Label`
    |                     |
    |                     required by a bound introduced by this call
    |
    = note: consider annotating `Label` with `#[derive(ScheduleLabel)]`
note: required by a bound in `bevy_ecs::schedule::Schedule::new`
   --> /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/schedule/schedule.rs:297:28
    |
297 |     pub fn new(label: impl ScheduleLabel) -> Self {
    |                            ^^^^^^^^^^^^^ required by this bound in `Schedule::new`
```
2025-01-20 21:51:26 +00:00
Younes
ebbd961739
docs: enhance documentation in query.rs to clarify borrowing rules (#17370)
docs: enhance documentation in `query.rs` to clarify borrowing rules.

Please, let me know if you don't agree with the wording.. There is
always room for improvement.

Tested locally and it looks like this:


![image](https://github.com/user-attachments/assets/1283fcac-c5f7-426f-844f-fc2a12ce2b42)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-20 21:31:20 +00:00
Hexroll by Pen, Dice & Paper
15facbb964
Fixing ui antialiasing clamp call parameters order (#14970) (#17456)
# Objective

Fixes #14970

## Solution

It seems the clamp call in `ui.wgsl` had the parameters order incorrect.

## Testing

Tested using examples/ui in native and my current project in wasm - both
in linux.
Could use some help with testing in other platforms.

---
2025-01-20 21:31:20 +00:00
Thierry Berger
6fc965ed56
Expose a few primitive builders, which seemed to be missed? (#17454)
Some primitives seems to have their export being missed, we can see in
the documentation that types are not followable: :
[CuboidMeshBuilder](https://docs.rs/bevy/latest/bevy/math/prelude/struct.Cuboid.html#impl-Meshable-for-Cuboid)
is not exposed.

This Pr addresses this, + its surrounding modules which were around.
2025-01-20 21:29:38 +00:00
Vic
59657ed1e2
remove unsound DerefMut impls from EntityHashMap/EntityHashSet (#17450)
# Objective

Noticed while doing #17449, I had left these `DerefMut` impls in.
Obtaining mutable references to those inner iterator types allows for
`mem::swap`, which can be used to swap an incorrectly behaving instance
into the wrappers.

## Solution

Remove them!
2025-01-20 21:28:28 +00:00
Alice Cecile
5a9bc28502
Support non-Vec data structures in relations (#17447)
# Objective

The existing `RelationshipSourceCollection` uses `Vec` as the only
possible backing for our relationships. While a reasonable choice,
benchmarking use cases might reveal that a different data type is better
or faster.

For example:

- Not all relationships require a stable ordering between the
relationship sources (i.e. children). In cases where we a) have many
such relations and b) don't care about the ordering between them, a hash
set is likely a better datastructure than a `Vec`.
- The number of children-like entities may be small on average, and a
`smallvec` may be faster

## Solution

- Implement `RelationshipSourceCollection` for `EntityHashSet`, our
custom entity-optimized `HashSet`.
-~~Implement `DoubleEndedIterator` for `EntityHashSet` to make things
compile.~~
   -  This implementation was cursed and very surprising.
- Instead, by moving the iterator type on `RelationshipSourceCollection`
from an erased RPTIT to an explicit associated type we can add a trait
bound on the offending methods!
- Implement `RelationshipSourceCollection` for `SmallVec`

## Testing

I've added a pair of new tests to make sure this pattern compiles
successfully in practice!

## Migration Guide

`EntityHashSet` and `EntityHashMap` are no longer re-exported in
`bevy_ecs::entity` directly. If you were not using `bevy_ecs` / `bevy`'s
`prelude`, you can access them through their now-public modules,
`hash_set` and `hash_map` instead.

## Notes to reviewers

The `EntityHashSet::Iter` type needs to be public for this impl to be
allowed. I initially renamed it to something that wasn't ambiguous and
re-exported it, but as @Victoronz pointed out, that was somewhat
unidiomatic.

In
1a8564898f,
I instead made the `entity_hash_set` public (and its `entity_hash_set`)
sister public, and removed the re-export. I prefer this design (give me
module docs please), but it leads to a lot of churn in this PR.

Let me know which you'd prefer, and if you'd like me to split that
change out into its own micro PR.
2025-01-20 21:26:08 +00:00
ickshonpe
3f99a3e8cd
Text 2d alignment fix (#17365)
# Objective

`Text2d` ignores `TextBounds` when calculating the offset for text
aligment.
On main a text entity positioned in the center of the window with center
justification and 600px horizontal text bounds isn't centered like it
should be but shifted off to the right:
<img width="305" alt="hellox"
src="https://github.com/user-attachments/assets/8896c6f0-1b9f-4633-9c12-1de6eff5f3e1"
/>
(second example in the testing section below)

Fixes #14266

I already had a PR in review for this (#14270) but it used post layout
adjustment (which we want to avoid) and ignored `TextBounds`.

## Solution

* If `TextBounds` are present for an axis, use them instead of the size
of the computed text layout size to calculate the offset.
* Adjust the vertical offset of text so it's top is aligned with the top
of the texts bounding rect (when present).

## Testing

```
use bevy::prelude::*;
use bevy::color::palettes;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn example(commands: &mut Commands, dest: Vec3, justify: JustifyText) {
    commands.spawn((
        Sprite {
            color: palettes::css::YELLOW.into(),
            custom_size: Some(10. * Vec2::ONE),
            anchor: Anchor::Center,
            ..Default::default()
        },
        Transform::from_translation(dest),
    ));

    for a in [
        Anchor::TopLeft,
        Anchor::TopRight,
        Anchor::BottomRight,
        Anchor::BottomLeft,
    ] {
        commands.spawn((
            Text2d(format!("L R\n{:?}\n{:?}", a, justify)),
            TextFont {
                font_size: 14.0,
                ..default()
            },
            TextLayout {
                justify,
                ..Default::default()
            },
            TextBounds::new(300., 75.),
            Transform::from_translation(dest + Vec3::Z),
            a,
        ));
    }
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());

    for (i, j) in [
        JustifyText::Left,
        JustifyText::Right,
        JustifyText::Center,
        JustifyText::Justified,
    ]
    .into_iter()
    .enumerate()
    {
        example(&mut commands, (300. - 150. * i as f32) * Vec3::Y, j);
    }

    commands.spawn(Sprite {
        color: palettes::css::YELLOW.into(),
        custom_size: Some(10. * Vec2::ONE),
        anchor: Anchor::Center,
        ..Default::default()
    });
}
```

<img width="566" alt="cap"
src="https://github.com/user-attachments/assets/e6a98fa5-80b2-4380-a9b7-155bb49635b8"
/>

This probably looks really confusing but it should make sense if you
imagine each block of text surrounded by a 300x75 rectangle that is
anchored to the center of the yellow square.

# 

```
use bevy::prelude::*;
use bevy::sprite::Anchor;
use bevy::text::TextBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());

    commands.spawn((
        Text2d::new("hello"),
        TextFont {
            font_size: 60.0,
            ..default()
        },
        TextLayout::new_with_justify(JustifyText::Center),
        TextBounds::new(600., 200.),
        Anchor::Center,
    ));
}
```

<img width="338" alt="hello"
src="https://github.com/user-attachments/assets/e5e89364-afda-4baa-aca8-df4cdacbb4ed"
/>

The text being above the center is intended. When `TextBounds` are
present, the text block's offset is calculated using its `TextBounds`
not the layout size returned by cosmic-text.

# 

Probably we should add a vertical alignment setting for Text2d. Didn't
do it here as this is intended for a 0.15.2 release.
2025-01-20 20:54:32 +00:00
Emerson Coskey
a99674ab86
FromWorld derive macro (#17352)
simple derive macro for `FromWorld`. Going to be needed for composable
pipeline specializers but probably a nice thing to have regardless

## Testing

simple manual testing, nothing seemed to blow up. I'm no proc macro pro
though, so there's a chance I've mishandled spans somewhere or
something.
2025-01-20 20:51:30 +00:00
Zachary Harrold
a64446b77e
Create bevy_platform_support Crate (#17250)
# Objective

- Contributes to #16877

## Solution

- Initial creation of `bevy_platform_support` crate.
- Moved `bevy_utils::Instant` into new `bevy_platform_support` crate.
- Moved `portable-atomic`, `portable-atomic-util`, and
`critical-section` into new `bevy_platform_support` crate.

## Testing

- CI

---

## Showcase

Instead of needing code like this to import an `Arc`:

```rust
#[cfg(feature = "portable-atomic")]
use portable_atomic_util::Arc;

#[cfg(not(feature = "portable-atomic"))]
use alloc::sync::Arc;
```

We can now use:

```rust
use bevy_platform_support::sync::Arc;
```

This applies to many other types, but the goal is overall the same:
allowing crates to use `std`-like types without the boilerplate of
conditional compilation and platform-dependencies.

## Migration Guide

- Replace imports of `bevy_utils::Instant` with
`bevy_platform_support::time::Instant`
- Replace imports of `bevy::utils::Instant` with
`bevy::platform_support::time::Instant`

## Notes

- `bevy_platform_support` hasn't been reserved on `crates.io`
- ~~`bevy_platform_support` is not re-exported from `bevy` at this time.
It may be worthwhile exporting this crate, but I am unsure of a
reasonable name to export it under (`platform_support` may be a bit
wordy for user-facing).~~
- I've included an implementation of `Instant` which is suitable for
`no_std` platforms that are not Wasm for the sake of eliminating feature
gates around its use. It may be a controversial inclusion, so I'm happy
to remove it if required.
- There are many other items (`spin`, `bevy_utils::Sync(Unsafe)Cell`,
etc.) which should be added to this crate. I have kept the initial scope
small to demonstrate utility without making this too unwieldy.

---------

Co-authored-by: TimJentzsch <TimJentzsch@users.noreply.github.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-01-20 20:45:30 +00:00
Zachary Harrold
8f32c799ee
Switch bevy_asset to core::prelude (#17442)
Makes use of `std` explicit, simplifying a possible `no_std` port.

# Objective

- Contributes to #15460
- Simplify future `no_std` work on `bevy_asset`

## Solution

- Add `#![no_std]` to switch to `core::prelude` instead of
`std::prelude`

## Testing

- CI

---

## Notes

This is entirely a change around the names of imports and has no impact
on functionality. This just reduces the quantity of changes involved in
the (likely more controversial) `no_std`-ification of `bevy_asset`.
2025-01-20 04:14:48 +00:00
AlephCubed
5d0e9cfb36
Flattened PointerAction::Pressed into Press and Release. (#17424)
Fixes #17397.
Also renamed all variants into present-tense.
## Migration Guide
- `PointerAction::Pressed` has been seperated into two variants,
`PointerAction::Press` and `PointerAction::Release`.
- `PointerAction::Moved` has been renamed to `PointerAction::Move`. 
- `PointerAction::Canceled` has been renamed to `PointerAction::Cancel`.
2025-01-19 22:51:57 +00:00
ickshonpe
adc33b5108
Rename TargetCamera to UiTargetCamera (#17403)
# Objective

It's not immediately obvious that `TargetCamera` only works with UI node
entities. It's natural to assume from looking at something like the
`multiple_windows` example that it will work with everything.

## Solution

Rename `TargetCamera` to `UiTargetCamera`.

## Migration Guide

`TargetCamera` has been renamed to `UiTargetCamera`.
2025-01-19 19:56:57 +00:00
Sigma-dev
7c8da1c05d
Reworked Segment types into their cartesian forms (#17404)
# Objective

Segment2d and Segment3d are currently hard to work with because unlike
many other primary shapes, they are bound to the origin.
The objective of this PR is to allow these segments to exist anywhere in
cartesian space, making them much more useful in a variety of contexts.

## Solution

Reworking the existing segment type's internal fields and methods to
allow them to exist anywhere in cartesian space.
I have done both reworks for 2d and 3d segments but I was unsure if I
should just have it all here or not so feel free to tell me how I should
proceed, for now I have only pushed Segment2d changes.

As I am not a very seasoned contributor, this first implementation is
very likely sloppy and will need some additional work from my end, I am
open to all criticisms and willing to work to get this to bevy's
standards.

## Testing

I am not very familiar with the standards of testing. Of course my
changes had to pass the thorough existing tests for primitive shapes.
I also checked the gizmo 2d shapes intersection example and everything
looked fine.

I did add a few utility methods to the types that have no tests yet. I
am willing to implement some if it is deemed necessary

## Migration Guide

The segment type constructors changed so if someone previously created a
Segment2d with a direction and length they would now need to use the
`from_direction` constructor

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2025-01-19 03:54:45 +00:00
Carter Anderson
21f1e3045c
Relationships (non-fragmenting, one-to-many) (#17398)
This adds support for one-to-many non-fragmenting relationships (with
planned paths for fragmenting and non-fragmenting many-to-many
relationships). "Non-fragmenting" means that entities with the same
relationship type, but different relationship targets, are not forced
into separate tables (which would cause "table fragmentation").

Functionally, this fills a similar niche as the current Parent/Children
system. The biggest differences are:

1. Relationships have simpler internals and significantly improved
performance and UX. Commands and specialized APIs are no longer
necessary to keep everything in sync. Just spawn entities with the
relationship components you want and everything "just works".
2. Relationships are generalized. Bevy can provide additional built in
relationships, and users can define their own.

**REQUEST TO REVIEWERS**: _please don't leave top level comments and
instead comment on specific lines of code. That way we can take
advantage of threaded discussions. Also dont leave comments simply
pointing out CI failures as I can read those just fine._

## Built on top of what we have

Relationships are implemented on top of the Bevy ECS features we already
have: components, immutability, and hooks. This makes them immediately
compatible with all of our existing (and future) APIs for querying,
spawning, removing, scenes, reflection, etc. The fewer specialized APIs
we need to build, maintain, and teach, the better.

## Why focus on one-to-many non-fragmenting first?

1. This allows us to improve Parent/Children relationships immediately,
in a way that is reasonably uncontroversial. Switching our hierarchy to
fragmenting relationships would have significant performance
implications. ~~Flecs is heavily considering a switch to non-fragmenting
relations after careful considerations of the performance tradeoffs.~~
_(Correction from @SanderMertens: Flecs is implementing non-fragmenting
storage specialized for asset hierarchies, where asset hierarchies are
many instances of small trees that have a well defined structure)_
2. Adding generalized one-to-many relationships is currently a priority
for the [Next Generation Scene / UI
effort](https://github.com/bevyengine/bevy/discussions/14437).
Specifically, we're interested in building reactions and observers on
top.

## The changes

This PR does the following:

1. Adds a generic one-to-many Relationship system
3. Ports the existing Parent/Children system to Relationships, which now
lives in `bevy_ecs::hierarchy`. The old `bevy_hierarchy` crate has been
removed.
4. Adds on_despawn component hooks
5. Relationships can opt-in to "despawn descendants" behavior, meaning
that the entire relationship hierarchy is despawned when
`entity.despawn()` is called. The built in Parent/Children hierarchies
enable this behavior, and `entity.despawn_recursive()` has been removed.
6. `world.spawn` now applies commands after spawning. This ensures that
relationship bookkeeping happens immediately and removes the need to
manually flush. This is in line with the equivalent behaviors recently
added to the other APIs (ex: insert).
7. Removes the ValidParentCheckPlugin (system-driven / poll based) in
favor of a `validate_parent_has_component` hook.

## Using Relationships

The `Relationship` trait looks like this:

```rust
pub trait Relationship: Component + Sized {
    type RelationshipSources: RelationshipSources<Relationship = Self>;
    fn get(&self) -> Entity;
    fn from(entity: Entity) -> Self;
}
```

A relationship is a component that:

1. Is a simple wrapper over a "target" Entity.
2. Has a corresponding `RelationshipSources` component, which is a
simple wrapper over a collection of entities. Every "target entity"
targeted by a "source entity" with a `Relationship` has a
`RelationshipSources` component, which contains every "source entity"
that targets it.

For example, the `Parent` component (as it currently exists in Bevy) is
the `Relationship` component and the entity containing the Parent is the
"source entity". The entity _inside_ the `Parent(Entity)` component is
the "target entity". And that target entity has a `Children` component
(which implements `RelationshipSources`).

In practice, the Parent/Children relationship looks like this:

```rust
#[derive(Relationship)]
#[relationship(relationship_sources = Children)]
pub struct Parent(pub Entity);

#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent)]
pub struct Children(Vec<Entity>);
```

The Relationship and RelationshipSources derives automatically implement
Component with the relevant configuration (namely, the hooks necessary
to keep everything in sync).

The most direct way to add relationships is to spawn entities with
relationship components:

```rust
let a = world.spawn_empty().id();
let b = world.spawn(Parent(a)).id();

assert_eq!(world.entity(a).get::<Children>().unwrap(), &[b]);
```

There are also convenience APIs for spawning more than one entity with
the same relationship:

```rust
world.spawn_empty().with_related::<Children>(|s| {
    s.spawn_empty();
    s.spawn_empty();
})
```

The existing `with_children` API is now a simpler wrapper over
`with_related`. This makes this change largely non-breaking for existing
spawn patterns.

```rust
world.spawn_empty().with_children(|s| {
    s.spawn_empty();
    s.spawn_empty();
})
```

There are also other relationship APIs, such as `add_related` and
`despawn_related`.

## Automatic recursive despawn via the new on_despawn hook

`RelationshipSources` can opt-in to "despawn descendants" behavior,
which will despawn all related entities in the relationship hierarchy:

```rust
#[derive(RelationshipSources)]
#[relationship_sources(relationship = Parent, despawn_descendants)]
pub struct Children(Vec<Entity>);
```

This means that `entity.despawn_recursive()` is no longer required.
Instead, just use `entity.despawn()` and the relevant related entities
will also be despawned.

To despawn an entity _without_ despawning its parent/child descendants,
you should remove the `Children` component first, which will also remove
the related `Parent` components:

```rust
entity
    .remove::<Children>()
    .despawn()
```

This builds on the on_despawn hook introduced in this PR, which is fired
when an entity is despawned (before other hooks).

## Relationships are the source of truth

`Relationship` is the _single_ source of truth component.
`RelationshipSources` is merely a reflection of what all the
`Relationship` components say. By embracing this, we are able to
significantly improve the performance of the system as a whole. We can
rely on component lifecycles to protect us against duplicates, rather
than needing to scan at runtime to ensure entities don't already exist
(which results in quadratic runtime). A single source of truth gives us
constant-time inserts. This does mean that we cannot directly spawn
populated `Children` components (or directly add or remove entities from
those components). I personally think this is a worthwhile tradeoff,
both because it makes the performance much better _and_ because it means
theres exactly one way to do things (which is a philosophy we try to
employ for Bevy APIs).

As an aside: treating both sides of the relationship as "equivalent
source of truth relations" does enable building simple and flexible
many-to-many relationships. But this introduces an _inherent_ need to
scan (or hash) to protect against duplicates.
[`evergreen_relations`](https://github.com/EvergreenNest/evergreen_relations)
has a very nice implementation of the "symmetrical many-to-many"
approach. Unfortunately I think the performance issues inherent to that
approach make it a poor choice for Bevy's default relationship system.

## Followup Work

* Discuss renaming `Parent` to `ChildOf`. I refrained from doing that in
this PR to keep the diff reasonable, but I'm personally biased toward
this change (and using that naming pattern generally for relationships).
* [Improved spawning
ergonomics](https://github.com/bevyengine/bevy/discussions/16920)
* Consider adding relationship observers/triggers for "relationship
targets" whenever a source is added or removed. This would replace the
current "hierarchy events" system, which is unused upstream but may have
existing users downstream. I think triggers are the better fit for this
than a buffered event queue, and would prefer not to add that back.
* Fragmenting relations: My current idea hinges on the introduction of
"value components" (aka: components whose type _and_ value determines
their ComponentId, via something like Hashing / PartialEq). By labeling
a Relationship component such as `ChildOf(Entity)` as a "value
component", `ChildOf(e1)` and `ChildOf(e2)` would be considered
"different components". This makes the transition between fragmenting
and non-fragmenting a single flag, and everything else continues to work
as expected.
* Many-to-many support
* Non-fragmenting: We can expand Relationship to be a list of entities
instead of a single entity. I have largely already written the code for
this.
* Fragmenting: With the "value component" impl mentioned above, we get
many-to-many support "for free", as it would allow inserting multiple
copies of a Relationship component with different target entities.

Fixes #3742 (If this PR is merged, I think we should open more targeted
followup issues for the work above, with a fresh tracking issue free of
the large amount of less-directed historical context)
Fixes #17301
Fixes #12235 
Fixes #15299
Fixes #15308 

## Migration Guide

* Replace `ChildBuilder` with `ChildSpawnerCommands`.
* Replace calls to `.set_parent(parent_id)` with
`.insert(Parent(parent_id))`.
* Replace calls to `.replace_children()` with `.remove::<Children>()`
followed by `.add_children()`. Note that you'll need to manually despawn
any children that are not carried over.
* Replace calls to `.despawn_recursive()` with `.despawn()`.
* Replace calls to `.despawn_descendants()` with
`.despawn_related::<Children>()`.
* If you have any calls to `.despawn()` which depend on the children
being preserved, you'll need to remove the `Children` component first.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-18 22:20:30 +00:00
Jean Mertz
23dbcf9215
impl Default for StateScoped<S: Default> (#17401)
This allows this:

```rust
#[derive(Component)]
#[require(StateScoped<MyState>(StateScoped(MyState)))]
struct ComponentA;
```

To be shortened to this:

```rust
#[derive(Component)]
#[require(StateScoped<MyState>)]
struct ComponentA;
```

When `MyState` implements `Default`.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
2025-01-17 01:19:09 +00:00
Christian Hughes
14a955c5eb
Add usage notes for the IntoX family of ECS traits (#17379)
# Objective

Occasionally bevy users will want to store systems or observer systems
in a component or resource, but they first try to store `IntoSystem`
instead of `System`, which leads to some headaches having to deal with
the `M` marker type parameter. We should recommend they use the `X`
trait instead of the `IntoX` trait in that case, as well for returning
from a function.

## Solution

Add usage notes to the `IntoX` traits about using `X` instead.
2025-01-17 01:18:22 +00:00
Alice Cecile
3737f86d84
Small improvements for directional navigation (#17395)
# Objective

While working on more complex directional navigation work, I noticed a
few small things.

## Solution

Rather than stick them in a bigger PR, split them out now.

- Include more useful information when responding to
`DirectionalNavigationError`.
- Use the less controversial `Click` events (rather than `Pressed`) in
the example
- Implement add_looping_edges in terms of `add_edges`. Thanks @rparrett
for the idea.

## Testing

Ran the `directional_navigation` example and things still work.
2025-01-17 01:15:39 +00:00
Rob Parrett
b693362b0c
Fix some bevy_remote typos (#17408)
# Objective

Contributor expressed distress on Discord over introducing a typo.

## Solution

Fix em
2025-01-16 23:34:51 +00:00
Joseph
77fd7bf7ce
Update safety docs for Ptr::assert_unique (#17394)
# Objective

The safety documentation for `Ptr::assert_unique` is incomplete.
Currently it only mentions the existence of other `Ptr` instances, but
it should also mention that the underlying data must be mutable and that
there cannot be active references to it.
2025-01-16 03:25:19 +00:00
Alice Cecile
72f70745c5
add_edges helper for directional navigation (#17389)
# Objective

While `add_looping_edges` is a helpful method for manually defining
directional navigation maps, we don't always want to loop around!

## Solution

Add a non-looping variant.

These commits are cherrypicked from the more complex #17247.

## Testing

I've updated the `directional_navigation` example to use these changes,
and verified that it works.

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-15 23:43:03 +00:00
Zachary Harrold
5cc3f4727e
Implement Clone for QueryIter over read-only data (#17391)
# Objective

- Fix issue identified on the [Discord
server](https://discord.com/channels/691052431525675048/691052431974465548/1328922812530036839)

## Solution

- Implement `Clone` for `QueryIter` using the existing
`QueryIter::remaining` method

## Testing

- CI

---

## Showcase

Users can now explicitly clone a read-only `QueryIter`:

```rust
fn combinations(query: Query<&ComponentA>) {
    let mut iter = query.iter();
    while let Some(a) = iter.next() {
        // Can now clone rather than use remaining
        for b in iter.clone() {
            // Check every combination (a, b)
        }
    }
}
```


## Notes

This doesn't add any new functionality outside the context of generic
code (e.g., `T: Iterator<...> + Clone`), it's mostly for
discoverability. Users are more likely to be familiar with
`Clone::clone` than they are with the methods on `QueryIter`.
2025-01-15 21:56:11 +00:00
Periwink
64ab33c6a7
Use chain() for system dependency (#17387)
# Objective

Tiny PR to use chain() for system dependency, which is shorter/clearer
2025-01-15 18:48:18 +00:00
Alice Cecile
237c6b207e
Remove Event: Component trait bound using a wrapper type which impls Component (#17380)
# Objective

As raised in https://github.com/bevyengine/bevy/pull/17317, the `Event:
Component` trait bound is confusing to users.

In general, a type `E` (like `AppExit`) which implements `Event` should
not:

- be stored as a component on an entity
- be a valid option for `Query<&AppExit>`
- require the storage type and other component metadata to be specified

Events are not components (even if they one day use some of the same
internal mechanisms), and this trait bound is confusing to users.

We're also automatically generating `Component` impls with our derive
macro, which should be avoided when possible to improve explicitness and
avoid conflicts with user impls.

Closes #17317, closes #17333

## Solution

- We only care that each unique event type gets a unique `ComponentId`
- dynamic events need their own tools for getting identifiers anyways
- This avoids complicating the internals of `ComponentId` generation.
- Clearly document why this cludge-y solution exists.

In the medium term, I think that either a) properly generalizing
`ComponentId` (and moving it into `bevy_reflect?) or b) using a
new-typed `Entity` as the key for events is more correct. This change is
stupid simple though, and removes the offending trait bound in a way
that doesn't introduce complex tech debt and does not risk changes to
the internals.

This change does not:

- restrict our ability to implement dynamic buffered events (the main
improvement over #17317)
- there's still a fair bit of work to do, but this is a step in the
right direction
- limit our ability to store event metadata on entities in the future
- make it harder for users to work with types that are both events and
components (just add the derive / trait bound)

## Migration Guide

The `Event` trait no longer requires the `Component` trait. If you were
relying on this behavior, change your trait bounds from `Event` to
`Event + Component`. If you also want your `Event` type to implement
`Component`, add a derive.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-01-15 18:42:47 +00:00
ickshonpe
daf665cc74
Clip outlines using the local clipping rect. (#17385)
# Objective

UI node Outlines are clipped using their parent's clipping rect instead
of their own.

## Solution

Clip outlines using the UI node's own clipping rect.
2025-01-15 18:19:35 +00:00
Andrew Hickman
6ea1574cc1
Add type registration for PickingInteraction (#17372)
I noticed that this component was not being returned correctly by the
`bevy_remote` api

```json
"errors": {
  "bevy_picking::focus::PickingInteraction": {
    "code": -23402,
    "message": "Unknown component type: `bevy_picking::focus::PickingInteraction`"
  }
}
```
2025-01-15 06:24:19 +00:00
mgi388
4d4253430c
Move CustomCursor to bevy_winit/src/custom_cursor.rs (#17381)
# Objective

- Follow up work from
https://github.com/bevyengine/bevy/pull/17121#issuecomment-2576615700 to
keep the `cursor.rs` file more manageable.

## Solution

- Move `CustomCursor` and make it compile.

## Testing

- Ran the example: `cargo run --example custom_cursor_image
--features=custom_cursor`
- CI
2025-01-15 05:35:57 +00:00
JMS55
e8e2426058
Forward decals (port of bevy_contact_projective_decals) (#16600)
# Objective

- Implement ForwardDecal as outlined in
https://github.com/bevyengine/bevy/issues/2401

## Solution

- Port https://github.com/naasblod/bevy_contact_projective_decals, and
cleanup the API a little.

## Testing

- Ran the new decal example.

---

## Showcase


![image](https://github.com/user-attachments/assets/72134af0-724f-4df9-a11f-b0888819a791)

## Changelog
* Added ForwardDecal and associated types
* Added MaterialExtension::alpha_mode()

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-01-15 02:31:30 +00:00
MichiRecRoom
26bb0b40d2
Move #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] to the workspace Cargo.toml (#17374)
# Objective
Fixes https://github.com/bevyengine/bevy/issues/17111

## Solution
Move `#![warn(clippy::allow_attributes,
clippy::allow_attributes_without_reason)]` to the workspace `Cargo.toml`

## Testing
Lots of CI testing, and local testing too.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-15 01:14:58 +00:00
mgi388
0756a19f28
Support texture atlases in CustomCursor::Image (#17121)
# Objective

- Bevy 0.15 added support for custom cursor images in
https://github.com/bevyengine/bevy/pull/14284.
- However, to do animated cursors using the initial support shipped in
0.15 means you'd have to animate the `Handle<Image>`: You can't use a
`TextureAtlas` like you can with sprites and UI images.
- For my use case, my cursors are spritesheets. To animate them, I'd
have to break them down into multiple `Image` assets, but that seems
less than ideal.


## Solution

- Allow users to specify a `TextureAtlas` field when creating a custom
cursor image.
- To create parity with Bevy's `TextureAtlas` support on `Sprite`s and
`ImageNode`s, this also allows users to specify `rect`, `flip_x` and
`flip_y`. In fact, for my own use case, I need to `flip_y`.

## Testing

- I added unit tests for `calculate_effective_rect` and
`extract_and_transform_rgba_pixels`.
- I added a brand new example for custom cursor images. It has controls
to toggle fields on and off. I opted to add a new example because the
existing cursor example (`window_settings`) would be far too messy for
showcasing these custom cursor features (I did start down that path but
decided to stop and make a brand new example).
- The new example uses a [Kenny cursor icon] sprite sheet. I included
the licence even though it's not required (and it's CC0).
- I decided to make the example just loop through all cursor icons for
its animation even though it's not a _realistic_ in-game animation
sequence.
- I ran the PNG through https://tinypng.com. Looks like it's about 35KB.
- I'm open to adjusting the example spritesheet if required, but if it's
fine as is, great.

[Kenny cursor icon]: https://kenney-assets.itch.io/crosshair-pack

---

## Showcase


https://github.com/user-attachments/assets/8f6be8d7-d1d4-42f9-b769-ef8532367749

## Migration Guide

The `CustomCursor::Image` enum variant has some new fields. Update your
code to set them.

Before:

```rust
CustomCursor::Image {
    handle: asset_server.load("branding/icon.png"),
    hotspot: (128, 128),
}
```

After:

```rust
CustomCursor::Image {
    handle: asset_server.load("branding/icon.png"),
    texture_atlas: None,
    flip_x: false,
    flip_y: false,
    rect: None,
    hotspot: (128, 128),
}
```

## References

- Feature request [originally raised in Discord].

[originally raised in Discord]:
https://discord.com/channels/691052431525675048/692572690833473578/1319836362219847681
2025-01-14 22:27:24 +00:00
Nicholas Charbonneau
f2e00c8ed5
feat: support for clip children on windows (#16545)
# Objective

Support the parametrization of the WS_CLIPCHILDREN style on Windows.

Fixes #16544

## Solution

Added a window configuration in bevy_winit to control the usage of the
WS_CLIPCHILDREN style.

## Testing

- Did you test these changes? If so, how?
I did. I was able to create a Wry Webview with a transparent HTML
document and was also able to see my Bevy scene behind the webview
elements.

- Are there any parts that need more testing?
I don't believe so. I assume the option is extensively tested within
winit itself.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Test repositiory [here](https://github.com/nicholasc/bevy_wry_test).
Bevy's path will need to be updated in the Cargo.toml

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
This is a Windows specific issue. Should be tested accordingly.

---------

Co-authored-by: jf908 <jf908@users.noreply.github.com>
2025-01-14 22:22:20 +00:00
Adrian Kortyczko
dcff8f3ecb
Make ObservedBy public (#17297)
# Objective
- Currently, the `ObservedBy`-component is only public within the
`bevy_ecs` crate. Sometimes it is desirable to refer to this component
in the "game-code". Two examples that come in mind:
- Clearing all components in an entity, but intending to keep the
existing observers: Making `ObservedBy` public allows us to use
`commands.entity(entity).retain::<ObservedBy>();`, which clears all
other components, but keeps `ObservedBy`, which prevents the Observers
from despawning.
- The opposite of the above, clearing all of entities' Observers:
`commands.entity(entity).remove::<ObservedBy>` will despawn all
associated Observers. Admittedly, a cleaner solution would be something
like `commands.entity(entity).clear_observers()`, but this is
sufficient.

## Solution

- Removed `(crate)` "rule" and added `ObservedBy` to the prelude-module

## Testing

- Linked `bevy_ecs` locally with another project to see if `ObservedBy`
could be referenced.
2025-01-14 21:53:42 +00:00
Jaso333
9ef1964d34
added any_match_filter common condition (#17327)
# Objective

resolves #17326.

## Solution

Simply added the suggested run condition.

## Testing

A self-explanatory run condition. Fully verified by the operation of
`QueryFilter` in a system.
2025-01-14 21:53:35 +00:00
Younes
276d6e8014
fix typo query.rs (#17366)
fix typo query.rs
2025-01-14 21:53:19 +00:00
Rich Churcher
eec5915da8
Fix some punctuation (#17368)
Found a few missing full-stops, etc.
2025-01-14 21:51:12 +00:00
MichiRecRoom
17c46f4add
bevy_ecs: Apply #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17335)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `warn`, and bring
`bevy_ecs` in line with the new restrictions.

## Testing
This PR is a WIP; testing will happen after it's finished.
2025-01-14 21:37:41 +00:00
MichiRecRoom
706cdd5ce2
bevy_macro_utils: Apply #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17304)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `warn`, and bring
`bevy_macro_utils` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_macro_utils` was
run, and no warnings were encountered.
2025-01-14 21:34:12 +00:00
MichiRecRoom
dfe8e6300a
bevy_input_focus: Apply #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17323)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `warn`, and bring
`bevy_input_focus` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --features
bevy_math/std,bevy_input/smol_str --package bevy_input_focus` was run,
and only an unrelated warning from `bevy_ecs` was encountered.

I could not test without the `bevy_math/std` feature due to compilation
errors with `glam`. Additionally, I had to use the `bevy_input/smol_str`
feature, as it appears some of `bevy_input_focus`' tests rely on that
feature. I will investigate these issues further, and make issues/PRs as
necessary.
2025-01-14 21:34:01 +00:00
MichiRecRoom
61a226bd8b
bevy_dylib: Apply #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17332)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `warn`, and bring
`bevy_dylib` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_dylib` was run, and
no warnings were encountered.

I would've skipped over this crate if there weren't the two lint
attributes in it - might as well handle it now, y'know?
2025-01-14 21:33:41 +00:00
MichiRecRoom
0c6fd70834
bevy_core_pipeline: Apply #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17137)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `warn`, and bring
`bevy_core_pipeline` in line with the new restrictions.

## Testing
`cargo clippy` and `cargo test --package bevy_core_pipeline` were run,
and no warnings were encountered.
2025-01-14 21:33:28 +00:00
Patrick Walton
35101f3ed5
Use multi_draw_indirect_count where available, in preparation for two-phase occlusion culling. (#17211)
This commit allows Bevy to use `multi_draw_indirect_count` for drawing
meshes. The `multi_draw_indirect_count` feature works just like
`multi_draw_indirect`, but it takes the number of indirect parameters
from a GPU buffer rather than specifying it on the CPU.

Currently, the CPU constructs the list of indirect draw parameters with
the instance count for each batch set to zero, uploads the resulting
buffer to the GPU, and dispatches a compute shader that bumps the
instance count for each mesh that survives culling. Unfortunately, this
is inefficient when we support `multi_draw_indirect_count`. Draw
commands corresponding to meshes for which all instances were culled
will remain present in the list when calling
`multi_draw_indirect_count`, causing overhead. Proper use of
`multi_draw_indirect_count` requires eliminating these empty draw
commands.

To address this inefficiency, this PR makes Bevy fully construct the
indirect draw commands on the GPU instead of on the CPU. Instead of
writing instance counts to the draw command buffer, the mesh
preprocessing shader now writes them to a separate *indirect metadata
buffer*. A second compute dispatch known as the *build indirect
parameters* shader runs after mesh preprocessing and converts the
indirect draw metadata into actual indirect draw commands for the GPU.
The build indirect parameters shader operates on a batch at a time,
rather than an instance at a time, and as such each thread writes only 0
or 1 indirect draw parameters, simplifying the current logic in
`mesh_preprocessing`, which currently has to have special cases for the
first mesh in each batch. The build indirect parameters shader emits
draw commands in a tightly packed manner, enabling maximally efficient
use of `multi_draw_indirect_count`.

Along the way, this patch switches mesh preprocessing to dispatch one
compute invocation per render phase per view, instead of dispatching one
compute invocation per view. This is preparation for two-phase occlusion
culling, in which we will have two mesh preprocessing stages. In that
scenario, the first mesh preprocessing stage must only process opaque
and alpha tested objects, so the work items must be separated into those
that are opaque or alpha tested and those that aren't. Thus this PR
splits out the work items into a separate buffer for each phase. As this
patch rewrites so much of the mesh preprocessing infrastructure, it was
simpler to just fold the change into this patch instead of deferring it
to the forthcoming occlusion culling PR.

Finally, this patch changes mesh preprocessing so that it runs
separately for indexed and non-indexed meshes. This is because draw
commands for indexed and non-indexed meshes have different sizes and
layouts. *The existing code is actually broken for non-indexed meshes*,
as it attempts to overlay the indirect parameters for non-indexed meshes
on top of those for indexed meshes. Consequently, right now the
parameters will be read incorrectly when multiple non-indexed meshes are
multi-drawn together. *This is a bug fix* and, as with the change to
dispatch phases separately noted above, was easiest to include in this
patch as opposed to separately.

## Migration Guide

* Systems that add custom phase items now need to populate the indirect
drawing-related buffers. See the `specialized_mesh_pipeline` example for
an example of how this is done.
2025-01-14 21:19:20 +00:00
BD103
e53c8e0933
Create missing constructors for 2D primitive mesh builders (#17291)
# Objective

- While all
[`MeshBuilder`](https://dev-docs.bevyengine.org/bevy/prelude/trait.MeshBuilder.html)s
can be created by first creating the primitive `bevy_math` type and
using
[`Meshable`](https://dev-docs.bevyengine.org/bevy/prelude/trait.Meshable.html),
most builders have their own `const` constructors that can be used
instead. Some builders are missing constructors, however, making them
unavailable in `const` contexts.

## Solution

- Add a `const` constructor for `RegularPolygonMeshBuilder`,
`RhombusMeshBuilder`, `Triangle2dMeshBuilder`, and
`RectangleMeshBuilder`.
- Add a note on the requirements of `ConvexPolygonMeshBuilder`, and
recommend using `ConvexPolygon::new().mesh()` instead.
- A constructor cannot easily be created for this type, since it
requires duplicating all of `ConvexPolygon::new()`'s verification code.
I may be able to work around this, but it requires touching a bit more
code surface. Opinions?

## Testing

Not much beyond CI! The changes are trivial enough that only a cursory
glance for typos and switched variables should be necessary.

## Note for Reviewers

Hi! I haven't directly used the types I modify in this PR beyond some
benchmarking work I did this morning. If you're familiar with these
types, please let me know if any of the constructors need additional
validation (or if the constructors shouldn't be there at all). Thanks!

---------

Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
2025-01-14 19:38:45 +00:00
Younes
031bb09737
Refactor event system documentation in system_param.rs (#17364)
Just clarify the role of `ParamSet` in this code snippet
2025-01-14 19:38:25 +00:00
robtfm
47d25c13d7
Ambient component (#17343)
# Objective

allow setting ambient light via component on cameras. 
arguably fixes #7193
note i chose to use a component rather than an entity since it was not
clear to me how to manage multiple ambient sources for a single
renderlayer, and it makes for a very small changeset.

## Solution

- make ambient light a component as well as a resource
- extract it
- use the component if present on a camera, fallback to the resource

## Testing

i added 
```rs
        if index == 1 {
            commands.entity(camera).insert(AmbientLight{
                color: Color::linear_rgba(1.0, 0.0, 0.0, 1.0),
                brightness: 1000.0,
                ..Default::default()                
            });
        }
```
at line 84 of the split_screen example

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 08:10:15 +00:00
Ben Whitley
b0beeab41a
Add BRP method to mutate a component (#16940)
# Objective

Add a method to mutate components with BRP.

Currently the only way to modify a component on an entity with BRP is to
insert a new one with the new values. This isn't ideal for several
reasons, one reason being that the client has to know what all the
fields are of the component and stay in sync with the server.

## Solution

Add a new BRP method called `bevy/mutate_component` to mutate a single
field in a component on an entity.

## Testing

Tested on a simple scene on all `Transform`, `Name`, and a custom
component.

---

## Showcase

Example JSON-RPC request to change the `Name` of an entity to "New
name!"

```json
{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "bevy/mutate_component",
    "params": {
        "entity": 4294967308,
        "component": "bevy_ecs::name::Name",
        "path": ".name",
        "value": "New name!"
    }
}
```

Or setting the X translation to 10.0 on a Transform:

```json
{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "bevy/mutate_component",
    "params": {
        "entity": 4294967308,
        "component": "bevy_transform::components::transform::Transform",
        "path": ".translation.x",
        "value": 10.0
    }
}
```

Clip of my Emacs BRP package using this method:


https://github.com/user-attachments/assets/a786b245-5c20-4189-859f-2261c5086a68

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 07:55:40 +00:00
IceSentry
41fd280596
Make InputFocus optional in bevy_winit (#17358)
# Objective

- Stop bevy from crashing when losing window focus

## Solution

- The InputFocus resource is optional but is accessed unconditionally in
bevy_winit. Make it optional.

## Testing

- Ran the window_settings example

## Note

It's possible this might not be a full fix for the issue, but this stop
bevy from crashing.

Closes #16961 
Closes #17227
2025-01-14 05:08:20 +00:00
ickshonpe
0222b35f6d
Diagnostics smoothing factor fix (#17354)
# Objective

Diagnostics is reporting incorrect FPS and frame time.

## Solution

Looks like the smoothing value should be `2 / (history_length + 1)` not
`(history_length + 1) / 2`.

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 01:13:24 +00:00
ickshonpe
b90329aef5
update_text2d_layout creates new font atlases when the primary window is closed (#7849)
# Objective

Necessary conditions:
* Scale factor != 1
* Text is being displayed with Text2d
* The primary window is closed on a frame where the text or text's
bounds are modified.

Then when `update_text2d_layout` runs, it finds no primary window and
assumes a scale factor of 1.
The previous scale_factor was not equal to 1 and the text pipeline's old
font atlases were created for a non-1 scale factor, so it creates new
font atlases even though the app is closing.

The bug was first identified in #6666

## Minimal Example

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

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                present_mode: bevy:🪟:PresentMode::Immediate,
                ..Default::default()
            }),
            ..default()
        }))
        .insert_resource(UiScale { scale: std::f64::consts::PI })
        .add_startup_system(setup)
        .add_system(update)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(Text2dBundle {
        text: Text {
            sections: (0..10).map(|i| TextSection {
                value: i.to_string(),
                style: TextStyle {
                    font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                    font_size: (10 + i) as f32,
                    color: Color::WHITE,
                }
            }).collect(),
            ..Default::default()            
        },
        ..Default::default()
    });
}

fn update(mut text: Query<&mut Text>) {
    for mut text in text.iter_mut() {
        text.set_changed();
    }
}
```
## Output
On closing the window you'll see the warning (if you don't, increase the
number of text sections):
```
WARN bevy_text::glyph_brush: warning[B0005]: Number of font atlases has exceeded the maximum of 16. Performance and memory usage may suffer.
```
The app should only create font atlases on startup, but it doesn't
display this warning until after you close the window

## Solution

Skip `update_text_layout` when there is no primary window.

## Changelog
* If no primary window is found, skip `update_text2d_layout`.
* Added a `Local` flag `skipped` to `update_text2d_layout`. This should
ensure there are no edge cases where text might not get drawn at all.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 01:01:31 +00:00
Alexis "spectria.limina" Horizon
4dfa87798f
Add std derives to SystemParam types (#16785)
# Objective

- Use `Clone` on `SystemParam`, when applicable, in a generic context.

## Solution

-  Add some derives

## Testing

- I ran `cargo test` once.
- I didn't even look at the output.

---------

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 00:30:51 +00:00
Greeble
83b2265673
Fix bevy_time tests occasionally failing on optimised Windows builds (#17349)
# Objective

Fix the `bevy_time` unit tests occasionally failing on optimised Windows
builds.

# Background

I noticed that the `bevy_time` unit tests would fail ~50% of the time
after enabling `opt-level=1` in config.toml, or adding `--release` to
cargo test.

```
> cargo test -p bevy_time --release

thread 'real::test::test_update' panicked at crates\bevy_time\src\real.rs:164:9:
assertion `left != right` failed
  left: Some(Instant { t: 9458.0756664s })
 right: Some(Instant { t: 9458.0756664s })
 ```

Disabling optimisations would fix the issue, as would switching from Windows to Linux.

The failing path is roughly:

```rust
let mut time = Time::<Real>::new(Instant::now());
time.update();
time.update();
assert_ne!(time.last_update(), time.first_update());
```

Which kinda boils down to:

```rust
let left = Instant::now();
let right = Instant::now();
assert_ne!(left, right);
```

So the failure seems legit, since there's no guarantee that `Instant::now()` increases between calls.

I suspect it only triggers with a combination of Windows + fast CPU + optimisations (Windows has a lower resolution clock than Linux/MacOS). That would explain why it doesn't fail on the Bevy Github CI (optimisations disabled, and I'm guessing the runner CPUs are clocked lower).

# Solution

Make sure `Instant::now()` has increased before calling `time.update()`.

I also considered:

1. Change the unit tests to accept `Instant:now()` not increasing.
    - In retrospect this is maybe the better change?
    - There's other unit tests that cover time increasing.
    - Could also add a deterministic test for zero delta updates.
    - I can switch the PR to this if desired.
2. Avoid any paths that hit `Instant::now()` in unit tests.
    - Arguably unit tests should always be deterministic.
    - But that would mean a bunch of paths aren't tested.

## Testing

`cargo test -p bevy_time --release`

## System Info

`os: "Windows 10 Pro", kernel: "19045", cpu: "AMD Ryzen 9 7900 12-Core Processor", core_count: "12", memory: "63.2 GiB"`

Also tested on same computer with Linux pop-os 6.9.3.

Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-14 00:30:07 +00:00
Patrick Walton
141b7673ab
Key render phases off the main world view entity, not the render world view entity. (#16942)
We won't be able to retain render phases from frame to frame if the keys
are unstable. It's not as simple as simply keying off the main world
entity, however, because some main world entities extract to multiple
render world entities. For example, directional lights extract to
multiple shadow cascades, and point lights extract to one view per
cubemap face. Therefore, we key off a new type, `RetainedViewEntity`,
which contains the main entity plus a *subview ID*.

This is part of the preparation for retained bins.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2025-01-12 20:24:17 +00:00
Rob Parrett
f0047899d7
Allow users to customize history length in FrameTimeDiagnosticsPlugin (#17259)
# Objective

I have an application where I'd like to measure average frame rate over
the entire life of the application, and it would be handy if I could
just configure this on the existing `FrameTimeDiagnosticsPlugin`.

Probably fixes #10948?

## Solution

Add `max_history_length` to `FrameTimeDiagnosticsPlugin`, and because
`smoothing_factor` seems to be based on history length, add that too.

## Discussion

I'm not totally sure that `DEFAULT_MAX_HISTORY_LENGTH` is a great
default for `FrameTimeDiagnosticsPlugin` (or any diagnostic?). That's
1/3 of a second at typical game frame rates. Moreover, the default print
interval for `LogDiagnosticsPlugin` is 1 second. So when the two are
combined, you are printing the average over the last third of the
duration between now and the previous print, which seems a bit wonky.
(related: #11429)

I'm pretty sure this default value discussed and the current value
wasn't totally arbitrary though.

Maybe it would be nice for `Diagnostic` to have a
`with_max_history_length_and_also_calculate_a_good_default_smoothing_factor`
method? And then make an explicit smoothing factor in
`FrameTimeDiagnosticsPlugin` optional?

Or add a `new(max_history_length: usize)` method to
`FrameTimeDiagnosticsPlugin` that sets a reasonable default
`smoothing_factor`? edit: This one seems like a no-brainer, doing it.

## Alternatives

It's really easy to roll your own `FrameTimeDiagnosticsPlugin`, but that
might not be super interoperable with, for example, third party FPS
overlays. Still, might be the right call.

## Testing

`cargo run --example many_sprites` (modified to use a custom
`max_history_length`)

## Migration Guide

`FrameTimeDiagnosticsPlugin` now contains two fields. Use
`FrameTimeDiagnosticsPlugin::default()` to match Bevy's previous
behavior or, for example, `FrameTimeDiagnosticsPlugin::new(60)` to
configure it.
2025-01-12 18:18:14 +00:00
JMS55
bb0a82b9a7
Higher quality bicubic lightmap sampling (#16740)
# Objective
- Closes https://github.com/bevyengine/bevy/issues/14322.

## Solution
- Implement fast 4-sample bicubic filtering based on this shader toy
https://www.shadertoy.com/view/4df3Dn, with a small speedup from a ghost
of tushima presentation.

## Testing

- Did you test these changes? If so, how?
  - Ran on lightmapped example. Practically no difference in that scene.
- Are there any parts that need more testing?
  - Lightmapping a better scene.

## Changelog
- Lightmaps now have a higher quality bicubic sampling method (off by
default).

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
2025-01-12 05:40:30 +00:00
AlephCubed
e808fbe987
Renamed members of ParamWarnPolicy to reflect new behaviour. (#17311)
- `Once` renamed to `Warn`.
- `param_warn_once()` renamed to `warn_param_missing()`.
- `never_param_warn()` renamed to `ignore_param_missing()`.

Also includes changes to the documentation of the above methods.

Fixes #17262.

## Migration Guide
- `ParamWarnPolicy::Once` has been renamed to `ParamWarnPolicy::Warn`.
- `ParamWarnPolicy::param_warn_once` has been renamed to
`ParamWarnPolicy::warn_param_missing`.
- `ParamWarnPolicy::never_param_warn` has been renamed to
`ParamWarnPolicy::ignore_param_missing`.
2025-01-12 05:40:04 +00:00
SpecificProtagonist
f5d38f30cc
Fix entity does not exist message on index reuse (#17264)
# Objective

With the `track_location` feature, the error message of trying to
acquire an entity that was despawned pointed to the wrong line if the
entity index has been reused.

## Showcase

```rust
use bevy_ecs::prelude::*;

fn main() {
    let mut world = World::new();
    let e = world.spawn_empty().id();
    world.despawn(e);
    world.flush();
    let _ = world.spawn_empty();
    world.entity(e);
}
```
Old message:
```
Entity 0v1 was despawned by src/main.rs:8:19
```
New message:
```
Entity 0v1 does not exist (its index has been reused)
```
2025-01-12 05:39:54 +00:00
Antony
02bb151889
Rename PickingBehavior to Pickable (#17266)
# Objective

PR #17225 allowed for sprite picking to be opt-in. After some
discussion, it was agreed that `PickingBehavior` should be used to
opt-in to sprite picking behavior for entities. This leads to
`PickingBehavior` having two purposes: mark an entity for use in a
backend, and describe how it should be picked. Discussion led to the
name `Pickable`making more sense (also: this is what the component was
named before upstreaming).

A follow-up pass will be made after this PR to unify backends.

## Solution

Replace all instances of `PickingBehavior` and `picking_behavior` with
`Pickable` and `pickable`, respectively.

## Testing

CI

## Migration Guide

Change all instances of `PickingBehavior` to `Pickable`.
2025-01-12 05:36:52 +00:00
ickshonpe
8ac1f8ccdc
Rename UI camera_entity fields (#17243)
# Objective

The `camera_entity` field on the extracted uinode structs holds the
render world entity that has the extracted camera components
corresponding to the target camera world entity. It should be renamed so
that it's clear it isn't the target camera world entity itself.

## Solution

Rename the `camera_entity` field on each of the extracted UI item
structs to `extracted_camera_entity`.
2025-01-12 05:32:08 +00:00
MichiRecRoom
447108b2a4
Downgrade clippy::allow_attributes and clippy::allow_attributes_without_reason to warn (#17320)
# Objective
I realized that setting these to `deny` may have been a little
aggressive - especially since we upgrade warnings to denies in CI.

## Solution
Downgrades these lints to `warn`, so that compiles can work locally. CI
will still treat these as denies.
2025-01-12 05:28:26 +00:00
MichiRecRoom
62a3077061
bevy_picking: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17302)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_picking` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_picking` was run,
and no errors were encountered.
2025-01-12 01:27:11 +00:00
MichiRecRoom
39a514637d
bevy_remote: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17303)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_remote` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_remote` was run, and
no errors were encountered.
2025-01-12 01:26:59 +00:00
MichiRecRoom
900509bec0
bevy_utils: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17305)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_utils` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_utils` was run, and
no errors were encountered.
2025-01-12 01:26:44 +00:00
MichiRecRoom
db4c6c3be7
bevy_internal: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17306)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_internal` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_internal` was run,
and no errors were encountered.
2025-01-12 01:26:23 +00:00
AlephCubed
6063887be2
Feature gate bevy_reflect in bevy_image. (#17313)
Fixes #17294.
2025-01-12 01:24:34 +00:00
Rob Parrett
5c0e13f29b
Fix text alignment for unbounded text (#17270)
# Objective

Fixes #16783

## Solution

Works around a `cosmic-text` bug or limitation by triggering a re-layout
with the calculated width from the first layout run. See linked issue.

Credit to @ickshonpe for the clever solution.

## Performance

This has a significant performance impact only on unbounded text that
are not `JustifyText::Left`, which is still a bit of a bummer because
text2d performance in 0.15.1 is already not great. But this seems better
than alignment not working.

||many_text2d nfc re|many_text2d nfc re center|
|-|-|-|
|unbounded-layout-no-fix|3.06|3.10|
|unbounded-layout-fix|3.05  -0.2%|2.71 🟥 -12.5%|

## Testing

I added a centered text to the `text2d` example.

`cargo run --example text2d`

We should look at other text examples and stress tests. I haven't tested
as thoroughly as I would like, so help testing that this doesn't break
something in UI would be appreciated.
2025-01-11 05:45:32 +00:00
MichiRecRoom
bab5a1026c
bevy_image: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17289)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_image` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_image` was run, and no errors were
encountered.

I could not run the above command with `--all-features` due to some
compilation errors with `bevy_core_pipeline` and `bevy_math` - but
hopefully CI catches anything I missed.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-11 04:11:07 +00:00
Zachary Harrold
14aeaa3c06
Improve Compiler Errors for bevy_tasks (#17296)
# Objective

- Fixes #17287

## Solution

- Added a dummy `LocalExecutor` (un)implementation to suppress
irrelevant errors.
- Added explicit `compiler_error!` when _not_ selecting either the
`async_executor` or `edge_executor` features

## Testing

- CI
2025-01-11 02:35:09 +00:00
MichiRecRoom
fa64e0f28d
bevy_image now enables reflection on bevy_math (#17293)
# Objective
`bevy_image` appears to expect `bevy_math` to have reflection enabled.
If you attempt to build `bevy_image` without another dependency enabling
the `bevy_math/bevy_reflect` feature, then `bevy_image` will fail to
compile.

## Solution
Ideally, `bevy_image` would feature-gate all of its reflection behind a
new feature. However, for the sake of getting compilation fixed
immediately, I'm opting to specify the `bevy_math/bevy_reflect` feature
in `bevy_image`'s `Cargo.toml`.

Perhaps an upcoming PR can remove the forced `bevy_math/bevy_reflect`
feature, in favor of feature-gating `bevy_image`'s reflecton.

## Testing
`cargo clippy --package bevy_image` was ran, and no longer returns the
compilation errors that it did before.
2025-01-10 23:51:51 +00:00
Rob Parrett
b77e3ef33a
Fix a few typos (#17292)
# Objective

Stumbled upon a `from <-> form` transposition while reviewing a PR,
thought it was interesting, and went down a bit of a rabbit hole.

## Solution

Fix em
2025-01-10 22:48:30 +00:00
Matty Weatherley
a5279d340d
Make bevy_remote feature enable serialize feature (#17260)
# Objective

`bevy_remote`'s reflection deserialization basically requires
`ReflectDeserialize` registrations in order to work correctly. In the
context of `bevy` (the library), this means that using `bevy_remote`
without using the `serialize` feature is a footgun, since
`#[reflect(Serialize)]` etc. are gated behind this feature.

The goal of this PR is to avoid this mistake by default.

## Solution

Make the `bevy_remote` feature enable the `serialize` feature, so that
it works as expected.

---

## Migration Guide

The `bevy_remote` feature of `bevy` now enables the `serialize` feature
automatically. If you wish to use `bevy_remote` without enabling the
`serialize` feature for Bevy subcrates, you must import `bevy_remote` on
its own.
2025-01-10 20:31:41 +00:00
Benjamin Brienen
454dd27922
Add documentation to DynamicStorageBuffer to clarify purpose (#17228)
# Objective

Fixes #15052

## Solution

Add sentence from @JMS55

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2025-01-10 19:47:53 +00:00
MichiRecRoom
081fe4f7ee
bevy_state: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17288)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_state` in line with the new restrictions.

## Testing
Rust-analyzer did not return any errors once the deny was added.
2025-01-10 19:44:49 +00:00
MichiRecRoom
6650931adf
bevy_scene: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17278)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_scene` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_scene` was run, and
no errors were encountered.
2025-01-10 19:40:19 +00:00
MichiRecRoom
df38d1a907
bevy_pbr: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17277)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_pbr` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_pbr` was run, and no errors were
encountered.
2025-01-10 19:40:07 +00:00
MichiRecRoom
8a82a0c83e
bevy_gltf: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17280)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gltf` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_gltf` was run, and
no errors were encountered.
2025-01-10 19:39:21 +00:00
MichiRecRoom
fec382d2b8
bevy_text: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17285)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_text` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_text` was run, and
no errors were encountered.
2025-01-10 19:38:12 +00:00
MichiRecRoom
b617ec0e5c
bevy_transform: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17284)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_transform` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_transform` was run,
and no errors were encountered.
2025-01-10 19:38:05 +00:00
MichiRecRoom
4340533538
bevy_hierarchy: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17286)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_hierarchy` in line with the new restrictions.

## Testing
Rust-analyzer did not discern any errors.
2025-01-10 19:37:58 +00:00
MichiRecRoom
f1dcd701bd
bevy_gizmos: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17281)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gizmos` in line with the new restrictions.

## Testing
`cargo clippy --tests --all-features --package bevy_gizmos` was run, and
no errors were encountered.
2025-01-10 19:36:10 +00:00
Rob Parrett
ec795a20a3
Minor TextPipeline cleanup (#17274)
# Objective

Both `set_metrics` and `set_size` **can** trigger text re-layout and
re-shaping, if the values provided are different form what is already in
the `Buffer`.

## Solution

Combine the `set_metrics` and `set_size` calls.

This might be a small optimization in some situations, maybe when both
font size and text bounds change in the same frame, or when spawning new
text.

I did measure a ~500 microsecond improvement in `text_system` for
`many_buttons --respawn`, but that may have just been noise.
2025-01-10 06:56:36 +00:00
Carter Anderson
4bca7f1b6d
Improved Command Errors (#17215)
# Objective

Rework / build on #17043 to simplify the implementation. #17043 should
be merged first, and the diff from this PR will get much nicer after it
is merged (this PR is net negative LOC).

## Solution

1. Command and EntityCommand have been vastly simplified. No more marker
components. Just one function.
2. Command and EntityCommand are now generic on the return type. This
enables result-less commands to exist, and allows us to statically
distinguish between fallible and infallible commands, which allows us to
skip the "error handling overhead" for cases that don't need it.
3. There are now only two command queue variants: `queue` and
`queue_fallible`. `queue` accepts commands with no return type.
`queue_fallible` accepts commands that return a Result (specifically,
one that returns an error that can convert to
`bevy_ecs::result::Error`).
4. I've added the concept of the "default error handler", which is used
by `queue_fallible`. This is a simple direct call to the `panic()` error
handler by default. Users that want to override this can enable the
`configurable_error_handler` cargo feature, then initialize the
GLOBAL_ERROR_HANDLER value on startup. This is behind a flag because
there might be minor overhead with `OnceLock` and I'm guessing this will
be a niche feature. We can also do perf testing with OnceLock if someone
really wants it to be used unconditionally, but I don't personally feel
the need to do that.
5. I removed the "temporary error handler" on Commands (and all code
associated with it). It added more branching, made Commands bigger /
more expensive to initialize (note that we construct it at high
frequencies / treat it like a pointer type), made the code harder to
follow, and introduced a bunch of additional functions. We instead rely
on the new default error handler used in `queue_fallible` for most
things. In the event that a custom handler is required,
`handle_error_with` can be used.
6. EntityCommand now _only_ supports functions that take
`EntityWorldMut` (and all existing entity commands have been ported).
Removing the marker component from EntityCommand hinged on this change,
but I strongly believe this is for the best anyway, as this sets the
stage for more efficient batched entity commands.
7. I added `EntityWorldMut::resource` and the other variants for more
ergonomic resource access on `EntityWorldMut` (removes the need for
entity.world_scope, which also incurs entity-lookup overhead).

## Open Questions

1. I believe we could merge `queue` and `queue_fallible` into a single
`queue` which accepts both fallible and infallible commands (via the
introduction of a `QueueCommand` trait). Is this desirable?
2025-01-10 04:15:50 +00:00
Alice Cecile
145f5f4394
Add a simple directional UI navigation example (#17224)
# Objective

Gamepad / directional navigation needs an example, for both teaching and
testing purposes.

## Solution

- Add a simple grid-based example.
- Fix an intermittent panic caused by a race condition with bevy_a11y
- Clean up small issues noticed in bevy_input_focus


![image](https://github.com/user-attachments/assets/3a924255-0cd6-44a5-9bb7-b2c400a22d7e)

## To do: this PR

- [x] figure out why "enter" isn't doing anything
- [x] change button color on interaction rather than printing
- [x] add on-screen directions
- [x] move to an asymmetric grid to catch bugs
- [x] ~~fix colors not resetting on button press~~ lol this is mostly
just a problem with hacking `Interaction` for this
- [x] swap to using observers + bubbling, rather than `Interaction`

## To do: future work

- when I increase the button size, such that there is no line break, the
text on the buttons is no longer centered :( EDIT: this is
https://github.com/bevyengine/bevy/issues/16783
- add gamepad stick navigation
- add tools to find the nearest populated quadrant to make diagonal
inputs work
- add a `add_edges` method to `DirectionalNavigationMap`
- add a `add_grid` method to `DirectionalNavigationMap`
- make the example's layout more complex and realistic
- add tools to automatically generate this list
- add button shake on failed navigation rather than printing an error
- make Pressed events easier to mock: default fields, PointerId::Focus

## Testing

`cargo run --example directional_navigation`

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-09 21:15:28 +00:00
Antony
0a9740c18f
Make sprite picking opt-in (#17225)
# Objective

Fixes #16903.

## Solution

- Make sprite picking opt-in by requiring a new `SpritePickingCamera`
component for cameras and usage of a new `Pickable` component for
entities.
- Update the `sprite_picking` example to reflect these changes.
- Some reflection cleanup (I hope that's ok).

## Testing

Ran the `sprite_picking` example

## Open Questions

<del>
   <ul>
    <li>Is the name `SpritePickable` appropriate?</li>
    <li>Should `SpritePickable` be in `bevy_sprite::prelude?</li>
  </ul> 
</del>

## Migration Guide

The sprite picking backend is now strictly opt-in using the
`SpritePickingCamera` and `Pickable` components. You should add the
`Pickable` component any entities that you want sprite picking to be
enabled for, and mark their respective cameras with
`SpritePickingCamera`.
2025-01-09 18:11:44 +00:00
mgi388
b20e23dd41
Add compile-time dyn compatible checks for DynEq, DynHash (#17254)
# Objective

- Shrink `bevy_utils` more.
- Refs #11478

## Solution

- Removes `assert_object_safe` from `bevy_utils` by using a compile time
check instead.

## Testing

- CI.

---

## Migration Guide

`assert_object_safe` is no longer exported by `bevy_utils`. Instead, you
can write a compile time check that your trait is "dyn compatible":

```rust
/// Assert MyTrait is dyn compatible
const _: Option<Box<dyn MyTrait>> = None;
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-09 07:30:54 +00:00
MichiRecRoom
3742e621ef
Allow clippy::too_many_arguments to lint without warnings (#17249)
# Objective
Many instances of `clippy::too_many_arguments` linting happen to be on
systems - functions which we don't call manually, and thus there's not
much reason to worry about the argument count.

## Solution
Allow `clippy::too_many_arguments` globally, and remove all lint
attributes related to it.
2025-01-09 07:26:15 +00:00
DaoLendaye
7b56a1aa98
If there is no movement, DragStart is not triggered. (#17233)
# Objective

Fixed the issue where DragStart was triggered even when there was no
movement
https://github.com/bevyengine/bevy/issues/17230

## Solution

- When position delta is zero, don't trigger DragStart events, DragStart
is not triggered, so DragEnd is not triggered either. Everything is
fine.

## Testing

- tested with the code from the issue

---

## Migration Guide

> Fix the missing part of Drag
https://github.com/bevyengine/bevy/pull/16950
2025-01-09 07:17:56 +00:00
MichiRecRoom
9f1b8b4769
bevy_time: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17210)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_time` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
`cargo clippy`, `cargo clippy --package bevy_time` and `cargo test
--package bevy_time` were run, and no errors were encountered.
2025-01-09 06:29:42 +00:00
MichiRecRoom
e0d3270c06
bevy_mesh: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17218)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_mesh` in line with the new restrictions.

## Testing
`cargo clippy --tests` and `cargo test --package bevy_mesh` were run,
and no errors were encountered.
2025-01-09 06:29:36 +00:00
MichiRecRoom
2403487239
bevy_winit: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17232)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_winit` in line with the new restrictions.

## Testing
`cargo clippy --tests` was run, and no errors were encountered.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-09 06:29:29 +00:00
ickshonpe
532bb15489
extract_shadows responsive coords fix (#17236)
# Objective

`extract_shadows` uses the render world entity corresponding to the
extracted camera when it queries the main world for the camera to get
the viewport size for the responsive viewport coords resolution and
fails. This means that viewport coords get resolved based on a viewport
size of zero.

## Solution

Use the main world camera entity.
2025-01-09 06:29:09 +00:00
AlephCubed
3ce8b284d5
Added docs about MinimalPlugins looping as fast as possible. (#17241)
This also includes suggestions and an example on how to limit the loop
speed.
Fixes #17147.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-01-09 06:28:06 +00:00
MichiRecRoom
00e82496d4
bevy_log: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17246)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_log` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_log` was run, and no errors were
encountered.
2025-01-09 06:26:04 +00:00
MichiRecRoom
53077b9316
bevy_gilrs: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17245)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_gilrs` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_gilrs` was run, and no errors were
encountered.
2025-01-09 06:25:45 +00:00
MichiRecRoom
8e51b326b5
Cleanup instances of #[allow(clippy::type_complexity)] (#17248)
# Objective
I never realized `clippy::type_complexity` was an allowed lint - I've
been assuming it'd generate a warning when performing my linting PRs.

## Solution
Removes any instances of `#[allow(clippy::type_complexity)]` and
`#[expect(clippy::type_complexity)]`

## Testing
`cargo clippy` ran without errors or warnings.
2025-01-09 06:25:20 +00:00
MichiRecRoom
71cd5f813e
Fix up the reason given for a couple of too_many_arguments lints (#17251)
# Objective
In my crusade to give every lint attribute a reason, it appears I got
too complacent and copy-pasted this expect onto non-system functions.

## Solution
Fix up the reason on those non-system functions

## Testing
N/A
2025-01-09 02:39:10 +00:00
MichiRecRoom
789c5e31fa
bevy_input: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17242)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_input` in line with the new restrictions.

## Testing
`cargo clippy --tests --package bevy_input` was run, and no errors were
encountered.
2025-01-08 20:42:50 +00:00
MichiRecRoom
8b4c25ad5f
bevy_ui: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17229)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_ui` in line with the new restrictions.

## Testing
`cargo clippy --tests` and `cargo test --package bevy_ui` were run, and
no errors were encountered.
2025-01-08 19:30:19 +00:00
Jakob Wolf
5f0674f6c3
Allow tuple structs in animated_field! macro (#17234)
# Objective

Allow tuple structs in the animated_field macro.
-  for example `animated_field!(MyTupleStruct::0)`.

Fixes #16736 
- This issue was partially fixed in #16747, where support for tuple
structs was added to `AnimatedField::new_unchecked`.

## Solution

Change the designator for `$field` in the macro from `ident` to `tt`.

## Testing

Expanded the doc test on `animated_field!` to include an example with a
tuple struct.
2025-01-08 19:04:32 +00:00
ickshonpe
e896c364dc
Rename DefaultCameraView (#17235)
# Objective

The name `DefaultCameraView` is confusing and misleading:
* It isn't the default UI camera, which is either the camera with the
`IsDefaultUiCamera` marker component or, if no such camera is found, the
camera with the highest order which has the primary window as its render
target.
* It doesn't make sense to call it a "default", every active 2d and 3d
camera is given its own `DefaultCameraView`.
* The name doesn't make it clear that it's UI specific component.

## Solution

Rename `DefaultCameraView` to `UiCameraView`, add a doc comment for it
and rename a few other fields and variables.

## Migration Guide

`DefaultCameraView` has been renamed to `UiCameraView`
2025-01-08 18:44:11 +00:00
BD103
020d082617
Fix "Unrecognized Option" error when using Criterion-specific arguments in benchmarks (#17222)
# Objective

- Commands like `cargo bench -- --save-baseline before` do not work
because the default `libtest` is intercepting Criterion-specific CLI
arguments.
- Fixes #17200.

## Solution

- Disable the default `libtest` benchmark harness for the library crate,
as per [the Criterion
book](https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options).

## Testing

- `cargo bench -p benches -- --save-baseline before`
- You don't need to run the entire benchmarks, just make sure that they
start without any errors. :)
2025-01-08 00:09:31 +00:00
Zachary Harrold
d60764908c
Update downcast-rs to version 2 (#17223)
# Objective & Solution

- Update `downcast-rs` to the latest version, 2.
- Disable (new) `sync` feature to improve compatibility with atomically
challenged platforms.
- Remove stub `downcast-rs` alternative code from `bevy_app`

## Testing

- CI

## Notes

The only change from version 1 to version 2 is the addition of a new
`sync` feature, which allows disabling the `DowncastSync` parts of
`downcast-rs`, which require access to `alloc::sync::Arc`, which is not
available on atomically challenged platforms. Since Bevy makes no use of
the functionality provided by the `sync` feature, I've disabled it in
all crates. Further details can be found
[here](https://github.com/marcianx/downcast-rs/pull/22).
2025-01-07 21:33:40 +00:00
MichiRecRoom
8031d8431b
bevy_window: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17213)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_window` in line with the new restrictions.

## Testing
`cargo clippy --tests` was run, and no errors were encountered.
2025-01-07 18:47:10 +00:00
MichiRecRoom
3aa89e15eb
bevy_ptr: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17214)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_ptr` in line with the new restrictions.

## Testing
`cargo clippy --tests` was run, and no errors were encountered.

I was expecting this crate to give more of a fight.
2025-01-07 18:46:53 +00:00
Antony
a2ae7e9a19
Remove temporary iOS workaround (#17217)
# Objective

Fixes #16928.

## Solution

Remove the temporary workaround introduced in #16548.
2025-01-07 18:44:32 +00:00
mgi388
e24ae6cf40
Move TextureAtlas and friends into bevy_image (#17219)
# Objective

- Allow other crates to use `TextureAtlas` and friends without needing
to depend on `bevy_sprite`.
- Specifically, this allows adding `TextureAtlas` support to custom
cursors in https://github.com/bevyengine/bevy/pull/17121 by allowing
`bevy_winit` to depend on `bevy_image` instead of `bevy_sprite` which is
a [non-starter].

[non-starter]:
https://github.com/bevyengine/bevy/pull/17121#discussion_r1904955083

## Solution

- Move `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`,
`TextureAtlasLayout` and `DynamicTextureAtlasBuilder` into `bevy_image`.
- Add a new plugin to `bevy_image` named `TextureAtlasPlugin` which
allows us to register `TextureAtlas` and `TextureAtlasLayout` which was
previously done in `SpritePlugin`. Since `SpritePlugin` did the
registration previously, we just need to make it add
`TextureAtlasPlugin`.

## Testing

- CI builds it.
- I also ran multiple examples which hopefully covered any issues:

```
$ cargo run --example sprite
$ cargo run --example text
$ cargo run --example ui_texture_atlas
$ cargo run --example sprite_animation
$ cargo run --example sprite_sheet
$ cargo run --example sprite_picking
```

---

## Migration Guide

The following types have been moved from `bevy_sprite` to `bevy_image`:
`TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`,
`TextureAtlasLayout` and `DynamicTextureAtlasBuilder`.

If you are using the `bevy` crate, and were importing these types
directly (e.g. before `use bevy::sprite::TextureAtlas`), be sure to
update your import paths (e.g. after `use bevy::image::TextureAtlas`)

If you are using the `bevy` prelude to import these types (e.g. `use
bevy::prelude::*`), you don't need to change anything.

If you are using the `bevy_sprite` subcrate, be sure to add `bevy_image`
as a dependency if you do not already have it, and be sure to update
your import paths.
2025-01-07 18:43:11 +00:00
Antony
3578f9e4d0
Reflect bevy_input_focus (#17212)
# Objective

Fixes #17099.

## Solution

Derive, register, and feature flag.

## Testing

Ran CI.
2025-01-07 18:16:46 +00:00
JaySpruce
ee4414159b
Add Result handling to Commands and EntityCommands (#17043)
## Objective

Fixes #2004
Fixes #3845
Fixes #7118
Fixes #10166

## Solution

- The crux of this PR is the new `Command::with_error_handling` method.
This wraps the relevant command in another command that, when applied,
will apply the original command and handle any resulting errors.
- To enable this, `Command::apply` and `EntityCommand::apply` now return
`Result`.
- `Command::with_error_handling` takes as a parameter an error handler
of the form `fn(&mut World, CommandError)`, which it passes the error
to.
- `CommandError` is an enum that can be either `NoSuchEntity(Entity)` or
`CommandFailed(Box<dyn Error>)`.

### Closures
- Closure commands can now optionally return `Result`, which will be
passed to `with_error_handling`.

### Commands
- Fallible commands can be queued with `Commands::queue_fallible` and
`Commands::queue_fallible_with`, which call `with_error_handling` before
queuing them (using `Commands::queue` will queue them without error
handling).
- `Commands::queue_fallible_with` takes an `error_handler` parameter,
which will be used by `with_error_handling` instead of a command's
default.
- The `command` submodule provides unqueued forms of built-in fallible
commands so that you can use them with `queue_fallible_with`.
- There is also an `error_handler` submodule that provides simple error
handlers for convenience.

### Entity Commands
- `EntityCommand` now automatically checks if the entity exists before
executing the command, and returns `NoSuchEntity` if it doesn't.
- Since all entity commands might need to return an error, they are
always queued with error handling.
- `EntityCommands::queue_with` takes an `error_handler` parameter, which
will be used by `with_error_handling` instead of a command's default.
- The `entity_command` submodule provides unqueued forms of built-in
entity commands so that you can use them with `queue_with`.

### Defaults
- In the future, commands should all fail according to the global error
handling setting. That doesn't exist yet though.
- For this PR, commands all fail the way they do on `main`.
- Both now and in the future, the defaults can be overridden by
`Commands::override_error_handler` (or equivalent methods on
`EntityCommands` and `EntityEntryCommands`).
- `override_error_handler` takes an error handler (`fn(&mut World,
CommandError)`) and passes it to every subsequent command queued with
`Commands::queue_fallible` or `EntityCommands::queue`.
- The `_with` variants of the queue methods will still provide an error
handler directly to the command.
- An override can be reset with `reset_error_handler`.

## Future Work

- After a universal error handling mode is added, we can change all
commands to fail that way by default.
- Once we have all commands failing the same way (which would require
either the full removal of `try` variants or just making them useless
while they're deprecated), `queue_fallible_with_default` could be
removed, since its only purpose is to enable commands having different
defaults.
2025-01-07 16:50:52 +00:00
Sean Kim
5faff84c10
Upstream DebugPickingPlugin from bevy_mod_picking (#17177)
# Objective

The debug features (`DebugPickingPlugin`) from `bevy_mod_picking` were
not upstreamed with the rest of the core changes, this PR reintroduces
it for usage inside `bevy_dev_tools`

## Solution

Vast majority of this code is taken as-is from `bevy_mod_picking` aside
from changes to ensure compilation and code style, as such @aevyrie was
added as the co-author for this change.

### Main changes
* `multiselection` support - the relevant code was explicitly not
included in the process of upstreaming the rest of the package, so it
also has been omitted here.
* `bevy_egui` support - the old package had a preference for using
`bevy_egui` instead of `bevy_ui` if possible, I couldn't see a way to
support this in a core crate, so this has been removed.

Relevant code has been added to the `bevy_dev_tools` crate instead of
`bevy_picking` as it is a better fit and requires a dependency on
`bevy_ui` for drawing debug elements.

### Minor changes
* Changed the debug text size from `60` to `12` as the former was so
large as to be unreadable in the new example.

## Testing
* `cargo run -p ci`
* Added a new example in `dev_tools/picking_debug` and visually verified
the in-window results and the console messages

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-07 05:19:50 +00:00
Christian Hughes
d1e5702020
Replace unsafe blocks in World and DeferredWorld with safe equivalents (#17206)
# Objective

Reduce the number of unsafe blocks.

## Solution

Replaced 5 unsafe blocks with safe equivalents.

## Testing

Reusing current tests
2025-01-07 03:21:47 +00:00
François Mockers
b4442bc30e
iOS: can change home indicator / status bar during runtime (#17204)
# Objective

- Followup on
https://github.com/bevyengine/bevy/pull/17179#pullrequestreview-2531852653
- Can show / hide home indicator / status bar during runtime

## Solution

- react on window change

## Testing

- Tested on iOS
2025-01-07 01:07:18 +00:00
AlephCubed
9f18fa695d
Added docs on how Parent component is affected by BuildChildren methods. (#17205)
`BuildChildren` docs didn't specify how the children's `Parent`
components are changed, which is now fixed.
Fixes #16526.
2025-01-07 00:49:50 +00:00
Alex Habich
f26af8f2e8
Remove references to old sample_texture function (#17195)
# Objective

Remove some outdated docs from 0.15 that mention a removed function.

## Solution

In `pbr_functions.wgsl`, I think it's fine to just remove the mention.
In `meshlet/asset.rs`, I think it would be nice to still have a note on
how texture samples should be done. Unfortunately, there isn't a nice
abstraction for it any more. Current workaround, for reference:


b386d08d0f/crates/bevy_pbr/src/render/pbr_fragment.wgsl (L184-L208)

For now, I've just removed the mention.
2025-01-07 00:44:17 +00:00
Eero Lehtinen
7cd1cba765
Add the original source for Oklab conversions (#17199)
# Objective

- Add the original source for Oklab calculations (a blog from the
creator of Oklab) instead of linking to other Rust crates.

## Solution

- Update the links.
2025-01-07 00:41:33 +00:00
Rob Parrett
f896ad8457
Add builder method for TextFont::line_height (#17203)
# Objective

Followup from #16614

`TextFont` has builder methods for its other fields. Add
`with_line_height` for consistency.

## Solution

Add it
2025-01-07 00:40:00 +00:00
Wei Xu
fbc55b84e2
Update winit_runner to use spawn_app for wasm32 target (#16630)
# Objective

- Fixes #12562
- Fixes #12195

## Solution

- Use `spawn_app` instead of `run_app` for web platform in
`winit_runner` as suggested in the
[document](https://docs.rs/winit/latest/winit/platform/web/trait.EventLoopExtWebSys.html#tymethod.spawn_app)

## Testing

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

Tested on web. Created a react app which renders the bevy WASM app and
returns the disposer to JS. Js will call the disposer on component
unmount to stop the app, the disposer sends a signal to a `signal`
receiver in rust which exits the app like this:

```rust
fn handle_stop_signal(
    signal: NonSendMut<StopSignalReceiver>,
    window_entities: Query<(Entity, &Window)>,
    mut event_writer: EventWriter<WindowCloseRequested>,
) {
    if let Ok(_) = signal.try_recv() {
        for (entity, _window) in window_entities.iter() {
            info!("closing window entity: {:x}", entity.to_bits());
            event_writer.send(WindowCloseRequested { window: entity });
        }
    }
}
```


- Are there any parts that need more testing?

  - No

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

- Are all resources released after stopping the app like this? The WASM
is still loaded, the LogPlugin complains on the logger
re-initialization, but it's a warning anyway.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

- Tested the WASM version on web platform and the native version on
MacOS.

---------

Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
2025-01-06 23:21:24 +00:00
Cyborus04
4ba09f3dd9
add line height to TextFont (#16614)
# Objective

- Allow users to customize the line height of text.
- Implements #16085

## Solution

- Add a `line_height` field to `TextFont` to feed into `cosmic_text`'s
`Metrics`.

## Testing

- Tested on my own game, and worked exactly as I wanted.
- My game is only 2D, so I only tested `Text2d`. `Text` still needs
tested, but I imagine it'll work fine.
- An example is available
[here](https://code.cartoon-aa.xyz/Cyborus/custom-line-height-example)

---

## Showcase

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

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


![image](https://github.com/user-attachments/assets/d12d8334-72ae-44b4-9b2e-993bbfd19da6)

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


![image](https://github.com/user-attachments/assets/6bc843b0-b633-4c30-bf77-6bbad774c1e5)

</details>

## Migration Guide

`TextFont` now has a `line_height` field. Any instantiation of
`TextFont` that doesn't have `..default()` will need to add this field.
2025-01-06 23:11:38 +00:00
MichiRecRoom
27802e6975
bevy_render: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17194)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_render` in line with the new restrictions.

## Testing
`cargo clippy` and `cargo test --package bevy_render` were run, and no
errors were encountered.
2025-01-06 23:10:58 +00:00
MichiRecRoom
94596d2bbf
bevy_diagnostic: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17186)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_diagnostic` in line with the new restrictions.

## Testing
`cargo clippy` and `cargo test --package bevy_diagnostic` were run, and
no errors were encountered.
2025-01-06 19:29:59 +00:00
MichiRecRoom
51075aab40
Remove bevy_core_pipeline::core_2d::Camera2dBundle (#17185)
# Objective
https://github.com/bevyengine/bevy/pull/16338 forgot to remove this
previously-deprecated item. In fact, it only removed the `#[deprecated]`
attribute attached to it.

## Solution
Removes `bevy_core_pipeline::core_2d::Camera2dBundle`.

## Testing
CI.
2025-01-06 19:29:14 +00:00
MichiRecRoom
3d797d7513
bevy_sprite: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (Attempt 2) (#17184)
I broke the commit history on the other one,
https://github.com/bevyengine/bevy/pull/17160. Woops.

# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_sprite` in line with the new restrictions.

## Testing
`cargo clippy` and `cargo test --package bevy_sprite` were run, and no
errors were encountered.
2025-01-06 19:26:44 +00:00
MichiRecRoom
b386d08d0f
bevy_asset: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17113)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_asset` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
`cargo clippy` and `cargo test --package bevy_asset --features
multi_threaded` were run, and no errors were encountered.
2025-01-06 19:25:47 +00:00
Christian Hughes
f64f3ac997
Cleanup entity reference types (#17149)
# Objective

Cleanup `EntityRef`, `EntityMut`, and `EntityWorldMut` in preparation
for my "Scoped Entity References" PR.

## Solution

- Switched `EntityRef`/`EntityMut` from tuple structs to normal ones.
- Ensured all conversion trait impls use the same `entity` argument
name.
- Replaced some `unsafe` with delegated calls from `EntityMut` to
`EntityRef`
    - Added `EntityMut::into_readonly` to make the replacements clearer
- Replaced some `unsafe` with delegated calls from `EntityWorldMut` to
`EntityMut` and `EntityRef`
- Added `EntityWorldMut::into_readonly`, `::as_readonly`,
`::into_mutable`, `::as_mutable` to make the replacements clearer

## Testing

Reusing current tests.
2025-01-06 19:25:06 +00:00
ickshonpe
17e3b850bd
Simplified UI tree navigation without ghost_nodes (#17143)
# Objective

There is a large performance regression in the UI systems in 0.15
because the `UiChildren` and `UiRootRootNodes` system params (even with
`ghost_nodes` disabled) are really inefficient compared to regular
queries and can trigger a heap allocation with large numbers of
children.

## Solution

Replace the `UiChildren` and `UiRootRootNodes` system params with
simplified versions when the `ghost_nodes` feature is disabled.

## Testing

yellow this PR, red main

cargo run --example many_buttons --features "trace_tracy" --release

`ui_stack_system`
<img width="494" alt="stack"
src="https://github.com/user-attachments/assets/4a09485f-0ded-4e54-bd47-ffbce869051a"
/>

`ui_layout_system`
<img width="467" alt="unghosted"
src="https://github.com/user-attachments/assets/9d906b20-66b6-4257-9eef-578de1827628"
/>

`update_clipping_system`
<img width="454" alt="clipping"
src="https://github.com/user-attachments/assets/320b50e8-1a1d-423a-95a0-42799ae72fc5"
/>
2025-01-06 19:22:00 +00:00
François Mockers
94b9fe384f
can hide status bar on iOS (#17179)
# Objective

- I want to hide the clock and the battery indicator on iOS

## Solution

- Add the platform specific property `prefers_status_bar_hidden` on
Window creation, and map it to `with_prefers_status_bar_hidden` in
winit.

## Testing

- Tested on iOS
2025-01-06 19:19:56 +00:00
Tim Overbeek
1162e03cec
Make the get function on InstanceInputUniformBuffer less error prone (#17131)
# Objective

the `get` function on [`InstanceInputUniformBuffer`] seems very
error-prone. This PR hopes to fix this.

## Solution

Do a few checks to ensure the index is in bounds and that the `BDI` is
not removed.
Return `Option<BDI>` instead of `BDI`. 

## Testing

- Did you test these changes? If so, how?
added a test to verify that the instance buffer works correctly

## Future Work
Performance decreases when using .binary_search(). However this is
likely due to the fact that [`InstanceInputUniformBuffer::get`] for now
is never used, and only get_unchecked.

## Migration Guide
`InstanceInputUniformBuffer::get` now returns `Option<BDI>` instead of
`BDI` to reduce panics. If you require the old functionality of
`InstanceInputUniformBuffer::get` consider using
`InstanceInputUniformBuffer::get_unchecked`.

---------

Co-authored-by: Tim Overbeek <oorbeck@gmail.com>
2025-01-06 19:15:19 +00:00
ickshonpe
d220eccbb1
More DefaultUiCamera fixes (#17120)
# Objective

Found more excessive `DefaultUiCamera` queries outside of extraction.
The default UI camera lookup only needs to be done once. Do it first,
not per node.

---------

Co-authored-by: MichiRecRoom <1008889+LikeLakers2@users.noreply.github.com>
2025-01-06 19:11:04 +00:00
MichiRecRoom
f61de1101c
bevy_audio: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17119)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
`cargo clippy` and `cargo test --package bevy_audio` were run, and no
errors were encountered.
2025-01-06 19:09:08 +00:00
vil'mo
b30ee2d051
Disallow requesting write resource access in Queries (#17116)
Related to https://github.com/bevyengine/bevy/pull/16843

Since `WorldQuery::Fetch` is `Clone`, it can't store mutable references
to resources, so it doesn't make sense to mutably access resources. In
that sense, it is hard to find usecases of mutably accessing resources
and to clearly define, what mutably accessing resources would mean, so
it's been decided to disallow write resource access.
Also changed documentation of safety requirements of
`WorldQuery::init_fetch` and `WorldQuery::fetch` to clearly state to the
caller, what safety invariants they need to uphold.
2025-01-06 19:04:26 +00:00
arunke
7dd56862a4
Fix duplicate asset loader registration warning (#17105)
# Objective

The original fix (bevyengine/bevy#11870) did not actually implement the
described logic. It checked if there were independently multiple loaders
for a given asset type and multiple loaders for a given extension.
However, this did not handle the case where those loaders were not the
same. For example, there could be a loader for type `Foo` and extension
`.foo`. Anther loader could exist for type `Bar` but extension `.bar`.
If a third loader was added for type `Foo` but extension `.bar`, the
warning would have been incorrectly logged.

## Solution

Instead of independently checking to see if there are preexisting
loaders for both the extension and type, look up the indices of the
loaders for the type in question. Then check to see if the loaders
registered for the extensions has any overlap. Only log if there are
loaders that fit this criteria.

## Testing

Ran CI tests. Locally tested the situation describe in the objective
section for the normal `App::init_asset_loader` flow. I think testing
could be done on the pre-registration flow for loaders still. I tested
on Windows, but the changes should not be affected by platform.
2025-01-06 18:56:05 +00:00
Alice Cecile
aa09b6601d
Add basic directional (gamepad) navigation for UI (and non-UI) (#17102)
# Objective

While directional navigation is helpful for UI in general for
accessibility reasons, it is *especially* valuable for a game engine,
where menus may be navigated primarily or exclusively through the use of
a game controller.

Thumb-stick powered cursor-based navigation can work as a fallback, but
is generally a pretty poor user experience. We can do better!

## Prior art

Within Bevy, https://github.com/nicopap/ui-navigation and
https://github.com/rparrett/bevy-alt-ui-navigation-lite exist to solve
this same problem. This isn't yet a complete replacement for that
ecosystem, but hopefully we'll be there for 0.16.

## Solution

UI navigation is complicated, and the right tradeoffs will vary based on
the project and even the individual scene.

We're starting with something simple and flexible, hooking into the
existing `InputFocus` resource, and storing a manually constructed graph
of entities to explore in a `DirectionalNavigationMap` resource. The
developer experience won't be great (so much wiring to do!), but the
tools are all there for a great user experience.

We could have chosen to represent these linkages via component-flavored
not-quite-relations. This would be useful for inspectors, and would give
us automatic cleanup when the entities were despawned, but seriously
complicates the developer experience when building and checking this
API. For now, we're doing a dumb "entity graph in a resource" thing and
`remove` helpers. Once relations are added, we can re-evaluate.

I've decided to use a `CompassOctant` as our key for the possible paths.
This should give users a reasonable amount of precise control without
being fiddly, and playing reasonably nicely with arrow-key navigation.
This design lets us store the set of entities that we're connected to as
a 8-byte array (yay Entity-niching). In theory, this is maybe nicer than
the double indirection of two hashmaps. but if this ends up being slow
we should create benchmarks.

To make this work more pleasant, I've added a few utilities to the
`CompassOctant` type: converting to and from usize, and adding a helper
to find the 180 degrees opposite direction. These have been mirrored
onto `CompassQuadrant` for consistency: they should be generally useful
for game logic.

## Future work

This is a relatively complex initiative! In the hopes of easing review
and avoiding merge conflicts, I've opted to split this work into
bite-sized chunks.

Before 0.16, I'd like to have:

- An example demonstrating gamepad and tab-based navigation in a
realistic game menu
- Helpers to convert axis-based inputs into compass quadrants / octants
- Tools to check the listed graph desiderata
- A helper to build a graph from a grid of entities
- A tool to automatically build a graph given a supplied UI layout

One day, it would be sweet if:

- We had an example demonstrating how to use focus navigation in a
non-UI scene to cycle between game objects
- Standard actions for tab-style and directional navigation with a
first-party bevy_actions integration
- We had a visual debugging tool to display these navigation graphs for
QC purposes
- There was a built-in way to go "up a level" by cancelling the current
action
- The navigation graph is built completely out of relations

## Testing

- tests for the new `CompassQuadrant` / `CompassOctant` methods
- tests for the new directional navigation module

---------

Co-authored-by: Rob Parrett <robparrett@gmail.com>
2025-01-06 18:51:44 +00:00
ickshonpe
b4b47d695b
default UI camera extraction fix (#17100)
# Objective

In UI extraction the default UI camera is queried for every UI node. It
only needs to be retrieved once.

## Solution

Query for the default UI camera once before iterating the UI nodes.

```
cargo run --example many_buttons --release --features "trace_tracy"
```
<img width="631" alt="default-camera-extract"
src="https://github.com/user-attachments/assets/db712bce-6a0b-49a7-8e20-654baf588390"
/>

`extract_uinode_background_colors` yellow is this PR, red is main.
2025-01-06 18:49:18 +00:00
Aevyrie
13deb3ed76
Anamorphic Bloom (#17096)
https://github.com/user-attachments/assets/e2de3d20-4246-4eba-a0a7-8469a468dddb

The _JJ Abrahams_


https://github.com/user-attachments/assets/2dce3df9-665b-46ff-b687-e7cb54364f30

The _Cyberfunk 2025_

<img width="1392" alt="image"
src="https://github.com/user-attachments/assets/0179df38-ea2e-4f34-bbd3-d3240f0d0a4f"
/>

# Objective

- Add the ability to scale bloom for artistic control, and to mimic
anamorphic blurs.

## Solution

- Add a scale factor in bloom settings, and plumb this to the shader.

## Testing

- Added runtime-tweak-able setting to the `bloom_3d`/`bloom_2d ` example

---

## Showcase


![image](https://github.com/user-attachments/assets/bb44dae4-52bb-4981-a77f-aaa1ec83f5d6)

- Added `scale` parameter to `Bloom` to improve artistic control and
enable anamorphic bloom.
2025-01-06 18:43:21 +00:00
Nándor Szalma
7f74e3c2f9
Fix depth_bias and build errors on less capable platforms (#17079)
# Objective

- I'm compiling (parts of) bevy for an embedded platform with no 64bit
atomic and ctrlc handler support. Some compilation errors came up. This
PR contains the fixes for those.
- Fix depth_bias casting in PBR material (Fixes #14169)
  - Negative depth_bias values were casted to 0 before this PR
  - f32::INFINITY depth_bias value was casted to -1 before this PR

## Solutions

- Restrict 64bit atomic reflection to supported platforms
- Restrict ctrlc handler to supported platforms (linux, windows or macos
instead of "not wasm")
- The depth bias value (f32) is first casted to i32 then u64 in order to
preserve negative values

## Testing
- This version compiles on a platform with no 64bit atomic support, and
no ctrlc support
- CtrlC handler still works on Linux and Windows (I can't test on Macos)
- depth_bias:
```rust
println!("{}",f32::INFINITY as u64 as i32); // Prints: -1 (old implementation)
println!("{}",f32::INFINITY as i32 as u64 as i32); // Prints: 2147483647 (expected, new implementation)
```
Also ran a modified version of 3d_scene example with the following
results:

RED cube depth_bias: -1000.0
BLUE cube depth_bias: 0.0

![image](https://github.com/user-attachments/assets/d5a96759-dd3c-4a0a-97ff-821163873a0d)

RED cube depth_bias: -INF
BLUE cube depth_bias: 0.0

![image](https://github.com/user-attachments/assets/e4de22b4-0c31-4dea-8be1-12b700e440b9)

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

![image](https://github.com/user-attachments/assets/52d9348f-df27-468f-a001-2d3d3ff6b553)
2025-01-06 18:39:08 +00:00
Patrick Walton
a8f15bd95e
Introduce two-level bins for multidrawable meshes. (#16898)
Currently, our batchable binned items are stored in a hash table that
maps bin key, which includes the batch set key, to a list of entities.
Multidraw is handled by sorting the bin keys and accumulating adjacent
bins that can be multidrawn together (i.e. have the same batch set key)
into multidraw commands during `batch_and_prepare_binned_render_phase`.

This is reasonably efficient right now, but it will complicate future
work to retain indirect draw parameters from frame to frame. Consider
what must happen when we have retained indirect draw parameters and the
application adds a bin (i.e. a new mesh) that shares a batch set key
with some pre-existing meshes. (That is, the new mesh can be multidrawn
with the pre-existing meshes.) To be maximally efficient, our goal in
that scenario will be to update *only* the indirect draw parameters for
the batch set (i.e. multidraw command) containing the mesh that was
added, while leaving the others alone. That means that we have to
quickly locate all the bins that belong to the batch set being modified.

In the existing code, we would have to sort the list of bin keys so that
bins that can be multidrawn together become adjacent to one another in
the list. Then we would have to do a binary search through the sorted
list to find the location of the bin that was just added. Next, we would
have to widen our search to adjacent indexes that contain the same batch
set, doing expensive comparisons against the batch set key every time.
Finally, we would reallocate the indirect draw parameters and update the
stored pointers to the indirect draw parameters that the bins store.

By contrast, it'd be dramatically simpler if we simply changed the way
bins are stored to first map from batch set key (i.e. multidraw command)
to the bins (i.e. meshes) within that batch set key, and then from each
individual bin to the mesh instances. That way, the scenario above in
which we add a new mesh will be simpler to handle. First, we will look
up the batch set key corresponding to that mesh in the outer map to find
an inner map corresponding to the single multidraw command that will
draw that batch set. We will know how many meshes the multidraw command
is going to draw by the size of that inner map. Then we simply need to
reallocate the indirect draw parameters and update the pointers to those
parameters within the bins as necessary. There will be no need to do any
binary search or expensive batch set key comparison: only a single hash
lookup and an iteration over the inner map to update the pointers.

This patch implements the above technique. Because we don't have
retained bins yet, this PR provides no performance benefits. However, it
opens the door to maximally efficient updates when only a small number
of meshes change from frame to frame.

The main churn that this patch causes is that the *batch set key* (which
uniquely specifies a multidraw command) and *bin key* (which uniquely
specifies a mesh *within* that multidraw command) are now separate,
instead of the batch set key being embedded *within* the bin key.

In order to isolate potential regressions, I think that at least #16890,
#16836, and #16825 should land before this PR does.

## Migration Guide

* The *batch set key* is now separate from the *bin key* in
`BinnedPhaseItem`. The batch set key is used to collect multidrawable
meshes together. If you aren't using the multidraw feature, you can
safely set the batch set key to `()`.
2025-01-06 18:34:40 +00:00
MichiRecRoom
21c1b6a1e8
Update all previously-merged #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] attributes to include a reason field pointing to the tracking issue (#17136)
# Objective
Ensure the deny lint attributes added as a result of #17111 point to the
tracking issue.

## Solution
Change all existing instances of:
```rust
#![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)]
```
to
```rust
#![deny(
    clippy::allow_attributes,
    clippy::allow_attributes_without_reason,
    reason = "See #17111; To be removed once all crates are in-line with these attributes"
)]
```

## Testing
N/A
2025-01-06 05:40:08 +00:00
github-actions[bot]
573b980685
Bump Version after Release (#17176)
Bump version after release
This PR has been auto-generated

---------

Co-authored-by: Bevy Auto Releaser <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2025-01-06 00:04:44 +00:00
Zachary Harrold
a371ee3019
Remove tracing re-export from bevy_utils (#17161)
# Objective

- Contributes to #11478

## Solution

- Made `bevy_utils::tracing` `doc(hidden)`
- Re-exported `tracing` from `bevy_log` for end-users
- Added `tracing` directly to crates that need it.

## Testing

- CI

---

## Migration Guide

If you were importing `tracing` via `bevy::utils::tracing`, instead use
`bevy::log::tracing`. Note that many items within `tracing` are also
directly re-exported from `bevy::log` as well, so you may only need
`bevy::log` for the most common items (e.g., `warn!`, `trace!`, etc.).
This also applies to the `log_once!` family of macros.

## Notes

- While this doesn't reduce the line-count in `bevy_utils`, it further
decouples the internal crates from `bevy_utils`, making its eventual
removal more feasible in the future.
- I have just imported `tracing` as we do for all dependencies. However,
a workspace dependency may be more appropriate for version management.
2025-01-05 23:06:34 +00:00
Patrick Walton
0e36abc180
Disable bindless on a per-material basis if the specific material uses more samplers than are available on the device. (#17155)
Some hardware and driver combos, such as Intel Iris Xe, have low limits
on the numbers of samplers per shader, causing an overflow. With
first-class bindless arrays, `wgpu` should be able to work around this
limitation eventually, but for now we need to disable bindless materials
on those platforms.

This is an alternative to PR #17107 that calculates the precise number
of samplers needed and compares to the hardware sampler limit,
transparently falling back to non-bindless if the limit is exceeded.

Fixes #16988.
2025-01-05 20:36:39 +00:00
Zachary Harrold
3c829d7f68
Remove everything except Instant from bevy_utils::time (#17158)
# Objective

- Contributes to #11478
- Contributes to #16877

## Solution

- Removed everything except `Instant` from `bevy_utils::time`

## Testing

- CI

---

## Migration Guide

If you relied on any of the following from `bevy_utils::time`:

- `Duration`
- `TryFromFloatSecsError`

Import these directly from `core::time` regardless of platform target
(WASM, mobile, etc.)

If you relied on any of the following from `bevy_utils::time`:

- `SystemTime`
- `SystemTimeError`

Instead import these directly from either `std::time` or `web_time` as
appropriate for your target platform.

## Notes

`Duration` and `TryFromFloatSecsError` are both re-exports from
`core::time` regardless of whether they are used from `web_time` or
`std::time`, so there is no value gained from re-exporting them from
`bevy_utils::time` as well. As for `SystemTime` and `SystemTimeError`,
no Bevy internal crates or examples rely on these types. Since Bevy
doesn't have a `Time<Wall>` resource for interacting with wall-time (and
likely shouldn't need one), I think removing these from `bevy_utils`
entirely and waiting for a use-case to justify inclusion is a reasonable
path forward.
2025-01-05 20:36:08 +00:00
ickshonpe
49aae89049
unmut extracted view queries (#17142)
# Objective

Noticed a lot of the extracted view queries are unnecessarily mutable.
Fixed them.
2025-01-05 20:34:11 +00:00
Benjamin Brienen
7112d5594e
Remove all deprecated code (#16338)
# Objective

Release cycle things

## Solution

Delete items deprecated in 0.15 and migrate bevy itself.

## Testing

CI
2025-01-05 20:33:39 +00:00
MichiRecRoom
1e03f2a7c1
bevy_dev_tools: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17159)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
`cargo clippy`, `cargo clippy --package bevy_dev_tools` and cargo test
--package bevy_dev_tools` were run, and no errors were encountered.
(Except for one warning from bevy_sprite, but I plan to fix that when I
get to bevy_sprite)
2025-01-05 20:32:15 +00:00
Rob Parrett
8898c9e142
Use radsort for sprite picking (#17174)
# Objective

Optimization for sprite picking

## Solution

Use `radsort` for the sort.

We already have `radsort` in tree for sorting various phase items
(including `Transparent2d` / sprites). It's a stable parallel radix
sort.

## Testing

Tested on an M1 Max.

`cargo run --example sprite_picking`

`cargo run --example bevymark --release --features=trace,trace_tracy --
--waves 100 --per-wave 1000 --benchmark`

<img width="983" alt="image"
src="https://github.com/user-attachments/assets/0f7a8c3a-006b-4323-a2ed-03788918dffa"
/>
2025-01-05 20:28:11 +00:00
MichiRecRoom
5f5876b1c9
Change bevy_reflect::RegisterForReflection::__register() to expect unused variables, rather than putting underscores on the parameter names (#17171)
# Objective
While checking over https://github.com/bevyengine/bevy/pull/17160, it
occurred to me that rust-analyzer will copy the method signature
exactly, when using tab completion trait methods. This includes provided
trait methods that use underscores to silence the `unused_variables`
lint. This probably isn't good for users, seeing as how they'll have to
remove the underscore if they want to use the parameters.

(I mean, they technically don't have to remove the underscore... but
usually you don't keep a leading underscore on parameters you're using.)

## Solution
Changes `bevy_reflect::RegisterForReflection::__register()` to
`#[expect(unused_variables)]`, and removes the underscores from its
parameter names.

## Testing
N/A
2025-01-05 20:27:20 +00:00
Sean Kim
f90a41ff72
Update GetPath unit test and documentation for empty path usecase (#17150)
# Objective

- `GetPath` `path` related methods allow an empty string as the
parameter, but this is not included as a test or in documentation. This
PR adds both.
- Fixes #13459

## Solution

- Updates the `bevy_reflect` `GetPath` documentation and unit tests

## Testing

- `cargo run -p ci`
2025-01-05 02:45:26 +00:00
AlephCubed
cf6c65522f
Derived Default for all public unit components. (#17139)
Derived `Default` for all public unit structs that already derive from
`Component`. This allows them to be used more easily as required
components.
To avoid clutter in tests/examples, only public components were
affected, but this could easily be expanded to affect all unit
components.

Fixes #17052.
2025-01-05 02:45:09 +00:00
ickshonpe
9ed76b7a56
More combinator cleanup (#17148)
# Objective

Cleanup some more awkward combinator chains.
2025-01-05 02:44:29 +00:00
JMS55
fe58993577
METIS-based meshlet generation (#16947)
# Objective
Improve DAG building for virtual geometry

## Solution

- Use METIS to group triangles into meshlets which lets us minimize
locked vertices which improves simplification, instead of using meshopt
which prioritizes culling efficiency. Also some other minor tweaks.
- Currently most meshlets have 126 triangles, and not 128. Fixing this
might involve calling METIS recursively ourselves to manually bisect the
graph, not sure. Not going to attempt to fix this in this PR.

## Testing

- Did you test these changes? If so, how?
  - Tested on bunny.glb and cliff.glb
- Are there any parts that need more testing?
  - No
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Download the new bunny asset, run the meshlet example.

---

## Showcase

New 

![image](https://github.com/user-attachments/assets/68f5d2f0-a4ca-41e1-90d5-35a2c6969c21)

Old

![image](https://github.com/user-attachments/assets/a3d97a09-773d-44b2-9990-25e1f6b51ec9)

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2025-01-05 02:03:26 +00:00
Sean Kim
c87ec09674
Fix 2D Gizmos not always drawn on top (#17085)
# Objective

- As stated in the linked issue, if a Mesh2D is drawn with elements with
a positive Z value, resulting gizmos get drawn behind instead of in
front of them.
- Fixes #17053

## Solution

- Similar to the change done for the `SpritePipeline` in the relevant
commit (5abc32ceda), this PR changes both
line gizmos to avoid writing to the depth buffer and always pass the
depth test to ensure they are not filtered out.

## Testing

- Tested with the provided snippet in #17053 
- I looked over the `2d_gizmos` example, but it seemed like adding more
elements there to demonstrate this might not be the best idea? Looking
for guidance here on if that should be updated or if a new gizmo example
needs to be made.
2025-01-05 02:02:30 +00:00
MichiRecRoom
5b0406c722
bevy_color: Apply #![deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17090)
# Objective
- https://github.com/bevyengine/bevy/issues/17111

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_audio` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-05 02:01:20 +00:00
JaySpruce
4fde223831
Optimize Entities::entity_does_not_exist_error_details_message, remove UnsafeWorldCell from error (#17115)
## Objective

The error `EntityFetchError::NoSuchEntity` has an `UnsafeWorldCell`
inside it, which it uses to call
`Entities::entity_does_not_exist_error_details_message` when being
printed. That method returns a `String` that, if the `track_location`
feature is enabled, contains the location of whoever despawned the
relevant entity.

I initially had to modify this error while working on #17043. The
`UnsafeWorldCell` was causing borrow problems when being returned from a
command, so I tried replacing it with the `String` that the method
returns, since that was the world cell's only purpose.

Unfortunately, `String`s are slow, and it significantly impacted
performance (on top of that PR's performance hit):
<details>
<summary>17043 benchmarks</summary>

### With `String`

![error_handling_insert_slow](https://github.com/user-attachments/assets/5629ba6d-69fc-4c16-84c9-8be7e449232d)

### No `String`

![error_handling_insert_fixed](https://github.com/user-attachments/assets/6393e2d6-e61a-4558-8ff1-471ff8356c1c)

</details>

For that PR, I just removed the error details entirely, but I figured
I'd try to find a way to keep them around.

## Solution

- Replace the `String` with a helper struct that holds the location, and
only turn it into a string when someone actually wants to print it.
- Replace the `UnsafeWorldCell` with the aforementioned struct.
- Do the same for `QueryEntityError::NoSuchEntity`.

## Benchmarking

This had some interesting performance impact:

<details>
<summary>This PR vs main</summary>


![dne_rework_1](https://github.com/user-attachments/assets/05bf91b4-dddc-4d76-b2c4-41c9d25c7a57)

![dne_rework_2](https://github.com/user-attachments/assets/34aa76b2-d8a7-41e0-9670-c213207e457d)

![dne_rework_3](https://github.com/user-attachments/assets/8b9bd4e4-77c8-45a7-b058-dc0dfd3dd323)

</details>

## Other work

`QueryEntityError::QueryDoesNotMatch` also has an `UnsafeWorldCell`
inside it. This one would be more complicated to rework while keeping
the same functionality.

## Migration Guide

The errors `EntityFetchError::NoSuchEntity` and
`QueryEntityError::NoSuchEntity` now contain an
`EntityDoesNotExistDetails` struct instead of an `UnsafeWorldCell`. If
you were just printing these, they should work identically.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-05 02:01:01 +00:00
Rob Parrett
859c2d77f9
Revert "Fix sprite performance regression since retained render world (#17078)" (#17123)
# Objective

Fixes #17098

It seems that it's not totally obvious how to fix this, but that
reverting might be part of the solution anyway.

Let's get the repo back into a working state.

## Solution

Revert the [recent
optimization](https://github.com/bevyengine/bevy/pull/17078) that broke
"many-to-one main->render world entities" for 2d.

## Testing

`cargo run --example text2d`
`cargo run --example sprite_slice`
2025-01-04 00:22:18 +00:00
Benjamin Brienen
43db44ca3a
Scale input to account for deadzones (#17015)
# Objective

Fixes #3450 

## Solution

Scale the input to account for the range

## Testing

Updated unit tests

## Migration Guide

`GamepadButtonChangedEvent.value` is now linearly rescaled to be from
`0.0..=1.0` (instead of `low..=high`) and
`GamepadAxisChangedEvent.value` is now linearly rescaled to be from
`-1.0..=0.0`/`0.0..=1.0` (accounting for the deadzone).
2025-01-03 22:27:59 +00:00
MichiRecRoom
120b733ab5
bevy_reflect: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17092)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_reflect` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-03 22:22:34 +00:00
MichiRecRoom
66a0e74a21
Truncate the floats in bevy_color::oklaba (#17109)
# Objective
Remove the reliance on `#[allow(clippy::excessive_precision)]`.

## Solution
Remove the `#[allow(clippy::excessive_precision)]`, and truncate the
float literals to the value rustc would normally truncate them to.

## Testing
I ran `cargo test -p bevy_color`, and received no errors.
2025-01-03 22:20:51 +00:00
Rob Parrett
651b22f31f
Update typos (#17126)
# Objective

Use the latest version of `typos` and fix the typos that it now detects

# Additional Info

By the way, `typos` has a "low priority typo suggestions issue" where we
can throw typos we find that `typos` doesn't catch.

(This link may go stale) https://github.com/crate-ci/typos/issues/1200
2025-01-03 17:44:26 +00:00
Zachary Harrold
0403948aa2
Remove Implicit std Prelude from no_std Crates (#17086)
# Background

In `no_std` compatible crates, there is often an `std` feature which
will allow access to the standard library. Currently, with the `std`
feature _enabled_, the
[`std::prelude`](https://doc.rust-lang.org/std/prelude/index.html) is
implicitly imported in all modules. With the feature _disabled_, instead
the [`core::prelude`](https://doc.rust-lang.org/core/prelude/index.html)
is implicitly imported. This creates a subtle and pervasive issue where
`alloc` items _may_ be implicitly included (if `std` is enabled), or
must be explicitly included (if `std` is not enabled).

# Objective

- Make the implicit imports for `no_std` crates consistent regardless of
what features are/not enabled.

## Solution

- Replace the `cfg_attr` "double negative" `no_std` attribute with
conditional compilation to _include_ `std` as an external crate.
```rust
// Before
#![cfg_attr(not(feature = "std"), no_std)]

// After
#![no_std]

#[cfg(feature = "std")]
extern crate std;
```
- Fix imports that are currently broken but are only now visible with
the above fix.

## Testing

- CI

## Notes

I had previously used the "double negative" version of `no_std` based on
general consensus that it was "cleaner" within the Rust embedded
community. However, this implicit prelude issue likely was considered
when forming this consensus. I believe the reason why is the items most
affected by this issue are provided by the `alloc` crate, which is
rarely used within embedded but extensively used within Bevy.
2025-01-03 01:58:43 +00:00
MichiRecRoom
5a5ddb9e35
bevy_tasks: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17089)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_tasks` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-02 22:42:25 +00:00
arunke
22bf3b9a62
Fix documentation for system set method (#17106)
# Objective

Fix incorrect comment on `IntoSystemSetConfigs::after` likely caused by
copy-paste error. It said "before" instead of "after".

## Solution

Update the comment to the correct text.

## Testing

CI tests pass. This is just updating a comment.
2025-01-02 22:38:26 +00:00
MichiRecRoom
e2248afb3e
bevy_math: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17091)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_math` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.

---------

Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
2025-01-02 18:47:36 +00:00
MichiRecRoom
00533a6d1c
bevy_a11y: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17093)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_a11y` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-02 18:45:19 +00:00
MichiRecRoom
c9109964e7
bevy_animation: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17094)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_animation` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-02 18:45:05 +00:00
MichiRecRoom
5d00ef4237
bevy_app: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17095)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_reflect` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-02 18:44:34 +00:00
ickshonpe
1a18c9f87b
UI Debug Overlay show_hidden and show_clipped options (#17097)
# Objective

The UI debug overlay draws an outline for every UI node even if it is
invisible or clipped.
Disable debug outlines for hidden and clipped nodes by default and add
options to renable them if needed.

## Solution

* Add `show_hidden` and `show_clipped` fields to `UiDebugOptions`:
```rust
    /// Show outlines for non-visible UI nodes
    pub show_hidden: bool,
    /// Show outlines for clipped sections of UI nodes
    pub show_clipped: bool,
```

* Only extract debug outlines for hidden and clipped UI nodes if the
respective field in `UiDebugOptions` is set to `true`.

## Testing

Also added some extra features to the `testbed_ui` example that
demonstrate the new options:

cargo run --example testbed_ui --features "bevy_ui_debug"

<img width="641" alt="show-hidden-and-clipped"
src="https://github.com/user-attachments/assets/16a68600-170c-469e-a3c7-f7dae411dc40"
/>
2025-01-02 18:43:14 +00:00
ickshonpe
2931e350b6
reduce nesting in the sparse_set module (#17066)
# Objective

Just being fussy but I hate this `.map(|v|
v.is_some()).unwrap_or(false)` stuff.

## Solution
Reduce it using `and_then`.

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2025-01-01 23:17:11 +00:00
Tristan Murphy
afed4e27d1
small documentation update and issue template fix (#17054)
# Objective
Fix some outdated `bevy_state` documentation examples.

## Solution
- updated some doc examples in `bevy_state` that hadn't been updated
with the API.
- fixed an outdated link in the documentation issue template that
referred to a 404 page instead of the contribution guide.

## Testing
No necessary testing aside from the usual doctests.

---

## Showcase
N/A

## Migration Guide
N/A

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-01 23:09:17 +00:00
Zachary Harrold
10e113d641
Add no_std support to bevy_window (#17031)
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `bevy_reflect` was previously always enabled, which isn't how most
other crates handle reflection. I've brought this in line with how most
crates gate `bevy_reflect`. This is where the majority of the changes
come from in this PR.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-01 23:05:25 +00:00
Benjamin Brienen
4058bfa47c
Fix clippy::precedence (#17080)
# Objective

Nightly clippy warnings

## Solution

Add parens

## Testing

```
PS C:\Users\BenjaminBrienen\source\bevy> cargo +nightly clippy
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.44s
```
2025-01-01 22:11:22 +00:00
Aevyrie
bed9ddf3ce
Refactor and simplify custom projections (#17063)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/16556
- Closes https://github.com/bevyengine/bevy/issues/11807

## Solution

- Simplify custom projections by using a single source of truth -
`Projection`, removing all existing generic systems and types.
- Existing perspective and orthographic structs are no longer components
- I could dissolve these to simplify further, but keeping them around
was the fast way to implement this.
- Instead of generics, introduce a third variant, with a trait object.
- Do an object safety dance with an intermediate trait to allow cloning
boxed camera projections. This is a normal rust polymorphism papercut.
You can do this with a crate but a manual impl is short and sweet.

## Testing

- Added a custom projection example

---

## Showcase

- Custom projections and projection handling has been simplified.
- Projection systems are no longer generic, with the potential for many
different projection components on the same camera.
- Instead `Projection` is now the single source of truth for camera
projections, and is the only projection component.
- Custom projections are still supported, and can be constructed with
`Projection::custom()`.

## Migration Guide

- `PerspectiveProjection` and `OrthographicProjection` are no longer
components. Use `Projection` instead.
- Custom projections should no longer be inserted as a component.
Instead, simply set the custom projection as a value of `Projection`
with `Projection::custom()`.
2025-01-01 20:44:24 +00:00
Sean Kim
294e0db719
Rename track_change_detection flag to track_location (#17075)
# Objective

- As stated in the related issue, this PR is to better align the feature
flag name with what it actually does and the plans for the future.
- Fixes #16852 

## Solution

- Simple find / replace

## Testing

- Local run of `cargo run -p ci`

## Migration Guide

The `track_change_detection` feature flag has been renamed to
`track_location` to better reflect its extended capabilities.
2025-01-01 18:43:47 +00:00
Robert Swain
fd330c834f
Fix sprite performance regression since retained render world (#17078)
# Objective

- Fix sprite rendering performance regression since retained render
world changes
- The retained render world changes moved `ExtractedSprites` from using
the highly-optimised `EntityHasher` with an `Entity` to using
`FixedHasher` with `(Entity, MainEntity)`. This was enough to regress
framerate in bevymark by 25%.

## Solution

- Move the render world entity into a member of `ExtractedSprite` and
change `ExtractedSprites` to use `MainEntityHashMap` for its storage
- Disable sprite picking in bevymark

## Testing

M4 Max. `bevymark --waves 100 --per-wave 1000 --benchmark`. main in
yellow vs PR in red:

<img width="590" alt="Screenshot 2025-01-01 at 16 36 22"
src="https://github.com/user-attachments/assets/1e4ed6ec-3811-4abf-8b30-336153737f89"
/>

20.2% median frame time reduction.

<img width="594" alt="Screenshot 2025-01-01 at 16 38 37"
src="https://github.com/user-attachments/assets/157c2022-cda6-4cf2-bc63-d0bc40528cf0"
/>

49.7% median extract_sprites execution time reduction.

Comparing 0.14.2 yellow vs PR red:
<img width="593" alt="Screenshot 2025-01-01 at 16 40 06"
src="https://github.com/user-attachments/assets/abd59b6f-290a-4eb6-8835-ed110af995f3"
/>

~6.1% median frame time reduction.

---

## Migration Guide

- `ExtractedSprites` is now using `MainEntityHashMap` for storage, which
is keyed on `MainEntity`.
- The render world entity corresponding to an `ExtractedSprite` is now
stored in the `render_entity` member of it.
2025-01-01 18:40:11 +00:00
ickshonpe
0141bd01b3
Remove the atlas_scaling field from ExtractedUiItem::Gylphs. (#17047)
# Objective

Remove the `atlas_scaling` field from `ExtractedUiItem::Gylphs`. 

It's only ever set to `Vec2::ONE`. I don't remember why/if this field
was ever needed, maybe it was useful before the scale factor clean up.

## Migration Guide

The `atlas_scaling` field from `ExtractedUiItem::Gylphs` has been
removed. This shouldn't affect any existing code as it wasn't used for
anything.
2025-01-01 04:06:53 +00:00
Alice Cecile
5f1e762f19
Return Result from tab navigation API (#17071)
# Objective

Tab navigation can fail in all manner of ways. The current API
recognizes this, but merely logs a warning and returns `None`.

We should supply the actual reason for failure to the caller, so they
can handle it in whatever fashion they please (including logging a
warning!).

Swapping to a Result-oriented pattern is also a bit more idiomatic and
makes the code's control flow easier to follow.

## Solution

- Refactor the `tab_navigation` module to return a `Result` rather than
an `Option` from its key APIs.
- Move the logging to the provided prebuilt observer. This leaves the
default behavior largely unchanged, but allows for better user control.
- Make the case where no tab group was found for the currently focused
entity an error branch, but provide enough information that we can still
recover from it.

## Testing

The `tab_navigation` example continues to function as intended.
2025-01-01 04:05:48 +00:00
ickshonpe
c817864e4f
Replace map_or(true, _) with is_none_or(_) (#17073)
# Objective

Replace uses of `map_or(true, _)` with the equivalent `is_none_or(_)`.
2025-01-01 04:05:26 +00:00
Niklas Eicker
7302e7c9e0
Do not lowercase asset file extensions (#17065)
# Objective

Resolves #17064

## Solution

- Bevy no longer converts asset file extensions to lowercase before
trying to resolve an asset loader

## Testing

- I adapted the `custom_asset` example (see comment in #17064)
- The changes were tested on Linux

As far as I know, Windows has a case-insensitive file system by default,
so case-sensitive asset file extensions are probably bad practice in a
game. But we should be case-sensitive everywhere or handle asset paths
completely case-insensitive.

Before this PR:
* asset loader extensions are case-sensitive
* asset file names are case-sensitive
* asset file extensions are converted to lowercase  

Now everything should be case-sensitive
2025-01-01 00:42:56 +00:00
ickshonpe
9b4e6b345f
Replace map_or(false, _) with is_some_and(_) (#17074)
# Objective

Replace `map_or(false, _)` with `is_some_and(_)`
2024-12-31 21:13:13 +00:00
ickshonpe
7a5a734452
Replace map + unwrap_or(false) with is_some_and (#17067)
# Objective

The `my_option.map(|inner| inner.is_whatever).unwrap_or(false)` pattern
is fragile and ugly.

Replace it with `is_some_and` everywhere.
2024-12-31 20:28:02 +00:00
ickshonpe
c73daea341
Replace map + unwrap_or(true) with is_none_or (#17070)
# Objective

Reduce all varieties of `my_maybe.map(|x| x.is_true).unwrap_or(true)`
using `is_none_or`.
2024-12-31 20:17:03 +00:00
Alice Cecile
d502796a41
Make the input focus docs less keyboard-centric (#17069)
# Objective

Following #16876, `bevy_input_focus` works with more than just keyboard
inputs! The docs should reflect that.

## Solution

Fix a few missed mentions in the documentation.

Also add a brief reference to navigation frameworks within the module
docs to help give more breadcrumbs.
2024-12-31 18:37:48 +00:00
Jonathan Chan Kwan Yin
3c7fbee2d8
Add Mut::clone_from_if_neq (#17019)
# Objective

- Support more ergonomic conditional updates for types that can be
modified by `clone_into`.

## Solution

- Use `ToOwned::clone_into` to copy a reference provided by the caller
in `Mut::clone_from_if_neq`.

## Testing

- See doc tests.
2024-12-31 16:23:01 +00:00
Benjamin Brienen
c93217b966
Fix compilation error (#17060)
Small follow-up to #17011 

Please don't merge until the CI passes all checks
2024-12-31 16:22:19 +00:00
Aevyrie
63634fd408
Update picking docs (#17057)
More updates to picking docs. Addresses some nits with wording, and
fixes some out of date information.
2024-12-31 01:56:45 +00:00
Aevyrie
f3da36c181
Update picking::events module docs (#17055)
Updates some out of date docs.
2024-12-31 00:46:15 +00:00
Mike
ac43d5c94f
Convert to fallible system in IntoSystemConfigs (#17051)
# Objective

- #16589 added an enum to switch between fallible and infallible system.
This branching should be unnecessary if we wrap infallible systems in a
function to return `Ok(())`.

## Solution

- Create a wrapper system for `System<(), ()>`s that returns `Ok` on the
call to `run` and `run_unsafe`. The wrapper should compile out, but I
haven't checked.
- I removed the `impl IntoSystemConfigs for BoxedSystem<(), ()>` as I
couldn't figure out a way to keep the impl without double boxing.

## Testing

- ran `many_foxes` example to check if it still runs.

## Migration Guide

- `IntoSystemConfigs` has been removed for `BoxedSystem<(), ()>`. Either
use `InfallibleSystemWrapper` before boxing or make your system return
`bevy::ecs::prelude::Result`.
2024-12-31 00:39:29 +00:00
Jer
33afd38ee1
show these 'fully qualified paths' for bevy_remote's rpc (#16944)
# Objective

It is not obvious that one would know these:
```json
{
  "id": 1,
  "jsonrpc": "2.0",
  "result": [
    "bevy_animation::AnimationPlayer",
    "bevy_animation::AnimationTarget",
    "bevy_animation::graph::AnimationGraphHandle",
    "bevy_animation::transition::AnimationTransitions",
    "bevy_audio::audio::PlaybackSettings",
    "bevy_audio::audio::SpatialListener",
    "bevy_core_pipeline::bloom::settings::Bloom",
    "bevy_core_pipeline::contrast_adaptive_sharpening::ContrastAdaptiveSharpening",
   **... snipping for brevity ...**
    "bevy_ui::ui_node::Node",
    "bevy_ui::ui_node::Outline",
    "bevy_ui::ui_node::ScrollPosition",
    "bevy_ui::ui_node::TargetCamera",
    "bevy_ui::ui_node::UiAntiAlias",
    "bevy_ui::ui_node::ZIndex",
    "bevy_ui::widget::button::Button",
    "bevy_window::monitor::Monitor",
    "bevy_window:🪟:PrimaryWindow",
    "bevy_window:🪟:Window",
    "bevy_winit::cursor::CursorIcon",
    "server::Cube"
  ]
}
```
Especially if you for example, are reading the GH examples because:

![image](https://github.com/user-attachments/assets/46c9c983-4bf9-4e70-9d6e-8de936505fbb)
If you for example expand these things, due to the number of places bevy
re-exports things you'll find it difficult to find the true path of
something.
i.e you'd probably be forgiven for writing a query (using the
`client.rs` example):
```sh
$ cargo run --example client --  bevy_pbr::mesh_material::MeshMaterial3d | jq
{
  "error": {
    "code": -23402,
    "message": "Unknown component type: `bevy_pbr::mesh_material::MeshMaterial3d`"
  },
  "id": 1,
  "jsonrpc": "2.0"
}
```
which is where
8d9a00f548/crates/bevy_pbr/src/mesh_material.rs (L41)
would lead you to believe it is...

I've worked with bevy a lot, so it's no issue for me, but for others...
?

## Solution

- Add some more docs, including a sample request (`json` and `rust`)

## Testing

N/A

---

## Showcase
N/A

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2024-12-31 00:29:27 +00:00
Zachary Harrold
3f19997096
Added modify_component to EntityWorldMut, DeferredWorld, and World (#16668)
# Objective

- Make working with immutable components more ergonomic
- Assist #16662

## Solution

Added `modify_component` to `World` and `EntityWorldMut`. This method
"removes" a component from an entity, gives a mutable reference to it to
a provided closure, and then "re-inserts" the component back onto the
entity. This replacement triggers the `OnReplace` and `OnInsert` hooks,
but does _not_ cause an archetype move, as the removal is purely
simulated.

## Testing

- Added doc-tests and a unit test.

---

## Showcase

```rust
use bevy_ecs::prelude::*;

/// An immutable component.
#[derive(Component, PartialEq, Eq, Debug)]
#[component(immutable)]
struct Foo(bool);

let mut world = World::default();

let mut entity = world.spawn(Foo(false));

assert_eq!(entity.get::<Foo>(), Some(&Foo(false)));

// Before the closure is executed, the `OnReplace` hooks/observers are triggered
entity.modify_component(|foo: &mut Foo| {
    foo.0 = true;
});
// After the closure is executed, `OnInsert` hooks/observers are triggered

assert_eq!(entity.get::<Foo>(), Some(&Foo(true)));
```

## Notes

- If the component is not available on the entity, the closure and hooks
aren't executed, and `None` is returned. I chose this as an alternative
to returning an error or panicking, but I'm open to changing that based
on feedback.
- This relies on `unsafe`, in particular for accessing the `Archetype`
to trigger hooks. All the unsafe operations are contained within
`DeferredWorld::modify_component`, and I would appreciate that this
function is given special attention to ensure soundness.
- The `OnAdd` hook can never be triggered by this method, since the
component must already be inserted. I have chosen to not trigger
`OnRemove`, as I believe it makes sense that this method is purely a
replacement operation, not an actual removal/insertion.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Malek <50841145+MalekiRe@users.noreply.github.com>
2024-12-31 00:23:44 +00:00
Benjamin Brienen
4460a4d9ed
Use -D warnings in all relevant CI (#17011)
# Objective

Fixes #17009

See:
https://doc.rust-lang.org/stable/clippy/continuous_integration/index.html

## Solution

Add the env

## Testing

CI should start to fail, then I'll fix it.

## Showcase


![image](https://github.com/user-attachments/assets/acd2888f-9fc0-445a-a96a-842ba9f1c6aa)
2024-12-31 00:15:28 +00:00
Zhixing Zhang
9cebc66486
Make 8 methods public and updated input parameter generics for SystemState::build_system_with_input (#17034)
# Objective

- Made certain methods public for advanced use cases. Methods that
returns mutable references are marked as unsafe due to the possibility
of violating internal lifetime constraint assumptions.
- Fixes an issue introduced by #15184
2024-12-30 23:04:14 +00:00
Zachary Harrold
5f42c9ab6d
Fix no_std CI Warnings and WASM Compatibility (#17049)
# Objective

- Resolve several warnings encountered when compiling for `no_std`
around `dead_code`
- Fix compatibility with `wasm32-unknown-unknown` when using `no_std`
(identified by Sachymetsu on
[Discord](https://discord.com/channels/691052431525675048/692572690833473578/1323365426901549097))

## Solution

- Removed some unused imports
- Added `allow(dead_code)` for certain private items when compiling on
`no_std`
- Fixed `bevy_app` and `bevy_tasks` compatibility with WASM when
compiling without `std` by appropriately importing `Box` and feature
gating panic unwinding

## Testing

- CI
2024-12-30 23:01:27 +00:00
Vic
b78efd339d
Simplify sort/max_by calls (#17048)
# Objective

Some sort calls and `Ord` impls are unnecessarily complex.

## Solution

Rewrite the "match on cmp, if equal do another cmp" as either a
comparison on tuples, or `Ordering::then_with`, depending on whether the
compare keys need construction.

`sort_by` -> `sort_by_key` when symmetrical. Do the same for
`min_by`/`max_by`.

Note that `total_cmp` can only work with `sort_by`, and not on tuples.

When sorting collected query results that contain
`Entity`/`MainEntity`/`RenderEntity` in their `QueryData`, with that
`Entity` in the sort key:
stable -> unstable sort (all queried entities are unique)

If key construction is not simple, switch to `sort_by_cached_key` when
possible.

Sorts that are only performed to discover the maximal element are
replaced by `max_by_key`.

Dedicated comparison functions and structs are removed where simple.

Derive `PartialOrd`/`Ord` when useful.

Misc. closure style inconsistencies.

## Testing
- Existing tests.
2024-12-30 22:59:36 +00:00
ickshonpe
1e9f647b33
prepare_sprite_image_bind_groups refactor (#17045)
# Objective

In `prepare_sprite_image_bind_groups` the `batch_image_changed`
condition is checked twice but the second if-block seems unnecessary.

# Solution

Queue new `SpriteBatch`es inside the first if-block and remove the
second if-block.
2024-12-30 22:54:04 +00:00
ickshonpe
d2f61e24e7
get_glyph_atlas_info refactor (#17044)
# Objective

Return a `GlyphAtlasInfo` instead of a tuple from the inner block so we
can remove the outer mapping.
2024-12-30 21:08:12 +00:00
Zachary Harrold
db5c31e1c4
Add no_std support to bevy_transform (#17030)
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `alloc` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `alloc` feature added to allow using this crate in `no_alloc`
environments.
- `bevy_reflect` was previously always enabled when `bevy-support` was
enabled, which isn't how most other crates handle reflection. I've
brought this in line with how most crates gate `bevy_reflect`.
2024-12-30 21:01:13 +00:00
JaySpruce
9ac7e17f2e
Refactor hierarchy-related commands to remove structs (#17029)
## Objective

Continuation of #16999.

This PR handles the following:
- Many hierarchy-related commands are wrappers around `World` and
`EntityWorldMut` methods and can be moved to closures:
  - `AddChild`
  - `InsertChildren`
  - `AddChildren`
  - `RemoveChildren`
  - `ClearChildren`
  - `ReplaceChildren`
  - `RemoveParent`
  - `DespawnRecursive`
  - `DespawnChildrenRecursive`
  - `AddChildInPlace`
  - `RemoveParentInPlace`
- `SendEvent` is a wrapper around `World` methods and can be moved to a
closure (and its file deleted).

## Migration Guide

If you were queuing the structs of hierarchy-related commands or
`SendEvent` directly, you will need to change them to the methods
implemented on `EntityCommands` (or `Commands` for `SendEvent`):

| Struct | Method |

|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
| `commands.queue(AddChild { child, parent });` |
`commands.entity(parent).add_child(child);` OR
`commands.entity(child).set_parent(parent);` |
| `commands.queue(AddChildren { children, parent });` |
`commands.entity(parent).add_children(children);` |
| `commands.queue(InsertChildren { children, parent });` |
`commands.entity(parent).insert_children(children);` |
| `commands.queue(RemoveChildren { children, parent });` |
`commands.entity(parent).remove_children(children);` |
| `commands.queue(ReplaceChildren { children, parent });` |
`commands.entity(parent).replace_children(children);` |
| `commands.queue(ClearChildren { parent });` |
`commands.entity(parent).clear_children();` |
| `commands.queue(RemoveParent { child });` |
`commands.entity(child).remove_parent()` |
| `commands.queue(DespawnRecursive { entity, warn: true });` |
`commands.entity(entity).despawn_recursive();` |
| `commands.queue(DespawnRecursive { entity, warn: false });` |
`commands.entity(entity).try_despawn_recursive();` |
| `commands.queue(DespawnChildrenRecursive { entity, warn: true });` |
`commands.entity(entity).despawn_descendants();` |
| `commands.queue(DespawnChildrenRecursive { entity, warn: false});` |
`commands.entity(entity).try_despawn_descendants();` |
| `commands.queue(SendEvent { event });` | `commands.send_event(event);`
|
2024-12-30 20:58:03 +00:00
Ethereumdegen
4f9dc6534b
fix visibility propagation during reparenting (#17025)
# Objective
Fixes #17024 

## Solution
 

## Testing
 By adding 

```
if let Some(mut cmd) = commands.get_entity( *equipment_link_node ){
                         cmd.insert(Visibility::Inherited); // a hack for now 
                     }

```
in my build after .set_parent() , this fixes the issue. This is why i
think that this change will fix the issue. Unfortunately i was not able
to test the Changed (parent ) , this actual code change, because no
matter how i 'patch', it breaks my project. I got super close but still
had 23 errors due to Reflect being angry.


---
2024-12-30 20:55:44 +00:00
Brezak
ae16bdf172
Add fallible add methods to PluginGroupBuilder (#17005)
# Objective

Make working with `PluginGroupBuilder` less panicky.
Fixes #17001

## Solution

Expand the `PluginGroupBuilder` api with fallible add methods + a
contains method.
Also reorder the `PluginGroupBuilder` tests because before should come
before after.

## Testing

Ran the `PluginGroupBuilder` tests which call into all the newly added
methods.
2024-12-30 20:14:02 +00:00
Patrick Walton
7767a8d161
Refactor batch_and_prepare_binned_render_phase in preparation for bin retention. (#16922)
This commit makes the following changes:

* `IndirectParametersBuffer` has been changed from a `BufferVec` to a
`RawBufferVec`. This won about 20us or so on Bistro by avoiding `encase`
overhead.

* The methods on the `GetFullBatchData` trait no longer have the
`entity` parameter, as it was unused.

* `PreprocessWorkItem`, which specifies a transform-and-cull operation,
now supplies the mesh instance uniform output index directly instead of
having the shader look it up from the indirect draw parameters.
Accordingly, the responsibility of writing the output index to the
indirect draw parameters has been moved from the CPU to the GPU. This is
in preparation for retained indirect instance draw commands, where the
mesh instance uniform output index may change from frame to frame, while
the indirect instance draw commands will be cached. We won't want the
CPU to have to upload the same indirect draw parameters again and again
if a batch didn't change from frame to frame.

* `batch_and_prepare_binned_render_phase` and
`batch_and_prepare_sorted_render_phase` now allocate indirect draw
commands for an entire batch set at a time when possible, instead of one
batch at a time. This change will allow us to retain the indirect draw
commands for whole batch sets.

* `GetFullBatchData::get_batch_indirect_parameters_index` has been
replaced with `GetFullBatchData::write_batch_indirect_parameters`, which
takes an offset and writes into it instead of allocating. This is
necessary in order to use the optimization mentioned in the previous
point.

* At the WGSL level, `IndirectParameters` has been factored out into
`mesh_preprocess_types.wgsl`. This is because we'll need a new compute
shader that zeroes out the instance counts in preparation for a new
frame. That shader will need to access `IndirectParameters`, so it was
moved to a separate file.

* Bins are no longer raw vectors but are instances of a separate type,
`RenderBin`. This is so that the bin can eventually contain its retained
batches.
2024-12-30 20:11:31 +00:00
Patrick Walton
fde7968168
Unbreak shadows by retaining work item buffers corresponding to ExtractedViews, not ViewTargets. (#17039)
OK, so this is tricky. Every frame, `delete_old_work_item_buffers`
deletes the mesh preprocessing index buffers (a.k.a. work item buffers)
for views that don't have `ViewTarget`s. This was always wrong for
shadow map views, as shadow maps only have `ExtractedView` components,
not `ViewTarget`s. However, before #16836, the problem was masked,
because uploading the mesh preprocessing index buffers for shadow views
had already completed by the time `delete_old_work_item_buffers` ran.
But PR #16836 moved `delete_old_work_item_buffers` from the
`ManageViews` phase to `PrepareResources`, which runs before
`write_batched_instance_buffers` uploads the work item buffers to the
GPU.

This itself isn't wrong, but it exposed the bug, because now it's
possible for work item buffers to get deleted before they're uploaded in
`write_batched_instance_buffers`. This is actually intermittent! It's
possible for the old work item buffers to get deleted, and then
*recreated* in `batch_and_prepare_binned_render_phase`, which runs
during `PrepareResources` as well, and under that system ordering, there
will be no problem other than a little inefficiency arising from
recreating the buffers every frame. But, if
`delete_old_work_item_buffers` runs *after*
`batch_and_prepare_render_phase`, then the work item buffers
corresponding to shadow views will get deleted, and then the shadows
will disappear.

The fact that this is racy is what made it look like #16922 solved the
issue. In fact, it didn't: it just perturbed the ordering on the build
bots enough that the issue stopped appearing. However, on my system, the
shadows still don't appear with #16922.

This commit solves the problem by making `delete_old_work_item_buffers`
look at `ExtractedView`s, not `ViewTarget`s, preventing work item
buffers corresponding to live shadow map views from being deleted.
2024-12-30 20:06:40 +00:00
Benjamin Brienen
0362abd4f4
Make extract_mesh_materials and MaterialBindGroupAllocator public (#16982)
# Objective

Fixes #16730

## Solution

Make the relevant functions public. (`MaterialBindGroupAllocator` itself
was already `pub`)
2024-12-30 05:57:11 +00:00
Brezak
54a3fd7754
Don't overalign aligned values in gpu_readback::align_byte_size (#17007)
# Objective

Fix alignment calculations in our rendering code.
Fixes #16992 

The `gpu_readback::align_byte_size` function incorrectly rounds aligned
values to the next alignment.
If we assume the alignment to be 256 (because that's what wgpu says it
its) the function would align 0 to 256, 256 to 512, etc...

## Solution

Forward the `gpu_readback::align_byte_size` to
`RenderDevice::align_copy_bytes_per_row` so we don't implement the same
method twice.
Simplify `RenderDevice::align_copy_bytes_per_row`.

## Testing

Ran the code provided in #16992 to see if the issue has been solved +
added a test to check if `align_copy_bytes_per_row` returns the correct
values.
2024-12-30 05:51:37 +00:00
Christian Hughes
b09bbfa905
Remove unsound Clone impl for EntityMutExcept (#17032)
# Objective

`EntityMutExcept` can currently be cloned, which can easily violate
aliasing rules.

## Solution

- Remove the `Clone` impl for `EntityMutExcept`
- Also manually derived `Clone` impl for `EntityRefExcept` so that `B:
Clone` isn't required, and also impl'd `Copy`

## Testing

Compile failure tests would be good for this, but I'm not exactly sure
how to set that up.

## Migration Guide

- `EntityMutExcept` can no-longer be cloned, as this violates Rust's
memory safety rules.
2024-12-30 05:17:46 +00:00
Zachary Harrold
79a367db16
Add no_std support to bevy_state (#17028)
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `portable-atomic`
  - `critical-section`

## Testing

- CI

## Notes

- `portable-atomic`, and `critical-section` are shortcuts to enable the
relevant features in dependencies, making the usage of this crate on
atomically challenged platforms possible and simpler.
- This PR is blocked until #17027 is merged (as it depends on fixes for
the `once!` macro). Once merged, the change-count for this PR should
reduce.
2024-12-29 23:28:18 +00:00
Rob Parrett
150eec7535
Fix Text2d performance regression (#16991)
# Objective

Probably fixes #16972

## Solution

With 100k text2d, tracy was showing most time being spent in
`extract_components<bevy_sprite::SpriteSource>`.


![image](https://github.com/user-attachments/assets/e82d5d4e-bb39-4d7e-ab7f-47a5466cb74f)

Browsing Bevy's code, this `SpriteSource` component is seemingly not
even used in the render world. So I just ~~deleted the code that was
extracting it~~ it.

## Testing

`cargo run --example text2d` still seems to work.

The example from [my
comment](https://github.com/bevyengine/bevy/issues/16972#issuecomment-2562680876)
in the linked issue shows a ~50x speedup.
2024-12-29 23:14:33 +00:00
Lyndon-Mackay
1614b213f1
Basic filtering examples for users of the bevy_log. (#16455)
# Objective

Give users a quick example on how to control logging so they can filter
out library logs while reading their own
This is intended to fix issue #15957.

## Solution

Added some examples

## Testing

I created project and tested the examples work

###
This is purely a documentation change.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Andres O. Vela <andresovela@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2024-12-29 22:56:40 +00:00
Zachary Harrold
c8110f5f86
Add portable-atomic support to bevy_utils for once! (#17027)
# Objective

- Improves platform compatibility for `bevy_utils`

## Solution

- Added `portable-atomic` to allow using the `once!` macro on more
platforms (e.g., Raspberry Pi Pico)

## Testing

- CI

## Notes

- This change should be entirely hidden thanks to the use of
`doc(hidden)`. Enabling the new `portable-atomic` feature just allows
using the `once!` macro on platforms which previously could not.
- I took the liberty of updating the feature documentation to be more in
line with how I've documented features in `bevy_ecs`/`bevy_app`/etc. for
their `no_std` updates.
2024-12-29 22:50:08 +00:00
Zachary Harrold
46af46695b
Add no_std support to bevy_input (#16995)
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `smol_str` (default)
  - `portable-atomic`
  - `critical-section`
  - `libm`
- Fixed an existing issue where `bevy_reflect` wasn't properly feature
gated.

## Testing

- CI

## Notes

- There were some minor issues with `bevy_math` and `bevy_ecs` noticed
in this PR which I have also resolved here. I can split these out if
desired, but I've left them here for now as they're very small changes
and I don't consider this PR itself to be very controversial.
- `libm`, `portable-atomic`, and `critical-section` are shortcuts to
enable the relevant features in dependencies, making the usage of this
crate on atomically challenged platforms possible and simpler.
- `smol_str` is gated as it doesn't support atomically challenged
platforms (e.g., Raspberry Pi Pico). I have an issue and a
[PR](https://github.com/rust-analyzer/smol_str/pull/91) to discuss this
upstream.
2024-12-29 22:46:30 +00:00
JaySpruce
0f2b2de333
Move some structs that impl Command to methods on World and EntityWorldMut (#16999)
## Objective

Commands were previously limited to structs that implemented `Command`.
Now there are blanket implementations for closures, which (in my
opinion) are generally preferable.

Internal commands within `commands/mod.rs` have been switched from
structs to closures, but there are a number of internal commands in
other areas of the engine that still use structs. I'd like to tidy these
up by moving their implementations to methods on
`World`/`EntityWorldMut` and changing `Commands` to use those methods
through closures.

This PR handles the following:
- `TriggerEvent` and `EmitDynamicTrigger` double as commands and helper
structs, and can just be moved to `World` methods.
- Four structs that enabled insertion/removal of components via
reflection. This functionality shouldn't be exclusive to commands, and
can be added to `EntityWorldMut`.
- Five structs that mostly just wrapped `World` methods, and can be
replaced with closures that do the same thing.

## Solution

- __Observer Triggers__ (`observer/trigger_event.rs` and
`observer/mod.rs`)
- Moved the internals of `TriggerEvent` to the `World` methods that used
it.
  - Replaced `EmitDynamicTrigger` with two `World` methods:
    - `trigger_targets_dynamic`
    - `trigger_targets_dynamic_ref`
- `TriggerTargets` was now the only thing in
`observer/trigger_event.rs`, so it's been moved to `observer/mod.rs` and
`trigger_event.rs` was deleted.
- __Reflection Insert/Remove__ (`reflect/entity_commands.rs`)
- Replaced the following `Command` impls with equivalent methods on
`EntityWorldMut`:
    - `InsertReflect` -> `insert_reflect`
    - `InsertReflectWithRegistry` -> `insert_reflect_with_registry`
    - `RemoveReflect` -> `remove_reflect`
    - `RemoveReflectWithRegistry` -> `remove_reflect_with_registry`
- __System Registration__ (`system/system_registry.rs`)
- The following `Command` impls just wrapped a `World` method and have
been replaced with closures:
    - `RunSystemWith`
    - `UnregisterSystem`
    - `RunSystemCachedWith`
    - `UnregisterSystemCached`
- `RegisterSystem` called a helper function that basically worked as a
constructor for `RegisteredSystem` and made sure it came with a marker
component. That helper function has been replaced with
`RegisteredSystem::new` and a `#[require]`.

## Possible Addition

The extension trait that adds the reflection commands,
`ReflectCommandExt`, isn't strictly necessary; we could just `impl
EntityCommands`. We could even move them to the same files as the main
impls and put it behind a `#[cfg]`.

The PR that added it [had a similar
conversation](https://github.com/bevyengine/bevy/pull/8895#discussion_r1234713671)
and decided to stick with the trait, but we could revisit it here if so
desired.
2024-12-29 22:18:53 +00:00
Benjamin Brienen
8c34f00deb
Fix msrvs (#17012)
# Objective

The rust-versions are out of date.
Fixes #17008

## Solution

Update the values

Cherry-picked from #17006 in case it is controversial

## Testing

Validated locally and in #17006

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-29 20:00:19 +00:00
Brezak
dc2cd71dc8
Make RawHandleWrapper fields private to save users from themselves (#16968)
# Objective

Fixes #16683

## Solution

Make all fields ine `RawHandleWrapper` private.

## Testing

- CI
- `cargo clippy`
- The lightmaps example
---

## Migration Guide

The `window_handle` and `dispay_handle` fields on `RawHandleWrapper` are
no longer public. Use the newly added getters and setters to manipulate
them instead.
2024-12-29 19:54:57 +00:00