Commit Graph

6619 Commits

Author SHA1 Message Date
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