Commit graph

5970 commits

Author SHA1 Message Date
poopy
3a66d88c83
command based entry api with EntityCommands::entry (#15274)
# Objective

It's convenient to be able to modify a component if it exist, and insert
a default value if it doesn't. You can already do most of this with
`EntityCommands::insert_if_new`, and all of this using a custom command.
However, that does not spark joy in my opinion.

Closes #10669

## Solution

Introduce a new commands type `EntityEntryCommands`, along with a method
to access it, `EntityCommands::entry`.

`EntityEntryCommands` exposes a subset of the entry API (`and_modify`,
`or_insert`, etc), however it's not an enum so it doesn't allow pattern
matching. Also, `or_insert` won't return the component because it's all
based on commands.

## Testing

Added a new test `entity_commands_entry`.

---

## Showcase

```rust
commands
    .entity(player)
    .entry::<Level>()
    .and_modify(|mut lvl| lvl.0 += 1)
    .or_default();
```

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-19 15:20:13 +00:00
Patrick Walton
2ae5a21009
Implement percentage-closer soft shadows (PCSS). (#13497)
[*Percentage-closer soft shadows*] are a technique from 2004 that allow
shadows to become blurrier farther from the objects that cast them. It
works by introducing a *blocker search* step that runs before the normal
shadow map sampling. The blocker search step detects the difference
between the depth of the fragment being rasterized and the depth of the
nearby samples in the depth buffer. Larger depth differences result in a
larger penumbra and therefore a blurrier shadow.

To enable PCSS, fill in the `soft_shadow_size` value in
`DirectionalLight`, `PointLight`, or `SpotLight`, as appropriate. This
shadow size value represents the size of the light and should be tuned
as appropriate for your scene. Higher values result in a wider penumbra
(i.e. blurrier shadows).

When using PCSS, temporal shadow maps
(`ShadowFilteringMethod::Temporal`) are recommended. If you don't use
`ShadowFilteringMethod::Temporal` and instead use
`ShadowFilteringMethod::Gaussian`, Bevy will use the same technique as
`Temporal`, but the result won't vary over time. This produces a rather
noisy result. Doing better would likely require downsampling the shadow
map, which would be complex and slower (and would require PR #13003 to
land first).

In addition to PCSS, this commit makes the near Z plane for the shadow
map configurable on a per-light basis. Previously, it had been hardcoded
to 0.1 meters. This change was necessary to make the point light shadow
map in the example look reasonable, as otherwise the shadows appeared
far too aliased.

A new example, `pcss`, has been added. It demonstrates the
percentage-closer soft shadow technique with directional lights, point
lights, spot lights, non-temporal operation, and temporal operation. The
assets are my original work.

Both temporal and non-temporal shadows are rather noisy in the example,
and, as mentioned before, this is unavoidable without downsampling the
depth buffer, which we can't do yet. Note also that the shadows don't
look particularly great for point lights; the example simply isn't an
ideal scene for them. Nevertheless, I felt that the benefits of the
ability to do a side-by-side comparison of directional and point lights
outweighed the unsightliness of the point light shadows in that example,
so I kept the point light feature in.

Fixes #3631.

[*Percentage-closer soft shadows*]:
https://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf

## Changelog

### Added

* Percentage-closer soft shadows (PCSS) are now supported, allowing
shadows to become blurrier as they stretch away from objects. To use
them, set the `soft_shadow_size` field in `DirectionalLight`,
`PointLight`, or `SpotLight`, as applicable.

* The near Z value for shadow maps is now customizable via the
`shadow_map_near_z` field in `DirectionalLight`, `PointLight`, and
`SpotLight`.

## Screenshots

PCSS off:
![Screenshot 2024-05-24
120012](https://github.com/bevyengine/bevy/assets/157897/0d35fe98-245b-44fb-8a43-8d0272a73b86)

PCSS on:
![Screenshot 2024-05-24
115959](https://github.com/bevyengine/bevy/assets/157897/83397ef8-1317-49dd-bfb3-f8286d7610cd)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
2024-09-18 18:07:17 +00:00
Zachary Harrold
bd489068c6
Allow bevy_utils in no_std Contexts (#15279)
# Objective

- Adjust `bevy_utils` to make it `no_std` compatible
- Partially replaces #6581
- Contributes to #8161
- Contributes to #6370

## Solution

Added `alloc` and `std` features to `bevy_utils` (`std` is enabled by
default), allowing the crate's use in `no_std` contexts.

## Testing

- CI passed locally.
- Used `bevy_utils` in a `no_std` crate as an experiment and compiled
successfully.

## Migration Guide

If you were importing `bevy_utils` and setting `default_features` to
`false`, but relying on elements which are now gated behind the `std` or
`alloc` features, include the relevant feature in your `Cargo.toml`.

## Notes

- Bevy already includes a single `no_std` crate, `bevy_ptr`, so there is
precedent for this change.
- As `bevy_utils` is widely used across the rest of Bevy, further work
to make Bevy `no_std` compatible would be blocked on this crate, if such
work was to be undertaken.
- Most of the changes in this PR are just the removal of an unnecessary
call to `to_string()` within unit tests.
2024-09-18 16:00:03 +00:00
TheBigCheese
b1273d48cb
Enable clippy::check-private-items so that missing_safety_doc will apply to private functions as well (#15161)
Enabled `check-private-items` in `clippy.toml` and then fixed the
resulting errors. Most of these were simply misformatted and of the
remaining:
- ~Added `#[allow(clippy::missing_safety_doc)]` to~ Removed unsafe from
a pair of functions in `bevy_utils/futures` which are only unsafe so
that they can be passed to a function which requires `unsafe fn`
- Removed `unsafe` from `UnsafeWorldCell::observers` as from what I can
tell it is always safe like `components`, `bundles` etc. (this should be
checked)
- Added safety docs to:
- `Bundles::get_storage_unchecked`: Based on the function that writes to
`dynamic_component_storages`
- `Bundles::get_storages_unchecked`: Based on the function that writes
to `dynamic_bundle_storages`
   - `QueryIterationCursor::init_empty`: Duplicated from `init`
- `QueryIterationCursor::peek_last`: Thanks Giooschi (also added
internal unsafe blocks)
   - `tests::drop_ptr`: Moved safety comment out to the doc string
 
This lint would also apply to `missing_errors_doc`, `missing_panics_doc`
and `unnecessary_safety_doc` if we chose to enable any of those at some
point, although there is an open
[issue](https://github.com/rust-lang/rust-clippy/issues/13074) to
separate these options.
2024-09-18 15:28:41 +00:00
Isaac Corbrey
fbb9b36441
Throw real error messages on all failed attempts to get StateTransition schedule (#15284)
# Objective

Make it clear to the user why their program is failing rather than
having an unhelpful `called Option::unwrap() on a None value` message.

## Solution

Change the `unwrap()` calls to `expect()` calls, mirroring previously
implemented error messages.

## Testing

I have not tested these changes, but they are fairly trivial so I do not
necessarily feel they need it.
2024-09-18 13:43:06 +00:00
Gino Valente
69541462c5
bevy_reflect: Add Reflectable trait (#5772)
# Objective

When deriving `Reflect`, users will notice that their generic arguments
also need to implement `Reflect`:

```rust
#[derive(Reflect)]
struct Foo<T: Reflect> {
  value: T
}
```

This works well for now. However, as we want to do more with `Reflect`,
these bounds might need to change. For example, to get #4154 working, we
likely need to enforce the `GetTypeRegistration` trait. So now we have:

```rust
#[derive(Reflect)]
struct Foo<T: Reflect + GetTypeRegistration> {
  value: T
}
```

Not great, but not horrible. However, we might then want to do something
as suggested in
[this](https://github.com/bevyengine/bevy/issues/5745#issuecomment-1221389131)
comment and add a `ReflectTypeName` trait for stable type name support.
Well now we have:

```rust
#[derive(Reflect)]
struct Foo<T: Reflect + GetTypeRegistration + ReflectTypeName> {
  value: T
}
```

Now imagine that for even two or three generic types. Yikes!

As the API changes it would be nice if users didn't need to manually
migrate their generic type bounds like this.

A lot of these traits are (or will/might be) core to the entire
reflection API. And although `Reflect` can't add them as supertraits for
object-safety reasons, they are still indirectly required for things to
function properly (manual implementors will know how easy it is to
forget to implement `GetTypeRegistration`). And they should all be
automatically implemented for user types anyways as long they're using
`#[derive(Reflect)]`.

## Solution

Add a "catch-all" trait called `Reflectable` whose supertraits are a
select handful of core reflection traits.

This allows us to consolidate all the examples above into this:

```rust
#[derive(Reflect)]
struct Foo<T: Reflectable> {
  value: T
}
```

And as we experiment with the API, users can rest easy knowing they
don't need to migrate dozens upon dozens of types. It should all be
automatic!

## Discussion

1. Thoughts on the name `Reflectable`? Is it too easily confused with
`Reflect`? Or does it at least accurately describe that this contains
the core traits? If not, maybe `BaseReflect`?

---

## Changelog

- Added the `Reflectable` trait

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-18 00:36:41 +00:00
JoshValjosh
8d78c37ce9
Use FloatOrd for sprite Z comparison and ignore sprites with NaN (#15267)
# Objective

Fixes #15258

## Solution

If my understanding is correct, sprites with NaN anywhere in their
transform won't even get onto the screen, so should not generate pick
events. This PR filters sprites with NaN in their transforms before
sorting by depth, then uses `FloatOrd` to simplify the comparison. Since
we're guaranteed to not have NaN values, it's technically unnecessary,
and we could instead sort with `a.partial_cmp(&b).unwrap()`, or even
`unwrap_unchecked()`.

## Testing

I ran the picking example to ensure Z sorting was working as intended.
2024-09-17 23:27:53 +00:00
Alice Cecile
e0d38a4a3b
Add basic docs explaining what asset processing is and where to look (#15058)
# Objective

Asset processing (added as part of #8624) is a powerful, high-impact
feature, but has been widely underused (and underdeveloped) due to poor
developer understanding.

## Solution

In this PR, I've documented what asset processing is, why it's useful,
and pointed users to the two primary entry points.

While I would like substantially more involved practical examples for
how to perform common asset-processing tasks, I've split them out from
this PR for ease of review (and actually submitting this for review
before the weekend).

We should add bread crumbs from the module docs to these docs, but
whether we add that here or in #15056 depends on which gets merged
first.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-09-17 22:59:12 +00:00
Alice Cecile
23aca13609
Add module and supporting documentation to bevy_assets (#15056)
# Objective

Bevy's asset system is powerful and generally well-designed but very
opaque.

Beginners struggle to discover how to do simple tasks and grok the
fundamental data models, while more advanced users trip over the
assorted traits and their relation to each other.

Reverts #15054 ;)

## Solution

This PR adds module documentation to `bevy_assets`, tweaking the
associated documentation on the items as needed to provide further
details and bread crumbs.

If you have ideas for other important, hard-to-discover patterns or
functionality in this crate, please let me know.

That said, I've left out a section on asset preprocessing which *should*
eventually go here. That is substantially more uncertain, and requires
both more time to investigate and more expertise to review.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: TrialDragon <31419708+TrialDragon@users.noreply.github.com>
Co-authored-by: NotAFile <notafile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-17 22:07:37 +00:00
Wybe Westra
612731edfb
Add DynamicTyped link to TypeInfo docs (#15188) (#15259)
Also added a bit to the paragraph to explain when to use the new
function.
Fixes #15188.
2024-09-17 19:27:26 +00:00
Christian Hughes
378dcacf82
Group IntoSystemConfigs impls together (#15254)
# Objective

Two of the `IntoSystemConfigs` `impl`s are out of place near the top of
the file.

## Solution

Put them below the `IntoSystemConfigs` trait definition, alongside the
other `impl`.
2024-09-17 17:57:22 +00:00
no-materials
b884f96598
Implement enabled flag for fps overlay (#15246)
# Objective

Fixes #15223 

## Solution

Adds an `enabled` flag to the `FpsOverlayConfig` resource with a system
that detects it's change, and adjusts the visibility of the overlay text
entity.

## Testing

I extended the `fps_overlay` example with the option to toggle the
overlay. Run with:
```
cargo run --features="bevy_dev_tools" --example fps_overlay
```
2024-09-17 15:16:28 +00:00
Patrick Walton
3c41586154
Add EntityRefExcept and EntityMutExcept world queries, in preparation for generalized animation. (#15207)
This commit adds two new `WorldQuery` types: `EntityRefExcept` and
`EntityMutExcept`. These types work just like `EntityRef` and
`EntityMut`, but they prevent access to a statically-specified list of
components. For example, `EntityMutExcept<(AnimationPlayer,
Handle<AnimationGraph>)>` provides mutable access to all components
except for `AnimationPlayer` and `Handle<AnimationGraph>`. These types
are useful when you need to be able to process arbitrary queries while
iterating over the results of another `EntityMut` query.

The motivating use case is *generalized animation*, which is an upcoming
feature that allows animation of any component property, not just
rotation, translation, scaling, or morph weights. To implement this, we
must change the current `AnyOf<(&mut Transform, &mut MorphWeights)>` to
instead be `EntityMutExcept<(AnimationPlayer, Handle<AnimationGraph>)>`.
It's possible to use `FilteredEntityMut` in conjunction with a
dynamically-generated system instead, but `FilteredEntityMut` isn't
optimized for the use case of a large number of allowed components
coupled with a small set of disallowed components. No amount of
optimization of `FilteredEntityMut` produced acceptable performance on
the `many_foxes` benchmark. `Query<EntityMut, Without<AnimationPlayer>>`
will not suffice either, as it's legal and idiomatic for an
`AnimationTarget` and an `AnimationPlayer` to coexist on the same
entity.

An alternate proposal was to implement a somewhat-more-general
`Except<Q, CL>` feature, where Q is a `WorldQuery` and CL is a
`ComponentList`. I wasn't able to implement that proposal in a
reasonable way, because of the fact that methods like
`EntityMut::get_mut` and `EntityRef::get` are inherent methods instead
of methods on `WorldQuery`, and therefore there was no way to delegate
methods like `get` and `get_mut` to the inner query in a generic way.
Refactoring those methods into a trait would probably be possible.
However, I didn't see a use case for a hypothetical `Except` with
arbitrary queries: `Query<Except<(&Transform, &Visibility),
Visibility>>` would just be a complicated equivalent to
`Query<&Transform>`, for instance. So, out of a desire for simplicity, I
omitted a generic `Except` mechanism.

I've tested the performance of generalized animation on `many_foxes` and
found that, with this patch, `animate_targets` has a 7.4% slowdown over
`main`. With `FilteredEntityMut` optimized to use `Arc<Access>`, the
slowdown is 75.6%, due to contention on the reference count. Without
`Arc<Access>`, the slowdown is even worse, over 2x.

## Testing

New tests have been added that check that `EntityRefExcept` and
`EntityMutExcept` allow and disallow access to components properly and
that the query engine can correctly reject conflicting queries involving
those types.

A Tracy profile of `many_foxes` with 10,000 foxes showing generalized
animation using `FilteredEntityMut` (red) vs. main (yellow) is as
follows:

![Screenshot 2024-09-12
225914](https://github.com/user-attachments/assets/2993d74c-a513-4ba4-85bd-225672e7170a)

A Tracy profile of `many_foxes` with 10,000 foxes showing generalized
animation using this `EntityMutExcept` (yellow) vs. main (red) is as
follows:

![Screenshot 2024-09-14
205831](https://github.com/user-attachments/assets/4241015e-0c5d-44ef-835b-43f78a24e604)
2024-09-17 14:53:39 +00:00
Benjamin Brienen
b45d83ebda
Rename Add to Queue for methods with deferred semantics (#15234)
# Objective

- Fixes #15106

## Solution

- Trivial refactor to rename the method. The duplicate method `push` was
removed as well. This will simpify the API and make the semantics more
clear. `Add` implies that the action happens immediately, whereas in
reality, the command is queued to be run eventually.
- `ChildBuilder::add_command` has similarly been renamed to
`queue_command`.

## Testing

Unit tests should suffice for this simple refactor.

---

## Migration Guide

- `Commands::add` and `Commands::push` have been replaced with
`Commnads::queue`.
- `ChildBuilder::add_command` has been renamed to
`ChildBuilder::queue_command`.
2024-09-17 00:17:49 +00:00
Navneet Aman
c2d54f5f04
Don't leak SEND resource, even if thread is panicking. (#15247)
# Objective
Currently the resource doesn't get dropped if thread panics. This is
presumably to prevent !SEND resource from being dropped by wrong thread.
But, this logic is not needed for SEND resources. So we don't need this
check for SEND resource.

Fixes #15144 

## Solution

We check if resource is !SEND before, validating that correct thread is
dropping the resource.

## Testing

- Did you test these changes? If so, how?
I did run cargo test on bevy.
- 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?
Nothing special
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
x86_64 desktop
2024-09-16 23:36:52 +00:00
dependabot[bot]
c3465a9676
Update gilrs requirement from 0.10.1 to 0.11.0 (#15245)
Updates the requirements on
[gilrs](https://gitlab.com/gilrs-project/gilrs) to permit the latest
version.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="cbcff6a4cd"><code>cbcff6a</code></a>
Speed up CI by testing only on x86_64-pc-windows-msvc from Windows’
targets</li>
<li><a
href="78582dd9df"><code>78582dd</code></a>
Update deps and prepare for gilrs 0.11.0 and gilrs-core 0.6.0</li>
<li><a
href="aad5c1072d"><code>aad5c10</code></a>
Mark error enums, Event and EventType as non_exhaustive</li>
<li><a
href="ec5d668d6b"><code>ec5d668</code></a>
Fix potential overflow in btn_value()</li>
<li><a
href="59811ff850"><code>59811ff</code></a>
Prepare for gilrs-core 0.5.15 release</li>
<li><a
href="aeaeb747d7"><code>aeaeb74</code></a>
windows: Don’t panic on Reading::update() returning error</li>
<li><a
href="d26e37f121"><code>d26e37f</code></a>
windows: Remove event handlers on drop</li>
<li><a
href="daf263d3cc"><code>daf263d</code></a>
Prevent crash in WASM backend when browser assigns gamepad unexpected
ID</li>
<li><a
href="5f7b786f83"><code>5f7b786</code></a>
Upgrade SDL_GameControllerDB.</li>
<li><a
href="3d92b2e15a"><code>3d92b2e</code></a>
gilrs-core version 0.5.13</li>
<li>Additional commits viewable in <a
href="https://gitlab.com/gilrs-project/gilrs/compare/v0.10.1...v0.11.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 23:34:04 +00:00
Benjamin Brienen
29508f065f
Fix floating point math (#15239)
# Objective

- Fixes #15236

## Solution

- Use bevy_math::ops instead of std floating point operations.

## Testing

- Did you test these changes? If so, how?
Unit tests and `cargo run -p ci -- test`

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Execute `cargo run -p ci -- test` on Windows.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Windows

## Migration Guide

- Not a breaking change
- Projects should use bevy math where applicable

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-09-16 23:28:12 +00:00
Taylor Neal
23a77ca5eb
Rename push children to add children (#15196)
# Objective

- Makes naming between add_child and add_children more consistent
- Fixes #15101 

## Solution

renamed push_children to add_children

## Testing

- Did you test these changes? If so, how?
Ran tests + grep search for any instance of `push_child`

- Are there any parts that need more testing?

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
ran tests on WSL2

---

## Migration Guide

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

- If this PR is a breaking change (relative to the last release of
Bevy), describe how a user might need to migrate their code to support
these changes

rename any use of `push_children()` to the updated `add_children()`
2024-09-16 23:16:04 +00:00
patrickariel
3efef59d83
Enable/disable UI anti-aliasing (#15170)
# Objective

Currently, UI is always rendered with anti-aliasing. This makes bevy's
UI completely unsuitable for art-styles that demands hard pixelated
edges, such as retro-style games.

## Solution

Add a component for disabling anti-aliasing in UI.

## Testing

In
[`examples/ui/button.rs`](15e246eff8/examples/ui/button.rs),
add the component to the camera like this:

```rust
use bevy::{prelude::*, ui::prelude::*};

commands.spawn((Camera2dBundle::default(), UiAntiAlias::Off));
```

The rounded button will now render without anti-aliasing.

## Showcase

An example of a rounded UI node rendered without anti-aliasing, with and
without borders:


![image](https://github.com/user-attachments/assets/ea797e40-bdaa-4ede-a0d3-c9a7eab95b6e)
2024-09-16 23:06:23 +00:00
Robert Walter
29c4c79342
Rotation api extension (#15169)
# Objective

- Another way of specifying rotations was requested in
https://github.com/bevyengine/bevy/issues/11132#issuecomment-2344603178

## Solution

- Add methods on `Rot2`
  - `turn_fraction(fraction: f32) -> Self`
  - `as_turn_fraction(self) -> f32`
- Also add some documentation on range of rotation

## Testing

- extended existing tests
- added new tests

## Showcase 

```rust
let rotation1 = Rot2::degrees(90.0);
let rotation2 = Rot2::turn_fraction(0.25);

// rotations should be equal
assert_relative_eq!(rotation1, rotation2);

// The rotation should be 90 degrees
assert_relative_eq!(rotation2.as_radians(), FRAC_PI_2);
assert_relative_eq!(rotation2.as_degrees(), 90.0);

```

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-16 23:02:08 +00:00
Cole Varner
17b1bcde95
Add missing insert API commands (#15166)
# Objective

- Adds the missing API commands `insert_if_new_and` and
`try_insert_if_new_and` (resolves #15105)
- Adds some test coverage for existing insert commands

## Testing

- Implemented additional unit tests to add coverage
2024-09-16 23:00:00 +00:00
Chris Russell
382917fbb3
Improve type inference in DynSystemParam::downcast() by making the type parameter match the return value. (#15103)
# Objective

Right now, `DynSystemParam::downcast()` always requires the type
parameter to be specified with a turbofish. Make it so that it can be
inferred from the use of the return value, like:

```rust
fn expects_res_a(mut param: DynSystemParam) {
    let res: Res<A> = param.downcast().unwrap();
}
```

## Solution

The reason this doesn't currently work is that the type parameter is a
`'static` version of the `SystemParam` so that it can be used with
`Any::downcast_mut()`. Change the method signature so that the type
parameter matches the return type, and use `T::Item<'static, 'static>`
to get the `'static` version. That means we wind up returning a
`T::Item<'static, 'static>::Item<'w, 's>`, so constrain that to be equal
to `T`. That works with every `SystemParam` implementation, since they
have `T::Item == T` up to lifetimes.
2024-09-16 22:56:57 +00:00
Eero Lehtinen
db525e660e
Fix MeshAllocator panic (#14560)
# Objective

 Fixes #14540

## Solution

- Clean slab layouts from stale `SlabId`s when freeing meshes
- Technically performance requirements of freeing now increase based on
the number of existing meshes, but maybe it doesn't matter too much in
practice
- This was the case before this PR too, but it's technically possible to
free and allocate 2^32 times and overflow with `SlabId`s and cause
incorrect behavior. It looks like new meshes would then override old
ones.

## Testing

- Tested in `loading_screen` example and tapping keyboard 1 and 2.
2024-09-16 22:54:01 +00:00
Adam
9bda913e36
Remove redundent information and optimize dynamic allocations in Table (#12929)
# Objective

- fix #12853
- Make `Table::allocate` faster

## Solution
The PR consists of multiple steps:

1) For the component data: create a new data-structure that's similar to
`BlobVec` but doesn't store `len` & `capacity` inside of it: "BlobArray"
(name suggestions welcome)
2) For the `Tick` data: create a new data-structure that's similar to
`ThinSlicePtr` but supports dynamic reallocation: "ThinArrayPtr" (name
suggestions welcome)
3) Create a new data-structure that's very similar to `Column` that
doesn't store `len` & `capacity` inside of it: "ThinColumn"
4) Adjust the `Table` implementation to use `ThinColumn` instead of
`Column`

The result is that only one set of `len` & `capacity` is stored in
`Table`, in `Table::entities`

### Notes Regarding Performance
Apart from shaving off some excess memory in `Table`, the changes have
also brought noteworthy performance improvements:
The previous implementation relied on `Vec::reserve` &
`BlobVec::reserve`, but that redundantly repeated the same if statement
(`capacity` == `len`). Now that check could be made at the `Table` level
because the capacity and length of all the columns are synchronized;
saving N branches per allocation. The result is a respectable
performance improvement per every `Table::reserve` (and subsequently
`Table::allocate`) call.

I'm hesitant to give exact numbers because I don't have a lot of
experience in profiling and benchmarking, but these are the results I
got so far:

*`add_remove_big/table` benchmark after the implementation:*


![after_add_remove_big_table](https://github.com/bevyengine/bevy/assets/46227443/b667da29-1212-4020-8bb0-ec0f15bb5f8a)

*`add_remove_big/table` benchmark in main branch (measured in comparison
to the implementation):*


![main_add_remove_big_table](https://github.com/bevyengine/bevy/assets/46227443/41abb92f-3112-4e01-b935-99696eb2fe58)

*`add_remove_very_big/table` benchmark after the implementation:*


![after_add_remove_very_big](https://github.com/bevyengine/bevy/assets/46227443/f268a155-295b-4f55-ab02-f8a9dcc64fc2)

*`add_remove_very_big/table` benchmark in main branch (measured in
comparison to the implementation):*


![main_add_remove_very_big](https://github.com/bevyengine/bevy/assets/46227443/78b4e3a6-b255-47c9-baee-1a24c25b9aea)

cc @james7132 to verify

---

## Changelog

- New data-structure that's similar to `BlobVec` but doesn't store `len`
& `capacity` inside of it: `BlobArray`
- New data-structure that's similar to `ThinSlicePtr` but supports
dynamic allocation:`ThinArrayPtr`
- New data-structure that's very similar to `Column` that doesn't store
`len` & `capacity` inside of it: `ThinColumn`
- Adjust the `Table` implementation to use `ThinColumn` instead of
`Column`
- New benchmark: `add_remove_very_big` to benchmark the performance of
spawning a lot of entities with a lot of components (15) each

## Migration Guide

`Table` now uses `ThinColumn` instead of `Column`. That means that
methods that previously returned `Column`, will now return `ThinColumn`
instead.

`ThinColumn` has a much more limited and low-level API, but you can
still achieve the same things in `ThinColumn` as you did in `Column`.
For example, instead of calling `Column::get_added_tick`, you'd call
`ThinColumn::get_added_ticks_slice` and index it to get the specific
added tick.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-09-16 22:52:05 +00:00
Federico Rinaldi
262b068bc3
Substitute trivial fallible conversions with infallible function calls (#10846)
Clippy for rust 1.75 will introduce the
[`unnecessary_fallible_conversions`][1] lint. This PR solves the trivial
ones.

[1]:
https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
2024-09-16 22:46:54 +00:00
Blazepaws
5a0c09d38f
Reflect derived traits on all components and resources: bevy_transform (#15230)
Fixes https://github.com/bevyengine/bevy/issues/15187 for bevy_transform
2024-09-15 18:19:44 +00:00
Blazepaws
cb6ab16c97
Reflect derived traits on all components and resources: bevy_ui (#15231)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_ui
2024-09-15 17:52:38 +00:00
Blazepaws
4d65757b3e
Reflect derived traits on all components and resources: bevy_window (#15233)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_window.
This is the last one.
2024-09-15 17:49:00 +00:00
Blazepaws
1c2e1fc15a
Reflect derived traits on all components and resources: bevy_text (#15229)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_text
2024-09-15 17:21:02 +00:00
Blazepaws
b38cc9e7b0
Reflect derived traits on all components and resources: bevy_state (#15228)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_state
2024-09-15 17:16:45 +00:00
Blazepaws
07e79f3e9f
Reflect derived traits on all components and resources: bevy_sprite (#15227)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_sprite
2024-09-15 17:10:53 +00:00
Blazepaws
274c97d415
Reflect derived traits on all components and resources: bevy_render (#15226)
Addresses https://github.com/bevyengine/bevy/issues/15187 for
bevy_render
2024-09-15 17:05:11 +00:00
Blazepaws
0c92908baf
Reflect derived traits on all components and resources: bevy_picking (#15225)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_picking
2024-09-15 16:17:39 +00:00
Blazepaws
b6b28a621f
Reflect derived traits on all components and resources: bevy_pbr (#15224)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_pbr
2024-09-15 16:07:30 +00:00
poopy
d878e2f8bd
add allow_all and deny_all methods to DynamicSceneBuilder (#15222)
# Objective

It would be convenient to be able to quickly deny or allow all
components and resources on a `DynamicSceneBuilder` with a single method
call.

Context: #15210 renamed `{allow/deny}_all` to
`{allow/deny}_all_components`.

## Solution

Added two new methods to `DynamicSceneBuilder`, `allow_all` and
`deny_all`, which affect both the component and resource filters.


## Showcase

### Before

```rust
let builder = DynamicSceneBuilder::from_world(world)
    .deny_all_components()
    .deny_all_resources();
```

### After

```rust
let builder = DynamicSceneBuilder::from_world(world).deny_all();
```
2024-09-15 15:30:53 +00:00
Blazepaws
228ce8170a
Use of deprecated function in example for ButtonInput (#15221)
The function `bevy_input::schedule::condition::Condition::or_else` has
been deprecated in favor of
`bevy_input::schedule::condition::Condition::or`. However the docs for
`ButtonInput` were still using the deprecated function in their example.
2024-09-15 15:22:39 +00:00
Blazepaws
62b2cdab32
Reflect derived traits on all components and resources: bevy_hierarchy (#15219)
Solves https://github.com/bevyengine/bevy/issues/15187 for
bevy_hierarchy
2024-09-15 15:09:28 +00:00
Blazepaws
e718bbd55c
Reflect derived traits on all components and resources: bevy_input (#15220)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_input
2024-09-15 15:08:46 +00:00
Blazepaws
569f68f8a0
Reflect derived traits on all components and resources: bevy_gltf (#15218)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_gltf
2024-09-15 14:47:43 +00:00
Blazepaws
379696a468
Reflect derived traits on all components and resources: bevy_gizmos (#15217)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_gizmos
2024-09-15 14:41:49 +00:00
poopy
2ea8d35900
explicitly mention component in methods on DynamicSceneBuilder (#15210)
# Objective

The method names on `DynamicSceneBuilder` are misleading. Specifically,
`deny_all` and `allow_all` implies everything will be denied/allowed,
including all components and resources. In reality, these methods only
apply to components (which is mentioned in the docs).

## Solution

- change `deny_all` and `allow_all` to `deny_all_components` and
`allow_all_components`
- also, change the remaining methods to mention component where it makes
sense

We could also add the `deny_all` and `allow_all` methods back later,
only this time, they would deny/allow both resources and components.

## Showcase

### Before
```rust
let builder = DynamicSceneBuilder::from_world(world)
    .deny_all()
    .deny_all_resources()
    .allow::<MyComponent>();
```

### After
```rust
let builder = DynamicSceneBuilder::from_world(world)
    .deny_all_components()
    .deny_all_resources()
    .allow_component::<MyComponent>();
```

## Migration Guide

the following invocations on `DynamicSceneBuilder` should be changed by
users
- `with_filter` -> `with_component_filter`
- `allow` -> `allow_component`
- `deny` -> `deny_component`
- `allow_all` -> `allow_all_components`
- `deny_all` -> `deny_all_components`
2024-09-15 14:37:32 +00:00
Al M.
2ea51fc60f
Use FromReflect when extracting entities in dynamic scenes (#15174)
# Objective

Fix #10284.

## Solution

When `DynamicSceneBuilder` extracts entities, they are cloned via
`PartialReflect::clone_value`, making them into dynamic versions of the
original components. This loses any custom `ReflectSerialize` type data.
Dynamic scenes are deserialized with the original types, not the dynamic
versions, and so any component with a custom serialize may fail. In this
case `Rect` and `Vec2`. The dynamic version includes the field names 'x'
and 'y' but the `Serialize` impl doesn't, hence the "expect float"
error.

The solution here: Instead of using `clone_value` to clone the
components, `FromReflect` clones and retains the original information
needed to serialize with any custom `Serialize` impls. I think using
something like `reflect_clone` from
(https://github.com/bevyengine/bevy/pull/13432) might make this more
efficient.

I also did the same when deserializing dynamic scenes to appease some of
the round-trip tests which use `ReflectPartialEq`, which requires the
types be the same and not a unique/proxy pair. I'm not sure it's
otherwise necessary. Maybe this would also be more efficient when
spawning dynamic scenes with `reflect_clone` instead of `FromReflect`
again?

An alternative solution would be to fall back to the dynamic version
when deserializing `DynamicScene`s if the custom version fails. I think
that's possible. Or maybe simply always deserializing via the dynamic
route for dynamic scenes?

## Testing

This example is similar to the original test case in #10284:

``` rust
#![allow(missing_docs)]

use bevy::{prelude::*, scene::SceneInstanceReady};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, (save, load).chain())
        .observe(check)
        .run();
}

static SAVEGAME_SAVE_PATH: &str = "savegame.scn.ron";

fn save(world: &mut World) {
    let entity = world.spawn(OrthographicProjection::default()).id();

    let scene = DynamicSceneBuilder::from_world(world)
        .extract_entity(entity)
        .build();

    if let Some(registry) = world.get_resource::<AppTypeRegistry>() {
        let registry = registry.read();
        let serialized_scene = scene.serialize(&registry).unwrap();
        // println!("{}", serialized_scene);
        std::fs::write(format!("assets/{SAVEGAME_SAVE_PATH}"), serialized_scene).unwrap();
    }

    world.entity_mut(entity).despawn_recursive();
}

fn load(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(DynamicSceneBundle {
        scene: asset_server.load(SAVEGAME_SAVE_PATH),
        ..default()
    });
}

fn check(_trigger: Trigger<SceneInstanceReady>, query: Query<&OrthographicProjection>) {
    dbg!(query.single());
}
```


## Migration Guide

The `DynamicScene` format is changed to use custom serialize impls so
old scene files will need updating:

Old: 

```ron
(
  resources: {},
  entities: {
    4294967299: (
      components: {
        "bevy_render:📷:projection::OrthographicProjection": (
          near: 0.0,
          far: 1000.0,
          viewport_origin: (
            x: 0.5,
            y: 0.5,
          ),
          scaling_mode: WindowSize(1.0),
          scale: 1.0,
          area: (
            min: (
              x: -1.0,
              y: -1.0,
            ),
            max: (
              x: 1.0,
              y: 1.0,
            ),
          ),
        ),
      },
    ),
  },
)
```

New:

```ron
(
  resources: {},
  entities: {
    4294967299: (
      components: {
        "bevy_render:📷:projection::OrthographicProjection": (
          near: 0.0,
          far: 1000.0,
          viewport_origin: (0.5, 0.5),
          scaling_mode: WindowSize(1.0),
          scale: 1.0,
          area: (
            min: (-1.0, -1.0),
            max: (1.0, 1.0),
          ),
        ),
      },
    ),
  },
)
```

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-09-15 14:33:39 +00:00
Blazepaws
21e39360f7
Example for bevy_ecs::event::Events uses deprecated function get_reader (#15216)
Fixes https://github.com/bevyengine/bevy/issues/15214
2024-09-15 14:24:04 +00:00
Blazepaws
abac8c7b0f
Reflect derived traits on all components and resources: bevy_audio (#15211)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_audio
2024-09-15 14:24:00 +00:00
Blazepaws
53d2bc9482
Reflect derived traits on all components and resources: bevy_ecs (#15215)
Solves https://github.com/bevyengine/bevy/issues/15187 for bevy_ecs
2024-09-15 14:23:54 +00:00
Blazepaws
df8cb3e5e2
Reflect derived traits on all components and resources: bevy_core_pipeline (#15213)
Solves https://github.com/bevyengine/bevy/issues/15187 for
bevy_core_pipeline
2024-09-15 14:23:41 +00:00
Blazepaws
c909a0572d
Reflect derived traits on all components and resources: bevy_animation (#15209)
Solves https://github.com/bevyengine/bevy/issues/15187 for the
bevy_animation subcrate
2024-09-15 11:58:51 +00:00
kivi
3f425da66e
Improve schedule note of .after/.before & encourage to use .chain ins… (#14986)
# Objective

- Fixes #14552 
- Make the current note of `before` and `after` understandable. 
- > The given set is not implicitly added to the schedule when this
system set is added.

## Solution

- Replace note in docs of [`after` and
`before`](https://docs.rs/bevy/latest/bevy/ecs/prelude/trait.IntoSystemConfigs.html#method.before)
- Note of after was removed completely, and links to `before`, because
they notes would be identical.
- Also encourage to use `.chain`, which is much simpler and safer to use

## Testing

- Checked the docs after running `cargo doc` and `cargo run -p ci --
lints`
- Are there any parts that need more testing?
- no need to test, but please review the text. If it is still including
the intended message and especially if its understandable.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-14 21:03:21 +00:00
Wybe Westra
70808af776
Added ordering information to observer tests (#14332) (#15178)
Fixes #14332 by recording the order in which the events occur.
2024-09-14 14:08:49 +00:00
Joona Aalto
b36443b6ed
Fix Capsule2d::sample_interior (#15191)
# Objective

`Capsule2d::sample_interior` uses the radius of the capsule for the
width of its rectangular section. It should be using two times the
radius for the full width!

I noticed this as I was getting incorrect results for angular inertia
approximated from a point cloud of points sampled on the capsule. This
hinted that something was wrong with the sampling.

## Solution

Multiply the radius by two to get the full width of the rectangular
section. With this, the sampling produces the correct result in my
tests.
2024-09-14 02:24:08 +00:00
Blazepaws
583e034796
Reflected traits for resources and components: bevy_a11y (#15192)
Solves https://github.com/bevyengine/bevy/issues/15187 for the bevy_a11y
subcrate.
2024-09-14 01:43:16 +00:00
Cole Varner
cf55e6cb22
ParsedPath::try_from<&str> (#15180)
# Objective

- implements ParsedPath::try_from<&str>
- resolves #14438

## Testing

- Added unit test for ParsedPath::try_from<&str>

Note: I don't claim to be an expert on lifetimes! That said I think it
makes sense that the error shares a lifetime with input string as deeper
down it is used to construct it.
2024-09-13 17:37:09 +00:00
Gino Valente
37443e0f3f
bevy_reflect: Add DynamicTyped trait (#15108)
# Objective

Thanks to #7207, we now have a way to validate at the type-level that a
reflected value is actually the type it says it is and not just a
dynamic representation of that type.

`dyn PartialReflect` values _might_ be a dynamic type, but `dyn Reflect`
values are guaranteed to _not_ be a dynamic type.

Therefore, we can start to add methods to `Reflect` that weren't really
possible before. For example, we should now be able to always get a
`&'static TypeInfo`, and not just an `Option<&'static TypeInfo>`.

## Solution

Add the `DynamicTyped` trait.

This trait is similar to `DynamicTypePath` in that it provides a way to
use the non-object-safe `Typed` trait in an object-safe way.

And since all types that derive `Reflect` will also derive `Typed`, we
can safely add `DynamicTyped` as a supertrait of `Reflect`. This allows
us to use it when just given a `dyn Reflect` trait object.

## Testing

You can test locally by running:

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

---

## Showcase

`Reflect` now has a supertrait of `DynamicTyped`, allowing `TypeInfo` to
be retrieved from a `dyn Reflect` trait object without having to unwrap
anything!

```rust
let value: Box<dyn Reflect> = Box::new(String::from("Hello!"));

// BEFORE
let info: &'static TypeInfo = value.get_represented_type_info().unwrap();

// AFTER
let info: &'static TypeInfo = value.reflect_type_info();
```

## Migration Guide

`Reflect` now has a supertrait of `DynamicTyped`. If you were manually
implementing `Reflect` and did not implement `Typed`, you will now need
to do so.
2024-09-13 17:17:10 +00:00
Wybe Westra
ae80a20690
Reccomend using AssetPlugin.file_path instead of CARGO_MANIFEST_DIR (#15176)
Fixes #15175.

One question I have: I see that the scene_viewer example uses the
CARGO_MANIFEST_DIR. Should that line be removed, or would that break the
tool?

1fd478277e/examples/tools/scene_viewer/main.rs (L40)
2024-09-13 16:16:23 +00:00
ickshonpe
1b1105e327
Remove border radius scaling (#15173)
# Objective

Fixes #15142

Split this off from #15163 as it's a very simple fix.

## Solution

UiScale was applied twice to border radius, remove the second
application.

## Testing

You can use this modified button example from the issue for testing:

```
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
        .insert_resource(UiScale(2.))
        .insert_resource(WinitSettings::desktop_app())
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

fn button_system(
    mut interaction_query: Query<
        (
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &Children,
        ),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                text.sections[0].value = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                border_color.0 = RED.into();
            }
            Interaction::Hovered => {
                text.sections[0].value = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                border_color.0 = Color::WHITE;
            }
            Interaction::None => {
                text.sections[0].value = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                border_color.0 = Color::BLACK;
            }
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2dBundle::default());
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            parent
                .spawn(ButtonBundle {
                    style: Style {
                        width: Val::Px(250.0),
                        height: Val::Px(100.0),
                        border: UiRect::all(Val::Px(25.0)),
                        // horizontally center child text
                        justify_content: JustifyContent::Center,
                        // vertically center child text
                        align_items: AlignItems::Center,
                        ..default()
                    },
                    border_color: BorderColor(Color::BLACK),
                    border_radius: BorderRadius::all(Val::Px(25.)),
                    background_color: NORMAL_BUTTON.into(),
                    ..default()
                })
                .with_child(TextBundle::from_section(
                    "Button",
                    TextStyle {
                        font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                        font_size: 40.0,
                        color: Color::srgb(0.9, 0.9, 0.9),
                    },
                ));
            parent
                .spawn(NodeBundle {
                    style: Style {
                        width: Val::Px(150.0),
                        padding: UiRect::vertical(Val::Px(25.)),
                        height: Val::Px(100.0),
                        align_items: AlignItems::Stretch,
                        justify_content: JustifyContent::Stretch,
                        ..Default::default()
                    },
                    ..default()
                })
                .with_child(NodeBundle {
                    style: Style {
                        flex_basis: Val::Percent(100.),
                        ..Default::default()
                    },
                    background_color: RED.into(),
                    ..Default::default()
                });
        });
}
```

## Showcase

Using the modified button example

### main

<img alt="366023197-e6124f07-e522-4514-bd8e-7986ac32890c"
src="https://github.com/user-attachments/assets/b7b909ed-1184-4d9d-b50b-e30f4c1f76b2">


### this PR

![image](https://github.com/user-attachments/assets/89b89a2f-533f-41bd-b2cb-4743aec6519e)
2024-09-13 15:52:42 +00:00
SpecificProtagonist
f570f52aa2
Optimize observer unregistration (#15150)
# Objective

Fixes #14980

## Solution

Only iterate over archetypes containing the component.

## Alternatives

Additionally, for each archetype, cache how many observers are watching
one of its components & use this to speed up the check for each affected
archetype ([implemented
here](55c89aa033)).
Benchmarking showed this to lead only to a minor speedup.

## Testing

There's both already a test checking that observers don't run after
being despawned as well as a regression test for the bug that
necessitates the check this PR optimizes.
2024-09-13 15:47:24 +00:00
Pēteris Pakalns
e567669c31
TrackedRenderPass internal tracking state reset (#14948)
# Objective

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

## Solution

Invalidate `TrackedRenderPass` internal state upon accessing internal
`wgpu::RenderPass`.

## Testing

- Tested by calling `set_bind_group` on `RenderPass` returned by
`TrackedRenderPass::wgpu_pass` and checking if in later `set_bind_group`
calls on `TrackedRenderPass` correct bind group is restored.
2024-09-12 16:51:36 +00:00
charlotte
1fd478277e
Fix mesh 2d non indexed draw. (#15155)
Closes #15154. Looks like 2d was just missed in
d235d41af1.


![image](https://github.com/user-attachments/assets/1656d320-fed2-4a25-b2b0-14755e10faf7)
2024-09-12 12:38:56 +00:00
Robert Walter
327e1ddba4
Micro typo in bevy_ecs (#15167)
I'm currently reading through the code and docs and found this.
2024-09-12 08:43:33 +00:00
mamekoro
15e246eff8
Fix typo in bevy_reflect/src/reflect.rs (#15157)
Corrected a typo "enumuration" to "enumeration".
2024-09-11 21:51:17 +00:00
Niashi
8bfe635c3e
Finish enhancing ReflectCommandExt to work with Bundles (#15152)
# Objective

- Finish resolving https://github.com/bevyengine/bevy/issues/15125
- Inserting bundles was implemented in
https://github.com/bevyengine/bevy/pull/15128 but removing bundles still
needed to be implemented.

## Solution

- Modified `bevy_ecs::reflect::entity_commands::remove_reflect` to
handle both components and bundles
- Modified documentation of `ReflectCommandExt` methods to reflect that
one can now use bundles with these commands.

## Testing

- Three tests were added to match the ones for inserting components.
2024-09-11 03:19:28 +00:00
Zachary Harrold
be35cba801
Removed Type Parameters from Observer (#15151)
# Objective

- Remove any ambiguity around how multiple `Observer` components work on
a single `Entity` by completely removing the concept.
- Fixes #15122

## Solution

- Removed type parameters from `Observer`, relying on a function pointer
to provide type information into the relevant aspects of running an
observer.

## Testing

- Ran CI locally.
- Checked `observers.rs` example continued to function as expected.

## Notes

This communicates to users of observers that only a single `Observer`
can be inserted onto an entity at a time within the established type
system. This has been achieved by erasing the type information from the
stored `ObserverSystem` and retrieving it again using a function
pointer. This has the downside of increasing the size of the `Observer`
component and increases the complexity of the observer runner. However,
this complexity was already present, and is in my opinion a worthwhile
tradeoff for the clearer user experience.

The other notable benefit is users no longer need to use the
`ObserverState` component to filter for `Observer` entities, and can
instead use `Observer` directly.

Technically this is a breaking change, since the type signature for
`Observer` has changed. However, it was so cumbersome to use that I
don't believe there are any instances in the wild of users directly
naming `Observer` types, instead relying on `ObserverState`, and the
methods provided by `App` and `World`. As can be seen in the diff, this
change had very little knock-on effects across Bevy.

## Migration Guide

If you filtered for observers using `Observer<A, B>`, instead filter for
an `Observer`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-11 01:14:28 +00:00
Gino Valente
75343ef584
bevy_reflect: Mention FunctionRegistry in bevy_reflect::func docs (#15147)
# Objective

The module docs for `bevy_reflect::func` don't mention the
`FunctionRegistry`.

## Solution

Add a section about the `FunctionRegistry` to the module-level
documentation.

## Testing

You can test locally by running:

```
cargo test --doc --package bevy_reflect --all-features
```
2024-09-10 23:39:05 +00:00
UkoeHB
fa51e26052
Trim cosmic-text's shape run cache (#15037)
# Objective

- Fixes https://github.com/bevyengine/bevy/pull/14991. The `cosmic-text`
shape run cache requires manual cleanup for old text that no longer
needs to be cached.

## Solution

- Add a system to trim the cache.
- Add an `average fps` indicator to the `text_debug` example.

## Testing

Tested with `cargo run --example text_debug`.
- **No shape run cache**: 82fps with ~1fps variance.
- **Shape run cache no trim**: 90-100fps with ~2-4fps variance
- **Shape run cache trim age = 1**: 90-100fps with ~2-8fps variance
- **Shape run cache trim age = 2**: 90-100fps with ~2-4fps variance
- **Shape run cache trim age = 2000**: 80-120fps with ~2-6fps variance

The shape run cache seems to increase average FPS but also increases
frame time variance (when there is dynamic text).
2024-09-10 23:28:05 +00:00
ickshonpe
cacf3929db
fix spelling mistake (#15146)
# Objective

Fix spelling mistake: `interned_root_notes` -> `interned_root_nodes`
2024-09-10 20:21:40 +00:00
Joona Aalto
afbbbd7335
Rename rendering components for improved consistency and clarity (#15035)
# Objective

The names of numerous rendering components in Bevy are inconsistent and
a bit confusing. Relevant names include:

- `AutoExposureSettings`
- `AutoExposureSettingsUniform`
- `BloomSettings`
- `BloomUniform` (no `Settings`)
- `BloomPrefilterSettings`
- `ChromaticAberration` (no `Settings`)
- `ContrastAdaptiveSharpeningSettings`
- `DepthOfFieldSettings`
- `DepthOfFieldUniform` (no `Settings`)
- `FogSettings`
- `SmaaSettings`, `Fxaa`, `TemporalAntiAliasSettings` (really
inconsistent??)
- `ScreenSpaceAmbientOcclusionSettings`
- `ScreenSpaceReflectionsSettings`
- `VolumetricFogSettings`

Firstly, there's a lot of inconsistency between `Foo`/`FooSettings` and
`FooUniform`/`FooSettingsUniform` and whether names are abbreviated or
not.

Secondly, the `Settings` post-fix seems unnecessary and a bit confusing
semantically, since it makes it seem like the component is mostly just
auxiliary configuration instead of the core *thing* that actually
enables the feature. This will be an even bigger problem once bundles
like `TemporalAntiAliasBundle` are deprecated in favor of required
components, as users will expect a component named `TemporalAntiAlias`
(or similar), not `TemporalAntiAliasSettings`.

## Solution

Drop the `Settings` post-fix from the component names, and change some
names to be more consistent.

- `AutoExposure`
- `AutoExposureUniform`
- `Bloom`
- `BloomUniform`
- `BloomPrefilter`
- `ChromaticAberration`
- `ContrastAdaptiveSharpening`
- `DepthOfField`
- `DepthOfFieldUniform`
- `DistanceFog`
- `Smaa`, `Fxaa`, `TemporalAntiAliasing` (note: we might want to change
to `Taa`, see "Discussion")
- `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflections`
- `VolumetricFog`

I kept the old names as deprecated type aliases to make migration a bit
less painful for users. We should remove them after the next release.
(And let me know if I should just... not add them at all)

I also added some very basic docs for a few types where they were
missing, like on `Fxaa` and `DepthOfField`.

## Discussion

- `TemporalAntiAliasing` is still inconsistent with `Smaa` and `Fxaa`.
Consensus [on
Discord](https://discord.com/channels/691052431525675048/743663924229963868/1280601167209955431)
seemed to be that renaming to `Taa` would probably be fine, but I think
it's a bit more controversial, and it would've required renaming a lot
of related types like `TemporalAntiAliasNode`,
`TemporalAntiAliasBundle`, and `TemporalAntiAliasPlugin`, so I think
it's better to leave to a follow-up.
- I think `Fog` should probably have a more specific name like
`DistanceFog` considering it seems to be distinct from `VolumetricFog`.
~~This should probably be done in a follow-up though, so I just removed
the `Settings` post-fix for now.~~ (done)

---

## Migration Guide

Many rendering components have been renamed for improved consistency and
clarity.

- `AutoExposureSettings` → `AutoExposure`
- `BloomSettings` → `Bloom`
- `BloomPrefilterSettings` → `BloomPrefilter`
- `ContrastAdaptiveSharpeningSettings` → `ContrastAdaptiveSharpening`
- `DepthOfFieldSettings` → `DepthOfField`
- `FogSettings` → `DistanceFog`
- `SmaaSettings` → `Smaa`
- `TemporalAntiAliasSettings` → `TemporalAntiAliasing`
- `ScreenSpaceAmbientOcclusionSettings` → `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflectionsSettings` → `ScreenSpaceReflections`
- `VolumetricFogSettings` → `VolumetricFog`

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-09-10 01:11:46 +00:00
Antony
74ccab947d
Remove ReceivedCharacter (#15126)
# Objective

- Fixes #12639.
- `ReceivedCharacter` was deprecated in #12868 for 0.14, and should be
removed for 0.15.

## Solution

- Remove all instances of `ReceivedCharacter`, including the relevant
`#[allow(deprecated)]` lint attributes.

## Migration Guide

`ReceivedCharacter` was deprecated in 0.14 due to `winit` reworking
their keyboard system. It has now been fully removed. Switch to using
`KeyboardInput` instead.

```rust
// 0.14
fn listen_characters(events: EventReader<ReceivedCharacter>) {
    for event in events.read() {
        info!("{}", event.char);
    }
}

// 0.15
fn listen_characters(events: EventReader<KeyboardInput>) {
    for event in events.read() {
        // Only check for characters when the key is pressed.
        if !event.state.is_pressed() {
            continue;
        }

        // Note that some keys such as `Space` and `Tab` won't be detected as a character.
        // Instead, check for them as separate enum variants.
        match &event.logical_key {
            Key::Character(character) => {
                info!("{} pressed.", character);
            },
            Key::Space => {
                info!("Space pressed.");
            },
            _ => {},
        }
    }
}
```
2024-09-10 00:22:06 +00:00
ickshonpe
8d143e3ed8
ui material node border calculations fix (#15119)
# Objective

Fixes  #15115

## Solution

Retrieve the size of the node's parent in a separate query and base
percentage border values on the parent node's width (or the width of the
viewport in the case of root nodes).
2024-09-09 22:35:29 +00:00
Rich Churcher
f326705cab
Remove OrthographicProjection.scale (adopted) (#15075)
# Objective

Hello! I am adopting #11022 to resolve conflicts with `main`. tldr: this
removes `scale` in favour of `scaling_mode`. Please see the original PR
for explanation/discussion.

Also relates to #2580.

## Migration Guide

Replace all uses of `scale` with `scaling_mode`, keeping in mind that
`scale` is (was) a multiplier. For example, replace
```rust
    scale: 2.0,
    scaling_mode: ScalingMode::FixedHorizontal(4.0),

```
with
```rust
    scaling_mode: ScalingMode::FixedHorizontal(8.0),
```

---------

Co-authored-by: Stepan Koltsov <stepan.koltsov@gmail.com>
2024-09-09 22:34:58 +00:00
Han Damin
0cf276f239
Enhance ReflectCommandExt (#15128)
# Objective

- Enhance #15125

## Solution

- Modified `ReflectCommandExt::insert_reflect` to accept and handle both
components and bundles.

---------

Co-authored-by: Gonçalo Rica Pais da Silva <bluefinger@gmail.com>
Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
2024-09-09 22:34:44 +00:00
Gino Valente
90bb1adeb2
bevy_reflect: Contextual serialization error messages (#13888)
# Objective

Reflection serialization can be difficult to debug. A lot of times a
type fails to be serialized and the user is left wondering where that
type came from.

This is most often encountered with Bevy's scenes. Attempting to
serialize all resources in the world will fail because some resources
can't be serialized.

For example, users will often get complaints about `bevy_utils::Instant`
not registering `ReflectSerialize`. Well, `Instant` can't be serialized,
so the only other option is to exclude the resource that contains it.
But what resource contains it? This is where reflection serialization
can get a little tricky (it's `Time<Real>` btw).

## Solution

Add the `debug_stack` feature to `bevy_reflect`. When enabled, the
reflection serializers and deserializers will keep track of the current
type stack. And this stack will be used in error messages to help with
debugging.

Now, if we unknowingly try to serialize `Time<Real>`, we'll get the
following error:

```
type `bevy_utils::Instant` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data` (stack: `bevy_time::time::Time<bevy_time::real::Real>` -> `bevy_time::real::Real` -> `bevy_utils::Instant`)
```

### Implementation

This makes use of `thread_local!` to manage an internal `TypeInfoStack`
which holds a stack of `&'static TypeInfo`. We push to the stack before
a type is (de)serialized and pop from the stack afterwards.

Using a thread-local should be fine since we know two (de)serializers
can't be running at the same time (and if they're running on separate
threads, then we're still good).

The only potential issue would be if a user went through one of the
sub-serializers, like `StructSerializer`. However, I don't think many
users are going through these types (I don't even know if we necessarily
want to keep those public either, but we'll save that for a different
PR). Additionally, this is just a debug feature that only affects error
messages, so it wouldn't have any drastically negative effect. It would
just result in the stack not being cleared properly if there were any
errors.

Lastly, this is not the most performant implementation since we now
fetch the `TypeInfo` an extra time. But I figured that for a debug tool,
it wouldn't matter too much.

### Feature

This also adds a `debug` feature, which enables the `debug_stack`
feature.

I added it because I think we may want to potentially add more debug
tools in the future, and this gives us a good framework for adding
those. Users who want all debug features, present and future, can just
set `debug`. If they only want this feature, then they can just use
`debug_stack`.

I also made the `debug` feature default to help capture the widest
audience (i.e. the users who want this feature but don't know they do).
However, if we think it's better as a non-default feature, I can change
it!

And if there's any bikeshedding around the name `debug_stack`, let me
know!

## Testing

Run the following command:

```
cargo test --package bevy_reflect --features debug_stack
```

---

## Changelog

- Added the `debug` and `debug_stack` features to `bevy_reflect`
- Updated the error messages returned by the reflection serializers and
deserializers to include more contextual information when the
`debug_stack` or `debug` feature is enabled
2024-09-09 17:52:40 +00:00
robtfm
4e6471ed23
honour NoFrustumCulling for shadows (#15117)
# Objective

`NoFrustumCulling` prevents meshes from being considered out of view
based on AABBs (sometimes useful for skinned meshes which don't
recalculate AABBs currently). it currently only applies for primary view
rendering, not for shadow rendering which can result in missing shadows.

## Solution

Add checks for `NoFrustumCulling` to `check_dir_light_mesh_visibility`
and `check_point_light_mesh_visibility` so that `NoFrustumCulling`
entities are rendered to all shadow views as well as all primary views.
2024-09-09 17:51:38 +00:00
akimakinai
bafffe1c5f
Fix screenshot example (#15094)
# Objective

I noticed some issues in `screenshot` example:
1. Cursor icon won't return from `SystemCursorIcon::Progress` to default
icon, even though screen shot saving is done.
2. Panics when exiting window: ``called `Result::unwrap()` on an `Err`
value:
NoEntities("bevy_ecs::query::state::QueryState<bevy_ecs::entity::Entity,
bevy_ecs::query::filter::With<bevy_window:🪟:Window>>")``

## Solution

1. Caused by cursor updating system not responding to [`CursorIcon`
component
removal](5cfcbf47ed/examples/window/screenshot.rs (L38)).
I believe it should, so change it to react to
`RemovedComponents<CursorIcon>`. (a suggestion)
2. Use `get_single` for window.

## Testing

- run screenshot example

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-09 16:53:20 +00:00
UkoeHB
adc2cf7dfe
Add state scoped events (#15085)
# Objective

- Improve robustness of state transitions. Currently events that should
be scoped to a specific state can leak between state scopes since events
live for two ticks.
- See https://github.com/bevyengine/bevy/issues/15072

## Solution

- Allow registering state scoped events that will be automatically
cleared when exiting a state. This is *most of the time* not obviously
useful, but enables users to write correct code that will avoid/reduce
edge conditions (such as systems that aren't state scoped polling for a
state scoped event and having unintended side effects outside a specific
state instance).

## Testing

Did not test.

---

## Showcase

Added state scoped events that will be automatically cleared when
exiting a state. Useful when you want to guarantee clean state
transitions.

Normal way to add an event:
```rust
fn setup(app: &mut App) {
    app.add_event::<MyGameEvent>();
}
```

Add a state-scoped event (**NEW**):
```rust
fn setup(app: &mut App) {
    app.add_state_scoped_event::<MyGameEvent>(GameState::Play);
}
```
2024-09-09 16:37:27 +00:00
Christian Hughes
79f6fcd1eb
EntityRef/Mut get_components (immutable variants only) (#15089)
# Objective

Smaller scoped version of #13375 without the `_mut` variants which
currently have unsoundness issues.

## Solution

Same as #13375, but without the `_mut` variants.

## Testing

- The same test from #13375 is reused.

---

## Migration Guide

- Renamed `FilteredEntityRef::components` to
`FilteredEntityRef::accessed_components` and
`FilteredEntityMut::components` to
`FilteredEntityMut::accessed_components`.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Periwink <charlesbour@gmail.com>
2024-09-09 16:29:44 +00:00
Gino Valente
245d03a78a
bevy_reflect: Update on_unimplemented attributes (#15110)
# Objective

Some of the new compile error messages are a little unclear (at least to
me). For example:

```
error[E0277]: `tests::foo::Bar` can not be created through reflection
   --> crates/bevy_reflect/src/lib.rs:679:18
    |
679 |         #[derive(Reflect)]
    |                  ^^^^^^^ the trait `from_reflect::FromReflect` is not implemented for `tests::foo::Bar`
    |
    = note: consider annotating `tests::foo::Bar` with `#[derive(Reflect)]` or `#[derive(FromReflect)]`
```

While the annotation makes it clear that `FromReflect` is missing, it's
not very clear from the main error message.

My IDE lists errors with only their message immediately present:

<p align="center">
<img width="700" alt="Image of said IDE listing errors with only their
message immediately present. These errors are as follows:
\"`tests::foo::Bar` can not be created through reflection\", \"The trait
bound `tests::foo::Bar: RegisterForReflection` is not satisfied\", and
\"The trait bound `tests::foo::Bar: type_info::MaybeTyped` is not
satisfied\""
src="https://github.com/user-attachments/assets/42c24051-9e8e-4555-8477-51a9407446aa">
</p>

This makes it hard to tell at a glance why my code isn't compiling.

## Solution

Updated all `on_unimplemented` attributes in `bevy_reflect` to mention
the relevant trait—either the actual trait or the one users actually
need to implement—as well as a small snippet of what not implementing
them means.

For example, failing to implement `TypePath` now mentions missing a
`TypePath` implementation. And failing to implement `DynamicTypePath`
now also mentions missing a `TypePath` implementation, since that's the
actual trait users need to implement (i.e. they shouldn't implement
`DynamicTypePath` directly).

Lastly, I also added some missing `on_unimplemented` attributes for
`MaybeTyped` and `RegisterForReflection` (which you can see in the image
above).

Here's how this looks in my IDE now:

<p align="center">
<img width="700" alt="Similar image as before showing the errors listed
by the IDE. This time the errors read as follows: \"`tests::foo::Bar`
does not implement `FromReflect` so cannot be reified through
reflection\", \"`tests::foo::Bar` does not implement
`GetTypeRegistration` so cannot be registered for reflection\", and
\"`tests::foo::Bar` does not implement `Typed` so cannot provide static
type information\""
src="https://github.com/user-attachments/assets/f6f8501f-0450-4f78-b84f-00e7a18d0533">
</p>


## Testing

You can test by adding the following code and verifying the compile
errors are correct:

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

struct Bar;
```
2024-09-09 16:26:17 +00:00
Tim
5adacf014c
Use associated type bounds for iter_many and friends (#15040)
# Objective

Make the bounds for these query methods less intimidating.
Continuation of #14107

<sub>My last pr was back in february 💀
2024-09-09 16:24:39 +00:00
Zachary Harrold
85e41ddace
Add observer to Trigger (#15066)
# Objective

- Fixes  #15061

## Solution

- Added `observer` to `Trigger`, which returns the entity observing the
triggered event.

## Testing

- CI passed locally.
2024-09-09 16:23:14 +00:00
ickshonpe
4de9edeaa6
Retrieve the stack_index from Node in extract_ui_material_nodes instead of walking UiStack (#15104)
# Objective

 `ExtractedUiMaterialNode` is still walking the whole `UiStack`. 

more info: https://github.com/bevyengine/bevy/pull/9853

## Solution

Retrieve the `stack_index` from the `Node` component instead.
Also changed the `stack_index` field of `ExtractedUiMaterialNode` to
`u32`.
2024-09-09 16:18:37 +00:00
Marco Meijer
66b5128b6f
Add rect field to UI image (#15095)
# Objective

Fixes #14424 

## Solution

Add a rect field to UiImage, and update the extraction of ui images and
slices.

## Testing

I tested all possible combinations of having a rect, using a texture
atlas, setting image scale mode to sliced and image scale mode to tiled.
See the showcase section.

---

## Showcase

<img width="1279" alt="Screenshot 2024-09-08 at 16 23 05"
src="https://github.com/user-attachments/assets/183e53eb-f27c-4c8e-9fd5-4678825db3b6">

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

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

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, create_ui)
        .run();
}

fn create_ui(
    mut commands: Commands,
    assets: Res<AssetServer>,
    mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
    let texture = assets.load("textures/fantasy_ui_borders/numbered_slices.png");
    let layout = TextureAtlasLayout::from_grid(UVec2::splat(16), 3, 3, None, None);
    let texture_atlas_layout = texture_atlas_layouts.add(layout);

    commands.spawn(Camera2dBundle::default());

    let style = Style {
        width: Val::Px(96.),
        height: Val::Px(96.),
        ..default()
    };

    commands
        .spawn(NodeBundle { ..default() })
        .with_children(|parent| {
            // nothing
            parent.spawn(ImageBundle {
                image: UiImage::new(texture.clone()),
                style: style.clone(),
                ..default()
            });

            // with rect
            parent.spawn(ImageBundle {
                image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                style: style.clone(),
                ..default()
            });

            // with rect and texture atlas
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
            ));

            // with texture atlas
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
            ));

            // with texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(16.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with rect and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(2.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with rect, texture atlas and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(1.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with texture atlas and texture slicer
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
                ImageScaleMode::Sliced(TextureSlicer {
                    border: BorderRect::square(2.),
                    center_scale_mode: SliceScaleMode::Stretch,
                    sides_scale_mode: SliceScaleMode::Stretch,
                    max_corner_scale: 1.,
                }),
            ));

            // with tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with rect and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 16., 16.)),
                    style: style.clone(),
                    ..default()
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with rect, texture atlas and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()).with_rect(Rect::new(0., 0., 8., 8.)),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 1,
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));

            // with texture atlas and tiled
            parent.spawn((
                ImageBundle {
                    image: UiImage::new(texture.clone()),
                    style: style.clone(),
                    ..default()
                },
                TextureAtlas {
                    layout: texture_atlas_layout.clone(),
                    index: 2,
                },
                ImageScaleMode::Tiled {
                    tile_x: true,
                    tile_y: true,
                    stretch_value: 1.,
                },
            ));
        });
}
```

</details>
2024-09-09 16:16:33 +00:00
研究社交
9b006fdf75
bevy_pbr: Make choosing of diffuse indirect lighting explicit. (#15093)
# Objective

Make choosing of diffuse indirect lighting explicit, instead of using
numerical conditions like `all(indirect_light == vec3(0.0f))`, as using
that may lead to unwanted light leakage.

## Solution

Use an explicit `found_diffuse_indirect` condition to indicate the found
indirect lighting source.

## Testing

I have tested examples `lightmaps`, `irradiance_volumes` and
`reflection_probes`, there are no visual changes. For further testing,
consider a "cave" scene with lightmaps and irradiance volumes. In the
cave there are some purly dark occluded area, those dark area will
sample the irradiance volume, and that is easy to leak light.
2024-09-09 16:11:16 +00:00
Han Damin
29c632b524
Add common aspect ratio constants and improve documentation (#15091)
Hello,

I'd like to contribute to this project by adding some useful constants
and improving the documentation for the AspectRatio struct. Here's a
summary of the changes I've made:

1. Added new constants for common aspect ratios:
   - SIXTEEN_NINE (16:9)
   - FOUR_THREE (4:3)
   - ULTRAWIDE (21:9)

2. Enhanced the overall documentation:
   - Improved module-level documentation with an overview and use cases
   - Expanded explanation of the AspectRatio struct with examples
- Added detailed descriptions and examples for all methods (both
existing and new)
   - Included explanations for the newly introduced constant values
   - Added clarifications for From trait implementations

These changes aim to make the AspectRatio API more user-friendly and
easier to understand. The new constants provide convenient access to
commonly used aspect ratios, which I believe will be helpful in many
scenarios.

---------

Co-authored-by: Gonçalo Rica Pais da Silva <bluefinger@gmail.com>
Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
2024-09-09 16:04:41 +00:00
Zachary Harrold
dac4a5bbb4
Depreciate LoadAndSave Asset Processor (#15090)
# Objective

- Fixes #15060

## Solution

- Added `IdentityAssetTransformer<A>` which is an `AssetTransformer`
which infallibly returns the input `Asset` unmodified.
- Replaced `LoadAndSave` and `LoadAndSaveSettings` with type definitions
linking back to `LoadTransformAndSave` and
`LoadTransformAndSaveSettings` respectively.
- Marked `LoadAndSave` and `LoadAndSaveSettings` as depreciated with a
migration guide included, hinting to the user to use the underlying type
instead.

## Testing

- Ran CI locally

---

## Migration Guide

- Replace `LoadAndSave<L, S>` with `LoadTransformAndSave<L,
IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>`
- Replace `LoadAndSaveSettings<L, S>` with
`LoadTransformAndSaveSettings<L, (), S>`
2024-09-09 16:01:14 +00:00
UkoeHB
ce32b5ca06
Add set_state extension method to Commands (#15083)
# Objective

- Improve the ergonomics of managing states.

## Solution

- Add `set_state` extension method to `Commands` so you don't need to
type out `ResMut<NextState<S>>` to update a state. It also reduces
system parameter list size when you already have `Commands`.
- I only updated a couple examples to showcase how it can be used. There
*is* a potential perf cost to introducing `Commands` so this method
shouldn't necessarily be used everywhere.

## Testing

- Tested the updated examples: `game_menu` and `alien_cake_addict`.

---

## Showcase

Add `Commands::set_state` method for easily updating states.

Set directly:
```rust
fn go_to_game(mut game_state: ResMut<NextState<GameState>>) {
    game_state.set(GameState::Play);
}
```

Set with commands (**NEW**):
```rust
fn go_to_game(mut commands: Commands) {
    commands.set_state(GameState::Play);
}
```
2024-09-09 15:58:09 +00:00
Alix Bott
82e416dc48
Split OrthographicProjection::default into 2d & 3d (Adopted) (#15073)
Adopted PR from dmlary, all credit to them!
https://github.com/bevyengine/bevy/pull/9915

Original description:

# Objective

The default value for `near` in `OrthographicProjection` should be
different for 2d & 3d.

For 2d using `near = -1000` allows bevy users to build up scenes using
background `z = 0`, and foreground elements `z > 0` similar to css.
However in 3d `near = -1000` results in objects behind the camera being
rendered. Using `near = 0` works for 3d, but forces 2d users to assign
`z <= 0` for rendered elements, putting the background at some arbitrary
negative value.

There is no common value for `near` that doesn't result in a footgun or
usability issue for either 2d or 3d, so they should have separate
values.

There was discussion about other options in the discord
[0](https://discord.com/channels/691052431525675048/1154114310042292325),
but splitting `default()` into `default_2d()` and `default_3d()` seemed
like the lowest cost approach.

Related/past work https://github.com/bevyengine/bevy/issues/9138,
https://github.com/bevyengine/bevy/pull/9214,
https://github.com/bevyengine/bevy/pull/9310,
https://github.com/bevyengine/bevy/pull/9537 (thanks to @Selene-Amanita
for the list)

## Solution

This commit splits `OrthographicProjection::default` into `default_2d`
and `default_3d`.

## Migration Guide

- In initialization of `OrthographicProjection`, change `..default()` to
`..OrthographicProjection::default_2d()` or
`..OrthographicProjection::default_3d()`

Example:
```diff
--- a/examples/3d/orthographic.rs
+++ b/examples/3d/orthographic.rs
@@ -20,7 +20,7 @@ fn setup(
         projection: OrthographicProjection {
             scale: 3.0,
             scaling_mode: ScalingMode::FixedVertical(2.0),
-            ..default()
+            ..OrthographicProjection::default_3d()
         }
         .into(),
         transform: Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
```

---------

Co-authored-by: David M. Lary <dmlary@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-09 15:51:28 +00:00
charlotte
8460cfa6ab
Fix AsBindGroup sampler validation. (#15071)
Kind of confused why this wasn't breaking for me pre-`0.15-dev` since
nothing obvious seems to have changed in `wgpu` upstream, but this fixes
it and ensures that we return the correct sample type re: the actual
device.
2024-09-09 15:48:33 +00:00
CrazyboyQCD
bca228fdaa
Simplify pick_rounded_rect (#15065)
# Objective

Simplify `pick_rounded_rect` with multiple `if` statements to make it
more readable and efficient([Godbolt
link](https://godbolt.org/z/W5vPEvT5c)).

Co-authored-by: WX\shixi <shixi1@cnwxsoft.com>
2024-09-09 15:40:00 +00:00
Ben Frankel
7b217a976c
Remove deprecated SpriteSheetBundle and AtlasImageBundle (#15062)
# Objective

Remove bundles that were deprecated in 0.14.

## Testing

`rg SpriteSheetBundle` and `rg AtlasImageBundle` show no results.
2024-09-09 15:36:09 +00:00
Alice Cecile
3d30b0f9ac
Add basic docs to AssetMode (#15057)
# Objective

We should attempt to document the entirety of bevy_assets. `AssetMode`
is missing docs explaining what it is, how it's used and why it exists.

## Solution

Add docs, focusing on the context in
https://github.com/bevyengine/bevy/issues/10157.
2024-09-09 15:33:29 +00:00
LP
fab0e5d085
Sorts the scene entries by path before serializing. (#15047)
# Objective

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

## Solution

Sorts the iterator with itertools' sorted_by function. This is required
given that 'self.entries' is an immutable &[Box<dyn PartialReflect]
which also doesn't implement Clone or Copy.

## Testing

The modifications passed the unit testing only after they were edited to
ensure that the items were in alphabetical order.
I haven't checked for performance implications.
2024-09-09 15:31:30 +00:00
charlotte
5eca832cee
Add convenience methods for constructing and setting storage buffer data (#15044)
Adds some methods to assist in building `ShaderStorageBuffer` without
using `bytemuck`. We keep the `&[u8]` constructors since this is still
modeled as a thin wrapper around the buffer descriptor, but should make
it easier to interact with at the cost of an extra allocation in the
`ShaderType` path for the buffer writer.

Follow up from #14663
2024-09-09 15:28:31 +00:00
Christian Hughes
e939d6c33f
Remove remnant EntityHash and related types from bevy_utils (#15039)
# Objective

`EntityHash` and related types were moved from `bevy_utils` to
`bevy_ecs` in #11498, but seemed to have been accidentally reintroduced
a week later in #11707.

## Solution

Remove the old leftover code.

---

## Migration Guide

- Uses of `bevy::utils::{EntityHash, EntityHasher, EntityHashMap,
EntityHashSet}` now have to be imported from `bevy::ecs::entity`.
2024-09-09 15:24:17 +00:00
Chris Russell
a9d2a9ea37
Make QueryFilter an unsafe trait (#14790)
# Objective

It's possible to create UB using an implementation of `QueryFilter` that
performs mutable access, but that does not violate any documented safety
invariants.

This code: 
```rust
#[derive(Component)]
struct Foo(usize);

// This derive is a simple way to get a valid WorldQuery impl.  The QueryData impl isn't used.
#[derive(QueryData)]
#[query_data(mutable)]
struct BadFilter<'w> {
    foo: &'w mut Foo,
}

impl QueryFilter for BadFilter<'_> {
    const IS_ARCHETYPAL: bool = false;

    unsafe fn filter_fetch(
        fetch: &mut Self::Fetch<'_>,
        entity: Entity,
        table_row: TableRow,
    ) -> bool {
        // SAFETY: fetch and filter_fetch have the same safety requirements
        let f: &mut usize = &mut unsafe { Self::fetch(fetch, entity, table_row) }.foo.0;
        println!("Got &mut at     {f:p}");
        true
    }
}

let mut world = World::new();
world.spawn(Foo(0));
world.run_system_once(|query: Query<&Foo, BadFilter>| {
    let f: &usize = &query.iter().next().unwrap().0;
    println!("Got & at        {f:p}");
    query.iter().next().unwrap();
    println!("Still have & at {f:p}");
});
```

prints: 

```
Got &mut at     0x1924b92dfb0
Got & at        0x1924b92dfb0
Got &mut at     0x1924b92dfb0
Still have & at 0x1924b92dfb0
```

Which means it had an `&` and `&mut` alive at the same time.

The only `unsafe` there is around `Self::fetch`, but I believe that call
correctly upholds the safety invariant, and matches what `Added` and
`Changed` do.


## Solution

Make `QueryFilter` an unsafe trait and document the requirement that the
`WorldQuery` implementation be read-only.

## Migration Guide

`QueryFilter` is now an `unsafe trait`. If you were manually
implementing it, you will need to verify that the `WorldQuery`
implementation is read-only and then add the `unsafe` keyword to the
`impl`.
2024-09-09 15:23:12 +00:00
Dragoș Tiselice
4b78ba0162
Replaced implicit emissive weight with default. (#13871)
Since `StandardMaterial::emissive_exposure_weight` does not get packed
into the gbuffer in the deferred case, unpacking uses an implicit
default value for emissive's alpha channel.

This resulted in divergent behavior between the forward and deferred
renderers when using standard materials with default
emissive_exposure_weight, this value defaulting to `0.0` in the forward
case and `1.0` in the other.

This patch changes the implicit value in the deferred case to `0.0` in
order to match the behavior of the forward renderer. However, this still
does not solve the case where `emissive_exposure_weight` is not `0.0`.
2024-09-09 15:14:50 +00:00
Gino Valente
ba3d9b3fb6
bevy_reflect: Refactor serde module (#15107)
# Objective

The `ser` and `de` modules in `bevy_reflect/serde` are very long and
difficult to navigate.

## Solution

Refactor both modules into many smaller modules that each have a single
primary focus (i.e. a `structs` module that only handles struct
serialization/deserialization).

I chose to keep the `ser` and `de` modules separate. We could have
instead broken it up kind (e.g. lists, maps, etc.), but I think this is
a little cleaner. Serialization and deserialization, while related, can
be very different. So keeping them separated makes sense for
organizational purposes.

That being said, if people disagree and think we should structure this a
different way, I am open to changing it.

Note that this PR's changes are mainly structural. There are a few
places I refactored code to reduce duplication and to make things a bit
cleaner, but these are largely cosmetic and shouldn't have any impact on
behavior.

### Other Details

This PR also hides a lot of the internal logic from being exported.
These were originally public, but it's unlikely they really saw any use
outside of these modules. In fact, you don't really gain anything by
using them outside of this module either.

By privatizing these fields and items, we also set ourselves up for more
easily changing internal logic around without involving a breaking
change.

I also chose not to mess around with tests since that would really blow
up the diff haha.

## Testing

You can test locally by running:

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

---

## Migration Guide

The fields on `ReflectSerializer` and `TypedReflectSerializer` are now
private. To instantiate, the corresponding constructor must be used:

```rust
// BEFORE
let serializer = ReflectSerializer {
    value: &my_value,
    registry: &type_registry,
};

// AFTER
let serializer = ReflectSerializer::new(&my_value, &type_registry);
```

Additionally, the following types are no longer public:

- `ArraySerializer`
- `EnumSerializer`
- `ListSerializer`
- `MapSerializer`
- `ReflectValueSerializer` (fully removed)
- `StructSerializer`
- `TupleSerializer`
- `TupleStructSerializer`

As well as the following traits:

- `DeserializeValue` (fully removed)
2024-09-09 14:03:42 +00:00
JMS55
a0faf9cd01
More triangles/vertices per meshlet (#15023)
### Builder changes
- Increased meshlet max vertices/triangles from 64v/64t to 255v/128t
(meshoptimizer won't allow 256v sadly). This gives us a much greater
percentage of meshlets with max triangle count (128). Still not perfect,
we still end up with some tiny <=10 triangle meshlets that never really
get simplified, but it's progress.
- Removed the error target limit. Now we allow meshoptimizer to simplify
as much as possible. No reason to cap this out, as the cluster culling
code will choose a good LOD level anyways. Again leads to higher quality
LOD trees.
- After some discussion and consulting the Nanite slides again, changed
meshlet group error from _adding_ the max child's error to the group
error, to doing `group_error = max(group_error, max_child_error)`. Error
is already cumulative between LODs as the edges we're collapsing during
simplification get longer each time.
- Bumped the 65% simplification threshold to allow up to 95% of the
original geometry (e.g. accept simplification as valid even if we only
simplified 5% of the triangles). This gives us closer to
log2(initial_meshlet_count) LOD levels, and fewer meshlet roots in the
DAG.

Still more work to be done in the future here. Maybe trying METIS for
meshlet building instead of meshoptimizer.

Using ~8 clusters per group instead of ~4 might also make a big
difference. The Nanite slides say that they have 8-32 meshlets per
group, suggesting some kind of heuristic. Unfortunately meshopt's
compute_cluster_bounds won't work with large groups atm
(https://github.com/zeux/meshoptimizer/discussions/750#discussioncomment-10562641)
so hard to test.

Based on discussion from
https://github.com/bevyengine/bevy/discussions/14998,
https://github.com/zeux/meshoptimizer/discussions/750, and discord.

### Runtime changes
- cluster:triangle packed IDs are now stored 25:7 instead of 26:6 bits,
as max triangles per cluster are now 128 instead of 64
- Hardware raster now spawns 128 * 3 vertices instead of 64 * 3 vertices
to account for the new max triangles limit
- Hardware raster now outputs NaN triangles (0 / 0) instead of
zero-positioned triangles for extra vertex invocations over the cluster
triangle count. Shouldn't really be a difference idt, but I did it
anyways.
- Software raster now does 128 threads per workgroup instead of 64
threads. Each thread now loads, projects, and caches a vertex (vertices
0-127), and then if needed does so again (vertices 128-254). Each thread
then rasterizes one of 128 triangles.
- Fixed a bug with `needs_dispatch_remap`. I had the condition backwards
in my last PR, I probably committed it by accident after testing the
non-default code path on my GPU.
2024-09-08 17:55:57 +00:00
Rob Parrett
0a79a0ac8c
Fix error link (#15082)
# Objective

A previous issue describes the same problem: #14248.

This particular link was seemingly missed by #14276.

## Solution

- Search repo for `bevyengine.org/learn/errors/#`
- Remove `#`
- Verify link goes to right place
2024-09-08 17:11:17 +00:00
BD103
6ec6a55645
Unify crate-level preludes (#15080)
# Objective

- Crate-level prelude modules, such as `bevy_ecs::prelude`, are plagued
with inconsistency! Let's fix it!

## Solution

Format all preludes based on the following rules:

1. All preludes should have brief documentation in the format of:
   > The _name_ prelude.
   >
> This includes the most common types in this crate, re-exported for
your convenience.
2. All documentation should be outer, not inner. (`///` instead of
`//!`.)
3. No prelude modules should be annotated with `#[doc(hidden)]`. (Items
within them may, though I'm not sure why this was done.)

## Testing

- I manually searched for the term `mod prelude` and updated all
occurrences by hand. 🫠

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-09-08 17:10:57 +00:00
Eero Lehtinen
b738f081f8
Register reflect type CursorIcon (#15078)
# Objective

- `CursorIcon` had derived `Reflect`, but it wasn't registered

## Solution

- Use `register_type` on it
- I also moved the cursor code to it's own plugin because there was
starting to be too much cursor code outside the cursor file.

## Testing

- window_settings example still works with the custom cursor
2024-09-08 17:10:45 +00:00
BigWingBeat
54aa45e62f
Fix bevy_ui compile error when bevy_picking feature is disabled (#15053)
# Objective

#14957 added the `pick_rounded_rect` function to `bevy_ui` in the
`picking_backend` module, which is gated behind the `bevy_picking`
feature. This function is used in that module, as well as in the `focus`
module. The latter usage is not gated behind the `bevy_picking` feature,
causing a compile error when the feature is disabled.

## Solution

Move the `pick_rounded_rect` function out of the `picking_backend`
module, as it does not depend on anything defined in that module. I put
it in `lib.rs` but it could reasonably be moved somewhere else instead.

## Testing

Encountered this compile error in a project and confirmed that this
patch fixes it.
2024-09-05 19:16:57 +00:00
ickshonpe
cb221d8852
Node::is_empty (#15050)
# Objective

Add a `Node::is_empty` method to replace the `uinode.size().x() <= 0. ||
uinode.size.y() <= 0.` checks.
2024-09-05 16:26:45 +00:00
Alice Cecile
5589f0da40
Revert accidentally added asset docs (#15054)
Our branch protection rules were misconfigured, allowing me to push
directly to `origin/main` 😱 This is now resolved:


![image](https://github.com/user-attachments/assets/bb0ac59a-6998-42f7-80d6-8b3a865c6f53)

This PR reverts those accidental changes, which will get their own PR
momentarily...
2024-09-05 14:24:24 +00:00
Alice Cecile
ba1f13fdc7 Add a small note on loading screens 2024-09-05 09:57:55 -04:00
Alice Cecile
480c2bcb56 Add note on AssetServer::load not being wasteful 2024-09-05 09:55:06 -04:00
Alice Cecile
a4b51d71f1 Basic practical overview 2024-09-05 09:51:51 -04:00
Alice Cecile
22aa9abb13 Clarify relationships between saving, loading, reading and writing 2024-09-05 09:42:23 -04:00
Alice Cecile
f016aeaaaa Add advice on handles and reference counting 2024-09-05 09:23:28 -04:00
Alice Cecile
77c5efc56f Basic docs for Asset and VisitAssetDependencies 2024-09-05 09:11:26 -04:00
Alice Cecile
1a9e55fa9b Initial overview 2024-09-05 08:53:45 -04:00
ickshonpe
a0f5ea0d36
UI outlines radius (#15018)
# Objective

Fixes #13479

This also fixes the gaps you can sometimes observe in outlines
(screenshot from main, not this PR):

<img width="636" alt="outline-gaps"
src="https://github.com/user-attachments/assets/c11dae24-20f5-4aea-8ffc-1894ad2a2b79">

The outline around the last item in each section has vertical gaps. 

## Solution

Draw the outlines with corner radius using the existing border rendering
for uinodes. The outline radius is very simple to calculate. We just
take the computed border radius of the node, and if it's greater than
zero, add it to the distance from the edge of the node to the outer edge
of the node's outline.

---

## Showcase

<img width="634" alt="outlines-radius"
src="https://github.com/user-attachments/assets/1ecda26c-65c5-41ef-87e4-5d9171ddc3ae">

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-09-04 22:30:16 +00:00
Miles Silberling-Cook
82128d778a
Picking event ordering (#14862)
# Objective

Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.

## Solution

Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.

The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.

The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.

The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.

## Status & Testing

This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.

Feedback on the chosen ordering of events is within-scope.

## Migration Guide

For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.

For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
ickshonpe
8ac745ab10
UI texture slice texture flipping reimplementation (#15034)
# Objective

Fixes #15032

## Solution

Reimplement support for the `flip_x` and `flip_y` fields.
This doesn't flip the border geometry, I'm not really sure whether that
is desirable or not.
Also fixes a bug that was causing the side and center slices to tile
incorrectly.

### Testing

```
cargo run --example ui_texture_slice_flip_and_tile
```

## Showcase
<img width="787" alt="nearest"
src="https://github.com/user-attachments/assets/bc044bae-1748-42ba-92b5-0500c87264f6">
With tiling need to use nearest filtering to avoid bleeding between the
slices.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-04 19:31:41 +00:00
re0312
739007f148
Opportunistically use dense iter for archetypal iteration in Par_iter (#14673)
# Objective

- follow of #14049 ,we could use it on our Parallel Iterator,this pr
also unified the used function in both regular iter and parallel
iterations.


## Performance 


![image](https://github.com/user-attachments/assets/cba700bc-169c-4b58-b504-823bdca8ec05)

no performance regression for regular itertaion

3.5X faster in hybrid parallel iteraion,this number is far greater than
the benefits obtained in regular iteration(~1.81) because mutable
iterations on continuous memory can effectively reduce the cost of
mataining core cache coherence
2024-09-03 23:41:10 +00:00
Alice Cecile
4ac2a63556
Remove all existing system order ambiguities in DefaultPlugins (#15031)
# Objective

As discussed in https://github.com/bevyengine/bevy/issues/7386, system
order ambiguities within `DefaultPlugins` are a source of bugs in the
engine and badly pollute diagnostic output for users.

We should eliminate them!

This PR is an alternative to #15027: with all external ambiguities
silenced, this should be much less prone to merge conflicts and the test
output should be much easier for authors to understand.

Note that system order ambiguities are still permitted in the
`RenderApp`: these need a bit of thought in terms of how to test them,
and will be fairly involved to fix. While these aren't *good*, they'll
generally only cause graphical bugs, not logic ones.

## Solution

All remaining system order ambiguities have been resolved.
Review this PR commit-by-commit to see how each of these problems were
fixed.

## Testing

`cargo run --example ambiguity_detection` passes with no panics or
logging!
2024-09-03 20:24:34 +00:00
Chris Juchem
c620eb7833
Return Results from Camera's world/viewport conversion methods (#14989)
# Objective

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

## Solution

- Add `ViewportConversionError` and return it from viewport conversion
methods on Camera.

## Testing

- I successfully compiled and ran all changed examples.

## Migration Guide

The following methods on `Camera` now return a `Result` instead of an
`Option` so that they can provide more information about failures:
 - `world_to_viewport`
 - `world_to_viewport_with_depth`
 - `viewport_to_world`
 - `viewport_to_world_2d`

Call `.ok()` on the `Result` to turn it back into an `Option`, or handle
the `Result` directly.

---------

Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-09-03 19:45:15 +00:00
ickshonpe
4e9a62f094
Ignore clicks on uinodes outside of rounded corners (#14957)
# Objective

Fixes #14941

## Solution
1. Add a `resolved_border_radius` field to `Node` to hold the resolved
border radius values.
2. Remove the border radius calculations from the UI's extraction
functions.
4. Compute the border radius during UI relayouts in `ui_layout_system`
and store them in `Node`.
5. New `pick_rounded_rect` function based on the border radius SDF from
`ui.wgsl`.
6. Use `pick_rounded_rect` in `focus` and `picking_backend` to check if
the pointer is hovering UI nodes with rounded corners.
---

## Showcase

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


https://github.com/user-attachments/assets/ea951a64-17ef-455e-b5c9-a2e6f6360648

## Testing

Modified button example with buttons with different corner radius:

```
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
        .insert_resource(WinitSettings::desktop_app())
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

fn button_system(
    mut interaction_query: Query<
        (
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &Children,
        ),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                text.sections[0].value = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                border_color.0 = RED.into();
            }
            Interaction::Hovered => {
                text.sections[0].value = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                border_color.0 = Color::WHITE;
            }
            Interaction::None => {
                text.sections[0].value = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                border_color.0 = Color::BLACK;
            }
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2dBundle::default());
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                row_gap: Val::Px(10.),
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            for border_radius in [
                BorderRadius {
                    top_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    top_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
            ] {
                parent
                    .spawn(ButtonBundle {
                        style: Style {
                            width: Val::Px(150.0),
                            height: Val::Px(65.0),
                            border: UiRect::all(Val::Px(5.0)),
                            // horizontally center child text
                            justify_content: JustifyContent::Center,
                            // vertically center child text
                            align_items: AlignItems::Center,
                            ..default()
                        },
                        border_color: BorderColor(Color::BLACK),
                        border_radius,
                        background_color: NORMAL_BUTTON.into(),
                        ..default()
                    })
                    .with_child(TextBundle::from_section(
                        "Button",
                        TextStyle {
                            font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                            font_size: 40.0,
                            color: Color::srgb(0.9, 0.9, 0.9),
                        },
                    ));
            }
        });
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-09-03 12:38:59 +00:00
Martín Maita
32f40f11b5
Bump crate-ci/typos from 1.24.1 to 1.24.3 (#15024)
# Objective

- Adopts #15015

## Solution

- Fixed a typo that broke the build and prevented updating
`crate-ci/typos`.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 00:57:41 +00:00
Zachary Harrold
250cc63ddf
Updated LogPlugin Documentation with Performance Warning (#14984)
# Objective

- Fixes #14966

## Solution

- Added a _Performance_ section to the documentation for
`LogPlugin::filter` explaining that long filter strings can degrade
performance and to instead rely on `LogPlugin::level` when possible.

## Testing

- CI passed locally.
2024-09-03 00:48:19 +00:00
Robert Walter
8a64b7621d
Color gradient curve (#14976)
# Objective

- Currently we have the `ColorRange` trait to interpolate linearly
between two colors
- It would be cool to have:
  1. linear interpolation between n colors where `n >= 1`
  2. other kinds of interpolation

## Solution

1. Implement `ColorGradient` which takes `n >= 1` colors and linearly
interpolates between consecutive pairs of them
2. Implement `Curve` intergration for this `ColorGradient` which yields
a curve struct. After that we can apply all of the cool curve adaptors
like `.reparametrize()` and `.map()` to the gradient

## Testing

- Added doc tests
- Added tests

## Showcase

```rust
// let gradient = ColorGradient::new(vec![]).unwrap(); // panic! 💥
let gradient = ColorGradient::new([basic::RED, basic::LIME, basic::BLUE]).expect("non-empty");
let curve = gradient.to_curve();
let brighter_curve = curve.map(|c| c.mix(&basic::WHITE, 0.5));
```

--- 

Kind of related to
https://github.com/bevyengine/bevy/pull/14971#discussion_r1736337631

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-09-02 23:26:30 +00:00
ickshonpe
01a3b0e830
UI texture atlas slice shader (#14990)
# Objective

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

## Solution

Reimplement the UI texture atlas slicer using a shader. 

The problems with #14183 could be fixed more simply by hacking around
with the coordinates and scaling but that way is very fragile and might
get broken again the next time we make changes to the layout
calculations. A shader based solution is more robust, it's impossible
for gaps to appear between the image slices with these changes as we're
only drawing a single quad.

I've not tried any benchmarks yet but it should much more efficient as
well, in the worst cases even hundreds or thousands of times faster.

Maybe could have used the UiMaterialPipeline. I wrote the shader first
and used fat vertices and then realised it wouldn't work that way with a
UiMaterial. If it's rewritten it so it puts all the slice geometry in
uniform buffer, then it might work? Adding the uniform buffer would
probably make the shader more complicated though, so don't know if it's
even worth it. Instancing is another alternative.

## Testing
The examples are working and it seems to match the old API correctly but
I've not used the texture atlas slicing API for anything before, I
reviewed the PR but that was back in January.

Needs a review by someone who knows the rendering pipeline and wgsl
really well because I don't really have any idea what I'm doing.
2024-09-02 23:03:58 +00:00
ickshonpe
96942058f7
Extract borders without border radius (#15020)
# Objective

The `BorderRadius` component shouldn't be required to draw borders for
nodes with sharp corners.

## Solution

Make `BorderRadius` optional in `extract_uinode_borders`'s UI node
query.
2024-09-02 22:47:43 +00:00
BigWingBeat
61f9f8c5f6
Fix with_child not inserting Parent component (#15009)
# Objective

The `Parent` component holds a reference to the parent entity of the
entity it is inserted onto. The `with_child` function erroneously
forgets to insert this component onto the child entity that it spawns,
causing buggy behaviour when the function is used instead of the other
child-spawning functions.

## Solution

Ensure `with_child` inserts the `Parent` component, the same as all the
other child-spawning functions.

## Testing

Checked before/after with a bevy_ui layout where this patch fixed buggy
behaviour I was seeing in parent/child UI nodes.
2024-09-02 22:47:25 +00:00
UkoeHB
3fc02cb925
Reduce allocations in ui_layout_system (#15001)
# Objective

- Shave off some allocations from `ui_layout_system`.

## Solution

- Add a `Local` for allocation buffers.
2024-09-02 22:37:27 +00:00
Zachary Harrold
547b1c7a7a
Reflect SmolStr's De/Serialize implementation (#14982)
# Objective

- Fixes #14969

## Solution

- Added `Deserialize` to the list of reflected traits for `SmolStr`

## Testing

- CI passed locally.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-02 22:35:17 +00:00
Patrick Walton
d2624765d0
Implement animation masks, allowing fine control of the targets that animations affect. (#15013)
This commit adds support for *masks* to the animation graph. A mask is a
set of animation targets (bones) that neither a node nor its descendants
are allowed to animate. Animation targets can be assigned one or more
*mask group*s, which are specific to a single graph. If a node masks out
any mask group that an animation target belongs to, animation curves for
that target will be ignored during evaluation.

The canonical use case for masks is to support characters holding
objects. Typically, character animations will contain hand animations in
the case that the character's hand is empty. (For example, running
animations may close a character's fingers into a fist.) However, when
the character is holding an object, the animation must be altered so
that the hand grips the object.

Bevy currently has no convenient way to handle this. The only workaround
that I can see is to have entirely separate animation clips for
characters' hands and bodies and keep them in sync, which is burdensome
and doesn't match artists' expectations from other engines, which all
effectively have support for masks. However, with mask group support,
this task is simple. We assign each hand to a mask group and parent all
character animations to a node. When a character grasps an object in
hand, we position the fingers as appropriate and then enable the mask
group for that hand in that node. This allows the character's animations
to run normally, while the object remains correctly attached to the
hand.

Note that even with this PR, we won't have support for running separate
animations for a character's hand and the rest of the character. This is
because we're missing additive blending: there's no way to combine the
two masked animations together properly. I intend that to be a follow-up
PR.

The major engines all have support for masks, though the workflow varies
from engine to engine:

* Unity has support for masks [essentially as implemented here], though
with layers instead of a tree. However, when using the Mecanim
("Humanoid") feature, precise control over bones is lost in favor of
predefined muscle groups.

* Unreal has a feature named [*layered blend per bone*]. This allows for
separate blend weights for different bones, effectively achieving masks.
I believe that the combination of blend nodes and masks make Bevy's
animation graph as expressible as that of Unreal, once we have support
for additive blending, though you may have to use more nodes than you
would in Unreal. Moreover, separating out the concepts of "blend weight"
and "which bones this node applies to" seems like a cleaner design than
what Unreal has.

* Godot's `AnimationTree` has the notion of [*blend filters*], which are
essentially the same as masks as implemented in this PR.

Additionally, this patch fixes a bug with weight evaluation whereby
weights weren't properly propagated down to grandchildren, because the
weight evaluation for a node only checked its parent's weight, not its
evaluated weight. I considered submitting this as a separate PR, but
given that this PR refactors that code entirely to support masks and
weights under a unified "evaluated node" concept, I simply included the
fix here.

A new example, `animation_masks`, has been added. It demonstrates how to
toggle masks on and off for specific portions of a skin.

This is part of #14395, but I'm going to defer closing that issue until
we have additive blending.

[essentially as implemented here]:
https://docs.unity3d.com/560/Documentation/Manual/class-AvatarMask.html

[*layered blend per bone*]:
https://dev.epicgames.com/documentation/en-us/unreal-engine/using-layered-animations-in-unreal-engine

[*blend filters*]:
https://docs.godotengine.org/en/stable/tutorials/animation/animation_tree.html

## Migration Guide

* The serialized format of animation graphs has changed with the
addition of animation masks. To upgrade animation graph RON files, add
`mask` and `mask_groups` fields as appropriate. (They can be safely set
to zero.)
2024-09-02 17:10:34 +00:00
UkoeHB
49a06e9c76
Avoid reallocating spans buffer in TextPipeline (#15012)
# Objective

- Don't reallocate the spans vector every time TextPipeline updates a
buffer.

## Solution

- Cache the spans buffer in `TextPipeline`. This is possible through
some [rust
magic](https://users.rust-lang.org/t/how-to-cache-a-vectors-capacity/94478/10).
2024-09-02 17:02:06 +00:00
UkoeHB
3227c3de36
Don't reallocate scale factors in measure_text_system (#14999)
# Objective

- Reuse allocation of `scale_factors` in `measure_text_system`.

## Solution

- Move it to a `Local`.
2024-09-02 17:01:59 +00:00
UkoeHB
2b94a108ae
Reuse TextLayoutInfo in queue_text (#14997)
# Objective

Don't reallocate `TextLayoutInfo` every time it needs to be updated.

## Solution

Reuse existing allocation.
2024-09-02 17:01:56 +00:00
UkoeHB
f02d76a44d
Use cosmic-text shaping buffer (#14991)
# Objective

- Improve performance of `cosmic-text` integration.

## Solution

- Activate the `shape-run-cache` feature to improve amortized cost of
spawning/updating text.
2024-09-02 17:01:46 +00:00
ickshonpe
be100b8760
Resolve UI outlines using the correct target's viewport size (#14947)
# Objective
`resolve_outlines_system` wasn't updated when multi-window support was
added and it always uses the size of the primary window when resolving
viewport coords, regardless of the layout's camera target.

Fixes #14945

## Solution

It's awkward to get the viewport size of the target for an individual
node without walking the tree or adding extra fields to `Node`, so I
removed `resolve_outlines_system` and instead the outline values are
updated in `ui_layout_system`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-02 16:56:58 +00:00
Chris Russell
f1414cba23
Use #[doc(fake_variadic)] for SystemParamBuilder tuple impls. (#14962)
# Objective

Make the documentation for `SystemParamBuilder` nicer by combining the
tuple implementations into a single line of documentation.

## Solution

Use `#[doc(fake_variadic)]` for `SystemParamBuilder` tuple impls.


![image](https://github.com/user-attachments/assets/b4665861-c405-467f-b30b-82b4b1d99bf7)

(This got missed originally because #14050 and #14703 were open at the
same time.)
2024-09-02 16:51:23 +00:00
charlotte
a4640046fc
Adds ShaderStorageBuffer asset (#14663)
Adds a new `Handle<Storage>` asset type that can be used as a render
asset, particularly for use with `AsBindGroup`.

Closes: #13658 

# Objective

Allow users to create storage buffers in the main world without having
to access the `RenderDevice`. While this resource is technically
available, it's bad form to use in the main world and requires mixing
rendering details with main world code. Additionally, this makes storage
buffers easier to use with `AsBindGroup`, particularly in the following
scenarios:
- Sharing the same buffers between a compute stage and material shader.
We already have examples of this for storage textures (see game of life
example) and these changes allow a similar pattern to be used with
storage buffers.
- Preventing repeated gpu upload (see the previous easier to use `Vec`
`AsBindGroup` option).
- Allow initializing custom materials using `Default`. Previously, the
lack of a `Default` implement for the raw `wgpu::Buffer` type made
implementing a `AsBindGroup + Default` bound difficult in the presence
of buffers.

## Solution

Adds a new `Handle<Storage>` asset type that is prepared into a
`GpuStorageBuffer` render asset. This asset can either be initialized
with a `Vec<u8>` of properly aligned data or with a size hint. Users can
modify the underlying `wgpu::BufferDescriptor` to provide additional
usage flags.

## Migration Guide

The `AsBindGroup` `storage` attribute has been modified to reference the
new `Handle<Storage>` asset instead. Usages of Vec` should be converted
into assets instead.

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-09-02 16:46:34 +00:00
no-materials
3a8d5598ad
Interpolate WorldQuery path in docs of generated types (#14985)
# Objective

Fixes #14972

## Solution

Uses the `concat!` macro to interpolate the `path` variable.

## Testing

* Run `cargo doc --workspace --open`
* Check functionality of `WorldQuery` links within `NodeQueryItem`,
`NodeQueryReadOnly`, `NodeQueryReadOnlyItem` docs
2024-09-01 22:18:13 +00:00
UkoeHB
41474226c3
Optimize UI text measurement (#15003)
# Objective

- Avoid cloning the `CosmicBuffer` every time you create a new text
measurement.

## Solution

- Inject a buffer query when calculating layout so existing buffers can
be reused.

## Testing

- I tested the `text`, `text_debug`, and `text_wrap_debug` examples.
- I did not do a performance test.
2024-09-01 11:50:54 +00:00
charlotte
f0560b8e78
Ensure more explicit system ordering for preparing view target. (#15000)
Fixes #14993 (maybe). Adds a system ordering constraint that was missed
in the refactor in #14833. The theory here is that the single threaded
forces a topology that causes the prepare system to run before
`prepare_windows` in a way that causes issues. For whatever reason, this
appears to be unlikely when multi-threading is enabled.
2024-08-31 22:03:01 +00:00
MichiRecRoom
4bea611a43
Don't require going through bevy_animation::prelude to get to certain items in bevy_animation (#14979)
# Objective
* Fixes https://github.com/bevyengine/bevy/issues/14889

## Solution
Exposes `bevy_animation::{animatable, graph, transition}` to the world.

## Testing
- Did you test these changes? If so, how?
- These changes do not need testing, as they do not modify/add/remove
any functionality.
- ~~Are there any parts that need more testing?~~
- ~~How can other people (reviewers) test your changes? Is there
anything specific they need to know?~~
- ~~If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?~~

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-31 18:38:34 +00:00
BigWingBeat
ffe0f7f2ba
Fix compile error caused by incorrect feature flag in bevy_state (#14987)
# Objective

The `reflect` module in `bevy_state` is gated behind the `bevy_reflect`
feature, but the type exports from that module in the crate prelude are
erroneously gated behind the `bevy_app` feature, causing a compile error
when the `bevy_reflect` feature is disabled, but the `bevy_app` feature
is enabled.

## Solution

Change the feature gate to `bevy_reflect`.

## Testing

- Discovered by depending on `bevy_state` with `default-features =
false, features = ["bevy_app"]`
- Tested by running `cargo check -p bevy_state --no-default-features
--features bevy_app`
2024-08-30 18:57:08 +00:00
Zachary Harrold
bc13161416
Migrated NonZero* to NonZero<*> (#14978)
# Objective

- Fixes #14974

## Solution

- Replace all* instances of `NonZero*` with `NonZero<*>`

## Testing

- CI passed locally.

---

## Notes

Within the `bevy_reflect` implementations for `std` types,
`impl_reflect_value!()` will continue to use the type aliases instead,
as it inappropriately parses the concrete type parameter as a generic
argument. If the `ZeroablePrimitive` trait was stable, or the macro
could be modified to accept a finite list of types, then we could fully
migrate.
2024-08-30 02:37:47 +00:00
MichiRecRoom
c816cf9072
Reorganize some of bevy_animation's imports into a more consistent style (#14983)
# Objective
`bevy_animation` imports a lot of items - and it uses a very
inconsistent code style to do so.

## Solution
Changes the offending `use` statements to be more consistent across the
crate.

## Testing
- Did you test these changes? If so, how?
- No testing is needed beyond lint checks, and those finished
successfully.
- ~~Are there any parts that need more testing?~~
- ~~How can other people (reviewers) test your changes? Is there
anything specific they need to know?~~
- ~~If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?~~
2024-08-30 01:24:31 +00:00
akimakinai
147768adf6
Use CowArc::Static (#14981)
# Objective

- There's one occurence of `CowArc::Borrow` that wraps '&'static str`

## Solution

- Replaces it with `CowArc::Static`. I don't think this change is
important but I can't unsee it:)

## Testing

- `cargo check` compiles fine
2024-08-30 01:22:11 +00:00
Alix Bott
f2cf02408f
Fix observer unregistering unsetting archetype flags (#14963)
# Objective

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

## Solution

- Check that the archetypes don't contain any other observed components
before unsetting their flags

## Testing

- I added a regression test: `observer_despawn_archetype_flags`
2024-08-30 00:43:56 +00:00
Chris Juchem
e08497dc8f
Replace bevy_utils::CowArc with atomicow (#14977)
# Objective

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

## Solution

- Replace usages of `bevy_utils::CowArc` with `atomicow::CowArc`
- Remove bevy_utils::CowArc

## Testing

- `bevy_asset` test suite continues to pass.

---

## Migration Guide

`bevy_utils::CowArc` has moved to a new crate called
[atomicow](https://crates.io/crates/atomicow).
2024-08-30 00:43:07 +00:00
Robert Walter
9e78433427
Curve gizmos integration (#14971)
# Objective

- Add gizmos integration for the new `Curve` things in the math lib

## Solution

- Add the following methods
  - `curve_2d(curve, sample_times, color)`
  - `curve_3d(curve, sample_times, color)`
  - `curve_gradient_2d(curve, sample_times_with_colors)`
  - `curve_gradient_3d(curve, sample_times_with_colors)`

## Testing

- I added examples of the 2D and 3D variants of the gradient curve
gizmos to the gizmos examples.

## Showcase

### 2D


![image](https://github.com/user-attachments/assets/01a75706-a7b4-4fc5-98d5-18018185c877)

```rust
    let domain = Interval::EVERYWHERE;
    let curve = function_curve(domain, |t| Vec2::new(t, (t / 25.0).sin() * 100.0));
    let resolution = ((time.elapsed_seconds().sin() + 1.0) * 50.0) as usize;
    let times_and_colors = (0..=resolution)
        .map(|n| n as f32 / resolution as f32)
        .map(|t| (t - 0.5) * 600.0)
        .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
    gizmos.curve_gradient_2d(curve, times_and_colors);
```

### 3D


![image](https://github.com/user-attachments/assets/3fd23983-1ec9-46cd-baed-5b5e2dc935d0)

```rust
    let domain = Interval::EVERYWHERE;
    let curve = function_curve(domain, |t| {
        (Vec2::from((t * 10.0).sin_cos())).extend(t - 6.0)
    });
    let resolution = ((time.elapsed_seconds().sin() + 1.0) * 100.0) as usize;
    let times_and_colors = (0..=resolution)
        .map(|n| n as f32 / resolution as f32)
        .map(|t| t * 5.0)
        .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
    gizmos.curve_gradient_3d(curve, times_and_colors);
```
2024-08-29 16:48:22 +00:00
Robert Walter
565324daa3
Improve the gizmo for Plane3d, reusing grid (#14650)
# Objective

With the current implementation of `Plane3d` gizmos, it's really hard to
get a good feeling for big planes. Usually I tend to add more axes as a
user but that doesn't scale well and is pretty wasteful. It's hard to
recognize the plane in the distance here. Especially if there would've
been other rendered objects in the scene


![image](https://github.com/user-attachments/assets/b65b7015-c08c-46d7-aa27-c7c0d49b2021)

## Solution

- Since we got grid gizmos in the mean time, I went ahead and just
reused them here.

## Testing

I added an instance of the new `Plane3D` to the `3d_gizmos.rs` example.
If you want to look at it you need to look around a bit. I didn't
position it in the center since that was too crowded already.

---

## Showcase


![image](https://github.com/user-attachments/assets/e4982afe-7296-416c-9801-7dd85cd975c1)

## Migration Guide

The optional builder methods on 

```rust

gizmos.primitive_3d(&Plane3d { }, ...);

```

changed from

- `segment_length`
- `segment_count`
- `axis_count`

to 

- `cell_count`
- `spacing`
2024-08-29 15:51:36 +00:00
Shane
e600e2c1b1
Move the default LogPlugin filter to a public constant (#14958)
# Objective

This moves the default `LogPlugin` filter to be a public constant so
that it can be updated and referenced from outside code without changes
across releases:

```
fn main() {
    App::new().add_plugins(
        DefaultPlugins
            .set(bevy::log::LogPlugin {
                filter: format!("{},mylogs=error", bevy::log::LogPlugin::DEFAULT_FILTER),
                ..default()
            })).run();
}
```

## Testing

Tested with `cargo run -p ci`
2024-08-29 12:15:49 +00:00
Chris Russell
4be8e497ca
SystemParamBuilder - Allow deriving a SystemParamBuilder struct when deriving SystemParam. (#14818)
# Objective

Allow `SystemParamBuilder` implementations for custom system parameters
created using `#[derive(SystemParam)]`.

## Solution

Extend the derive macro to accept a `#[system_param(builder)]`
attribute. When present, emit a builder type with a field corresponding
to each field of the param.

## Example

```rust
#[derive(SystemParam)]
#[system_param(builder)]
struct CustomParam<'w, 's> {
    query: Query<'w, 's, ()>,
    local: Local<'s, usize>,
}

let system = (CustomParamBuilder {
    local: LocalBuilder(100),
    query: QueryParamBuilder::new(|builder| {
        builder.with::<A>();
    }),
},)
    .build_state(&mut world)
    .build_system(|param: CustomParam| *param.local + param.query.iter().count());
```
2024-08-28 18:24:52 +00:00
akimakinai
4648f7bf72
Make TrackedRenderPass::set_vertex_buffer aware of slice size (#14916)
# Objective

- Fixes #14841

## Solution

- Compute BufferSlice size manually and use it for comparison in
`TrackedRenderPass`

## Testing

- Gizmo example does not crash with #14721 (without system ordering),
and `slice` computes correct size there

---

## Migration Guide

- `TrackedRenderPass::set_vertex_buffer` function has been modified to
update vertex buffers when the same buffer with the same offset is
provided, but its size has changed. Some existing code may rely on the
previous behavior, which did not update the vertex buffer in this
scenario.

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-08-28 11:41:42 +00:00
Allen Pocket
d93b78a66e
Remove unnecessary muts in RenderSet::QueueMeshes (#14953)
# Objective

Fixes #14952
2024-08-28 11:38:38 +00:00
Zachary Harrold
371e07e77d
Updated FromWorld Documentation to mention Default (#14954)
# Objective

- Fixes #14860

## Solution

- Added a line of documentation to `FromWorld`'s trait definition
mention the `Default` blanket implementation.
- Added custom documentation to the `from_world` method for the
`Default` blanket implementation. This ensures when inspecting the
`from_world` function within an IDE, the tooltip will explicitly state
the `default()` method will be used for any `Default` types.

## Testing

- CI passes.
2024-08-28 11:37:31 +00:00
Robert Walter
210c79c9f9
Gizmos: arc_2d utility helpers (#14932)
# Objective

Since https://github.com/bevyengine/bevy/pull/14731 is merged, it
unblocked a few utility methods for 2D arcs. In 2D the pendant to
`long_arc_3d_between` and `short_arc_3d_between` are missing. Since
`arc_2d` can be a bit hard to use, this PR is trying to plug some holes
in the `arcs` API.

## Solution

Implement

- `long_arc_2d_between(center, from, tp, color)`
- `short_arc_2d_between(center, from, tp, color)`

## Testing

- There are new doc tests
- The `2d_gizmos` example has been extended a bit to include a few more
arcs which can easily be checked with respect to the grid

---

## Showcase


![image](https://github.com/user-attachments/assets/b90ad8b1-86c2-4304-a481-4f9a5246c457)

Code related to the screenshot (from outer = first line to inner = last
line)

```rust
    my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
    my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
    my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
```
2024-08-28 11:33:11 +00:00
Chris Russell
419359b9a7
SystemParamBuilder - Enable type inference of closure parameter when building dynamic systems (#14820)
# Objective

When building a system from `SystemParamBuilder`s and defining the
system as a closure, the compiler should be able to infer the parameter
types from the builder types.

## Solution

Create methods for each arity that take an argument that implements both
`SystemParamFunction` as well as `FnMut(SystemParamItem<P>,...)`. The
explicit `FnMut` constraint will allow the compiler to infer the
necessary higher-ranked lifetimes along with the parameter types.

I wanted to show that this was possible, but I can't tell whether it's
worth the complexity. It requires a separate method for each arity,
which pollutes the docs a bit:
![SystemState build_system
docs](https://github.com/user-attachments/assets/5069b749-7ec7-47e3-a5e4-1a4c78129f78)

## Example

```rust
let system = (LocalBuilder(0u64), ParamBuilder::local::<u64>())
    .build_state(&mut world)
    .build_system(|a, b| *a + *b + 1);
```
2024-08-28 01:37:52 +00:00
Robert Walter
8895113784
Use Isometry in bevy_gizmos wherever we can (#14676)
# Objective

- Solves the last bullet in and closes #14319
- Make better use of the `Isometry` types
- Prevent issues like #14655
- Probably simplify and clean up a lot of code through the use of Gizmos
as well (i.e. the 3D gizmos for cylinders circles & lines don't connect
well, probably due to wrong rotations)

## Solution

- go through the `bevy_gizmos` crate and give all methods a slight
workover

## Testing

- For all the changed examples I run `git switch main && cargo rr
--example <X> && git switch <BRANCH> && cargo rr --example <X>` and
compare the visual results
- Check if all doc tests are still compiling
- Check the docs in general and update them !!! 

---

## Migration Guide

The gizmos methods function signature changes as follows:

- 2D
- if it took `position` & `rotation_angle` before ->
`Isometry2d::new(position, Rot2::radians(rotation_angle))`
- if it just took `position` before ->
`Isometry2d::from_translation(position)`
- 3D
- if it took `position` & `rotation` before ->
`Isometry3d::new(position, rotation)`
- if it just took `position` before ->
`Isometry3d::from_translation(position)`
2024-08-28 01:37:19 +00:00
robtfm
45281e62d7
Commands::send_event (#14933)
# Objective

sending events tends to be low-frequency so ergonomics can be
prioritized over efficiency.
add `Commands::send_event` to send any type of event without needing a
writer in hand.

i don't know how we feel about these kind of ergonomic things, i add
this to all my projects and find it useful. adding `mut
this_particular_event_writer: EventWriter<ThisParticularEvent>` every
time i want to send something is unnecessarily cumbersome.
it also simplifies the "send and receive in the same system" pattern
significantly.

basic example before:
```rs
fn my_func(
    q: Query<(Entity, &State)>,
    mut damage_event_writer: EventWriter<DamageEvent>,
    mut heal_event_writer: EventWriter<HealEvent>,
) {
    for (entity, state) in q.iter() {
        if let Some(damage) = state.get_damage() {
            damage_event_writer.send(DamageEvent { entity, damage });
        }

        if let Some(heal) = state.get_heal() {
            heal_event_writer.send(HealEvent { entity, heal });
        }
    }
}
```

basic example after:
```rs
import bevy::ecs::event::SendEventEx;

fn my_func(
    mut commands: Commands,
    q: Query<(Entity, &State)>,
) {
    for (entity, state) in q.iter() {
        if let Some(damage) = state.get_damage() {
            commands.send_event(DamageEvent { entity, damage });
        }

        if let Some(heal) = state.get_heal() {
            commands.send_event(HealEvent { entity, heal });
        }
    }
}
```

send/receive in the same system before:
```rs
fn send_and_receive_param_set(
    mut param_set: ParamSet<(EventReader<DebugEvent>, EventWriter<DebugEvent>)>,
) {
    // We must collect the events to resend, because we can't access the writer while we're iterating over the reader.
    let mut events_to_resend = Vec::new();

    // This is p0, as the first parameter in the `ParamSet` is the reader.
    for event in param_set.p0().read() {
        if event.resend_from_param_set {
            events_to_resend.push(event.clone());
        }
    }

    // This is p1, as the second parameter in the `ParamSet` is the writer.
    for mut event in events_to_resend {
        event.times_sent += 1;
        param_set.p1().send(event);
    }
}
```

after:
```rs
use bevy::ecs::event::SendEventEx;

fn send_via_commands_and_receive(
    mut reader: EventReader<DebugEvent>,
    mut commands: Commands,
) {
    for event in reader.read() {
        if event.resend_via_commands {
            commands.send_event(DebugEvent {
                times_sent: event.times_sent + 1,
                ..event.clone()
            });
        }
    }
}
```

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-08-27 23:43:40 +00:00
François Mockers
e63d7c340f
don't use padding for layout (#14944)
# Objective

- Fixes #14792 
- Padding is already handled by taffy, don't handle it also on Bevy side

## Solution

- Remove extra computation added in
https://github.com/bevyengine/bevy/pull/14777
2024-08-27 22:41:23 +00:00
Carter Anderson
9cdb915809
Required Components (#14791)
## Introduction

This is the first step in my [Next Generation Scene / UI
Proposal](https://github.com/bevyengine/bevy/discussions/14437).

Fixes https://github.com/bevyengine/bevy/issues/7272 #14800.

Bevy's current Bundles as the "unit of construction" hamstring the UI
user experience and have been a pain point in the Bevy ecosystem
generally when composing scenes:

* They are an additional _object defining_ concept, which must be
learned separately from components. Notably, Bundles _are not present at
runtime_, which is confusing and limiting.
* They can completely erase the _defining component_ during Bundle init.
For example, `ButtonBundle { style: Style::default(), ..default() }`
_makes no mention_ of the `Button` component symbol, which is what makes
the Entity a "button"!
* They are not capable of representing "dependency inheritance" without
completely non-viable / ergonomically crushing nested bundles. This
limitation is especially painful in UI scenarios, but it applies to
everything across the board.
* They introduce a bunch of additional nesting when defining scenes,
making them ugly to look at
* They introduce component name "stutter": `SomeBundle { component_name:
ComponentName::new() }`
* They require copious sprinklings of `..default()` when spawning them
in Rust code, due to the additional layer of nesting

**Required Components** solve this by allowing you to define which
components a given component needs, and how to construct those
components when they aren't explicitly provided.

This is what a `ButtonBundle` looks like with Bundles (the current
approach):

```rust
#[derive(Component, Default)]
struct Button;

#[derive(Bundle, Default)]
struct ButtonBundle {
    pub button: Button,
    pub node: Node,
    pub style: Style,
    pub interaction: Interaction,
    pub focus_policy: FocusPolicy,
    pub border_color: BorderColor,
    pub border_radius: BorderRadius,
    pub image: UiImage,
    pub transform: Transform,
    pub global_transform: GlobalTransform,
    pub visibility: Visibility,
    pub inherited_visibility: InheritedVisibility,
    pub view_visibility: ViewVisibility,
    pub z_index: ZIndex,
}

commands.spawn(ButtonBundle {
    style: Style {
        width: Val::Px(100.0),
        height: Val::Px(50.0),
        ..default()
    },
    focus_policy: FocusPolicy::Block,
    ..default()
})
```

And this is what it looks like with Required Components:

```rust
#[derive(Component)]
#[require(Node, UiImage)]
struct Button;

commands.spawn((
    Button,
    Style { 
        width: Val::Px(100.0),
        height: Val::Px(50.0),
        ..default()
    },
    FocusPolicy::Block,
));
```

With Required Components, we mention only the most relevant components.
Every component required by `Node` (ex: `Style`, `FocusPolicy`, etc) is
automatically brought in!

### Efficiency

1. At insertion/spawn time, Required Components (including recursive
required components) are initialized and inserted _as if they were
manually inserted alongside the given components_. This means that this
is maximally efficient: there are no archetype or table moves.
2. Required components are only initialized and inserted if they were
not manually provided by the developer. For the code example in the
previous section, because `Style` and `FocusPolicy` are inserted
manually, they _will not_ be initialized and inserted as part of the
required components system. Efficient!
3. The "missing required components _and_ constructors needed for an
insertion" are cached in the "archetype graph edge", meaning they aren't
computed per-insertion. When a component is inserted, the "missing
required components" list is iterated (and that graph edge (AddBundle)
is actually already looked up for us during insertion, because we need
that for "normal" insert logic too).

### IDE Integration

The `#[require(SomeComponent)]` macro has been written in such a way
that Rust Analyzer can provide type-inspection-on-hover and `F12` /
go-to-definition for required components.

### Custom Constructors

The `require` syntax expects a `Default` constructor by default, but it
can be overridden with a custom constructor:

```rust
#[derive(Component)]
#[require(
    Node,
    Style(button_style),
    UiImage
)]
struct Button;

fn button_style() -> Style {
    Style {
        width: Val::Px(100.0),
        ..default()
    }
}
```

### Multiple Inheritance

You may have noticed by now that this behaves a bit like "multiple
inheritance". One of the problems that this presents is that it is
possible to have duplicate requires for a given type at different levels
of the inheritance tree:

```rust
#[derive(Component)
struct X(usize);

#[derive(Component)]
#[require(X(x1))
struct Y;

fn x1() -> X {
    X(1)
}

#[derive(Component)]
#[require(
    Y,
    X(x2),
)]
struct Z;

fn x2() -> X {
    X(2)
}

// What version of X is inserted for Z?
commands.spawn(Z);
```

This is allowed (and encouraged), although this doesn't appear to occur
much in practice. First: only one version of `X` is initialized and
inserted for `Z`. In the case above, I think we can all probably agree
that it makes the most sense to use the `x2` constructor for `X`,
because `Y`'s `x1` constructor exists "beneath" `Z` in the inheritance
hierarchy; `Z`'s constructor is "more specific".

The algorithm is simple and predictable:

1. Use all of the constructors (including default constructors) directly
defined in the spawned component's require list
2. In the order the requires are defined in `#[require()]`, recursively
visit the require list of each of the components in the list (this is a
depth Depth First Search). When a constructor is found, it will only be
used if one has not already been found.

From a user perspective, just think about this as the following:

1. Specifying a required component constructor for `Foo` directly on a
spawned component `Bar` will result in that constructor being used (and
overriding existing constructors lower in the inheritance tree). This is
the classic "inheritance override" behavior people expect.
2. For cases where "multiple inheritance" results in constructor
clashes, Components should be listed in "importance order". List a
component earlier in the requirement list to initialize its inheritance
tree earlier.

Required Components _does_ generally result in a model where component
values are decoupled from each other at construction time. Notably, some
existing Bundle patterns use bundle constructors to initialize multiple
components with shared state. I think (in general) moving away from this
is necessary:

1. It allows Required Components (and the Scene system more generally)
to operate according to simple rules
2. The "do arbitrary init value sharing in Bundle constructors" approach
_already_ causes data consistency problems, and those problems would be
exacerbated in the context of a Scene/UI system. For cases where shared
state is truly necessary, I think we are better served by observers /
hooks.
3. If a situation _truly_ needs shared state constructors (which should
be rare / generally discouraged), Bundles are still there if they are
needed.

## Next Steps

* **Require Construct-ed Components**: I have already implemented this
(as defined in the [Next Generation Scene / UI
Proposal](https://github.com/bevyengine/bevy/discussions/14437). However
I've removed `Construct` support from this PR, as that has not landed
yet. Adding this back in requires relatively minimal changes to the
current impl, and can be done as part of a future Construct pr.
* **Port Built-in Bundles to Required Components**: This isn't something
we should do right away. It will require rethinking our public
interfaces, which IMO should be done holistically after the rest of Next
Generation Scene / UI lands. I think we should merge this PR first and
let people experiment _inside their own code with their own Components_
while we wait for the rest of the new scene system to land.
* **_Consider_ Automatic Required Component Removal**: We should
evaluate _if_ automatic Required Component removal should be done. Ex:
if all components that explicitly require a component are removed,
automatically remove that component. This issue has been explicitly
deferred in this PR, as I consider the insertion behavior to be
desirable on its own (and viable on its own). I am also doubtful that we
can find a design that has behavior we actually want. Aka: can we
_really_ distinguish between a component that is "only there because it
was automatically inserted" and "a component that was necessary / should
be kept". See my [discussion response
here](https://github.com/bevyengine/bevy/discussions/14437#discussioncomment-10268668)
for more details.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2024-08-27 20:22:23 +00:00
Sam Pettersson
5f061ea008
Fix Adreno 642L crash (#14937)
# Objective

The Android example on Adreno 642L currently crashes on startup.

Previous PRs #14176 and #13323 have adressed this specific crash
occurring on some Adreno GPUs, that fix works as it should but isn't
applied when to the GPU name contains a suffix like in the case of
`642L`.

## Solution

- Amending the logic to filter out any parts of the GPU name not
containing digits thus enabling the fix on `642L`.

## Testing

- Ran the Android example on a Nothing Phone 1. Before this change it
crashed, after it works as intended.

---------

Co-authored-by: Sam Pettersson <sam.pettersson@geoguessr.com>
2024-08-27 17:35:01 +00:00
Erick Z
1690b28e9f
Fixing Curve trait not being object safe. (#14939)
# Objective

- `Curve<T>` was meant to be object safe, but one of the latest commits
made it not object safe.
- When trying to use `Curve<T>` as `&dyn Curve<T>` this compile error is
raised:
```
error[E0038]: the trait `curve::Curve` cannot be made into an object
    --> crates/bevy_math/src/curve/mod.rs:1025:20
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
    --> crates/bevy_math/src/curve/mod.rs:60:8
     |
23   | pub trait Curve<T> {
     |           ----- this trait cannot be made into an object...
...
60   |     fn sample_iter(&self, iter: impl IntoIterator<Item = f32>) -> impl Iterator<Item = Option<T>> {
     |        ^^^^^^^^^^^                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `sample_iter` references an `impl Trait` type in its return type
     |        |
     |        ...because method `sample_iter` has generic type parameters
...
```

## Solution

- Making `Curve<T>` object safe again by adding `Self: Sized` to newly
added methods.

## Testing

- Added new test that ensures the `Curve<T>` trait can be made into an
objet.
2024-08-27 13:29:02 +00:00
Giacomo Stevanato
e320fa0738
Fix query transmute from table to archetype iteration unsoundness (#14615)
# Objective

- Fixes #14348 
- Fixes #14528
- Less complex (but also likely less performant) alternative to #14611

## Solution

- Add a `is_dense` field flag to `QueryIter` indicating whether it is
dense or not, that is whether it can perform dense iteration or not;
- Check this flag any time iteration over a query is performed.

---

It would be nice if someone could try benching this change to see if it
actually matters.

~Note that this not 100% ready for mergin, since there are a bunch of
safety comments on the use of the various `IS_DENSE` for checks that
still need to be updated.~ This is ready modulo benchmarks

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-27 00:58:40 +00:00
robtfm
f06cd448db
drop pending asset loads (#14808)
# Objective

when handles for loading assets are dropped, we currently wait until
load is completed before dropping the handle. drop asset-load tasks
immediately

## Solution

- track tasks for loading assets and drop them immediately when all
handles are dropped.
~~- use `join_all` in `gltf_loader.rs` to allow it to yield and be
dropped.~~

doesn't cover all the load apis - for those it doesn't cover the task
will still be detached and will still complete before the result is
discarded.

separated out from #13170
2024-08-27 00:16:44 +00:00
Chris Russell
6ddbf9771a
SystemParamBuilder - Support buildable Vec parameters (#14821)
# Objective

Allow dynamic systems to take lists of system parameters whose length is
not known at compile time.

This can be used for building a system that runs a script defined at
runtime, where the script needs a variable number of query parameters.
It can also be used for building a system that collects a list of
plugins at runtime, and provides a parameter to each one.

This is most useful today with `Vec<Query<FilteredEntityMut>>`. It will
be even more useful with `Vec<DynSystemParam>` if #14817 is merged,
since the parameters in the list can then be of different types.

## Solution

Implement `SystemParam` and `SystemParamBuilder` for `Vec` and
`ParamSet<Vec>`.

## Example

```rust
let system = (vec![
    QueryParamBuilder::new_box(|builder| {
        builder.with::<B>().without::<C>();
    }),
    QueryParamBuilder::new_box(|builder| {
        builder.with::<C>().without::<B>();
    }),
],)
    .build_state(&mut world)
    .build_system(|params: Vec<Query<&mut A>>| {
        let mut count: usize = 0;
        params
            .into_iter()
            .for_each(|mut query| count += query.iter_mut().count());
        count
    });
```
2024-08-27 00:16:29 +00:00
kivi
95ef8f6975
rename Drop to bevy::picking::events::DragDrop to unclash std::ops:Drop (#14926)
# Objective

- Fixes #14902
- > #14686 Introduced a name clash when using use bevy::prelude::*;


## Solution

- renamed `bevy::picking::events::Drop`
`bevy::picking::events::DragDrop`

 
## Testing

- Not being used in tests or examples, so I just compiled.

---

</details>

## Migration Guide

- Rename `Drop` to `DragDrop`
- `bevy::picking::events::Drop` is now `bevy::picking::events::DragDrop`
2024-08-26 18:38:56 +00:00
Robert Walter
20c5270a0c
add Interval::UNIT constant (#14923)
# Objective

This is a value that is and will be used as a domain of curves pretty
often. By adding it as a dedicated constant we can get rid of some
`unwraps` and function calls.

## Solution

added `Interval::UNIT`

## Testing

I replaced all occurrences of `interval(0.0, 1.0).unwrap()` with the new
`Interval::UNIT` constant in tests and doc tests.
2024-08-26 18:37:16 +00:00
Alix Bott
12f005a024
Add condition_changed and condition_became_true to common_conditions (#14917)
# Objective

- I needed to run a system whenever a specific condition became true
after being previously false.
- Other users might also need to run a system when a condition changes,
regardless of if it became true or false.

## Solution

- This adds two systems to common_conditions:
- `condition_changed` that changes whenever the inner condition changes
- `condition_became_true` that returns true whenever the inner condition
becomes true after previously being false

## Testing

- I added a doctest for each function

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-08-26 18:32:44 +00:00
extrawurst
23979b8160
Allow removing asset from embedded asset registry (#14912)
# Objective

- Allow not only inserting `Data` into `EmbeddedAssetRegistry` and `Dir`
in turn but now also removing it again.
- This way when used to embed asset data from *somewhere* but not load
it using the conventional means via `AssetServer` (which I observed
takes ownership of the `Data`) the `Data` does not need to stay in
memory of the `EmbeddedAssetRegistry` throughout the lifetime of the
application.

## Solution

- added the `remove_asset` functions in `EmbeddedAssetRegistry` and
`Dir`

## Testing

- added a module unittest
- does this require changes if build with feature `embedded_watcher`?
2024-08-26 18:29:05 +00:00
Shane
484721be80
Have EntityCommands methods consume self for easier chaining (#14897)
# Objective

Fixes #14883

## Solution

Pretty simple update to `EntityCommands` methods to consume `self` and
return it rather than taking `&mut self`. The things probably worth
noting:

* I added `#[allow(clippy::should_implement_trait)]` to the `add` method
because it causes a linting conflict with `std::ops::Add`.
* `despawn` and `log_components` now return `Self`. I'm not sure if
that's exactly the desired behavior so I'm happy to adjust if that seems
wrong.

## Testing

Tested with `cargo run -p ci`. I think that should be sufficient to call
things good.

## Migration Guide

The most likely migration needed is changing code from this:

```
        let mut entity = commands.get_or_spawn(entity);

        if depth_prepass {
            entity.insert(DepthPrepass);
        }
        if normal_prepass {
            entity.insert(NormalPrepass);
        }
        if motion_vector_prepass {
            entity.insert(MotionVectorPrepass);
        }
        if deferred_prepass {
            entity.insert(DeferredPrepass);
        }
```

to this:

```
        let mut entity = commands.get_or_spawn(entity);

        if depth_prepass {
            entity = entity.insert(DepthPrepass);
        }
        if normal_prepass {
            entity = entity.insert(NormalPrepass);
        }
        if motion_vector_prepass {
            entity = entity.insert(MotionVectorPrepass);
        }
        if deferred_prepass {
            entity.insert(DeferredPrepass);
        }
```

as can be seen in several of the example code updates here. There will
probably also be instances where mutable `EntityCommands` vars no longer
need to be mutable.
2024-08-26 18:24:59 +00:00
Zachary Harrold
44620dd6ae
Split GenericTypeCell::get_or_insert into smaller pieces (#14865)
# Objective

Based on the discussion in #14864, I wanted to experiment with the core
`GenericTypeCell` type, whose `get_or_insert` method accounted for 2% of
the final binary size of the `3d_scene` example. The reason for this
large percentage is likely because the type is fundamental to the rest
of Bevy while having 3 generic parameters (the type stored `T`, the type
to retrieve `G`, and the function used to insert a new value `F`).

- Acts on #14864 

## Solution

- Split `get_or_insert` into smaller functions with minimised
parameterisation. These new functions are private as to preserve the
public facing API, but could be exposed if desired.

## Testing

- Ran CI locally.
- Used `cargo bloat --release --example 3d_scene -n 100000
--message-format json > out.json` and @cart's [bloat
analyzer](https://gist.github.com/cart/722756ba3da0e983d207633e0a48a8ab)
to measure a 428KiB reduction in binary size when compiling on Windows
10.
- ~I have _not_ benchmarked to determine if this improves/hurts
performance.~ See
[below](https://github.com/bevyengine/bevy/pull/14865#issuecomment-2306083606).

## Notes

In my opinion this seems like a good test-case for the concept of
debloating generics within the Bevy codebase. I believe the performance
impact here is negligible in either direction (at runtime and compile
time), but the binary reduction is measurable and quite significant for
a relatively minor change in code.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-08-26 18:20:01 +00:00
Robert Walter
96f1fd73cb
Add methods to sample curves from IntoIterator types (#14815)
# Objective

Citing @mweatherley 

> As mentioned before, a multi-sampling function in the API which takes
an iterator is probably something we want (e.g. `sample_iter(iter: impl
IntoIterator<Item = f32>) -> impl IntoIterator<Item = T> { //... }`, but
there are some design choices to be made on the details (e.g. does this
filter out points that aren't in the domain? does it do sorting? etc.)

## Solution

I think the most flexible solution for end users is to expose all the
`sample_...` functions with an `iter` equivalent, so we'll have

- `sample_iter`
- `sample_iter_unchecked`
- `sample_iter_clamped`

Answering some questions from the original idea:

> does this filter out points that aren't in the domain?

With the methods the user has the choice to just sample or if they want
to filter out invalid types us `sample_iter` and then apply `filter_map`
to the iterator returned themselves.

> does it do sorting?

I think it's the same thing. If the user wants it, they need to do it
themselves by either collecting and sorting a `Vec` or using
`itertools`. I think there is a legit use case for "please sample me
this collection of points that are unordered" and we would destroy it if
we take away to much agency from users by sorting for them

## Testing

- Added a test which covers all three methods
2024-08-26 18:08:41 +00:00
JoshValjosh
3540b87e17
Add bevy_picking sprite backend (#14757)
# Objective

Add `bevy_picking` sprite backend as part of the `bevy_mod_picking`
upstreamening (#12365).

## Solution

More or less a copy/paste from `bevy_mod_picking`, with the changes
[here](https://github.com/aevyrie/bevy_mod_picking/pull/354). I'm
putting that link here since those changes haven't yet made it through
review, so should probably be reviewed on their own.

## Testing

I couldn't find any sprite-backend-specific tests in `bevy_mod_picking`
and unfortunately I'm not familiar enough with Bevy's testing patterns
to write tests for code that relies on windowing and input. I'm willing
to break the pointer hit system into testable blocks and add some more
modular tests if that's deemed important enough to block, otherwise I
can open an issue for adding tests as follow-up.

## Follow-up work

- More docs/tests
- Ignore pick events on transparent sprite pixels with potential opt-out

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
2024-08-26 18:01:32 +00:00
Robert Walter
6819e998c0
Fix arc_2d Gizmos (#14731)
# Objective

`arc_2d` wasn't actually doing what the docs were saying. The arc wasn't
offset by what was previously `direction_angle` but by `direction_angle
- arc_angle / 2.0`. This meant that the arcs center was laying on the
`Vec2::Y` axis and then it was offset. This was probably done to fit the
behavior of the `Arc2D` primitive. I would argue that this isn't
desirable for the plain `arc_2d` gizmo method since

- a) the docs get longer to explain the weird centering
- b) the mental model the user has to know gets bigger with more
implicit assumptions

given the code

```rust
    my_gizmos.arc_2d(Vec2::ZERO, 0.0, FRAC_PI_2, 75.0, ORANGE_RED);
```

we get


![image](https://github.com/user-attachments/assets/84894c6d-42e4-451b-b3e2-811266486ede)

where after the fix with

```rust
    my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 75.0, ORANGE_RED);
```

we get


![image](https://github.com/user-attachments/assets/16b0aba0-f7b5-4600-ac49-a22be0315c40)

To get the same result with the previous implementation you would have
to randomly add `arc_angle / 2.0` to the `direction_angle`.

```rust
    my_gizmos.arc_2d(Vec2::ZERO, FRAC_PI_4, FRAC_PI_2, 75.0, ORANGE_RED);
```

This makes constructing similar helping functions as they already exist
in 3D like

- `long_arc_2d_between`
- `short_arc_2d_between`

 much harder.

## Solution

- Make the arc really start at `Vec2::Y * radius` in counter-clockwise
direction + offset by an angle as the docs state it
- Use `Isometry2d` instead of `position : Vec2` and `direction_angle :
f32` to reduce the chance of messing up rotation/translation
- Adjust the docs for the changes above
- Adjust the gizmo rendering of some primitives

## Testing

- check `2d_gizmos.rs` and `render_primitives.rs` examples

## Migration Guide

- users have to adjust their usages of `arc_2d`:
  - before: 
  ```rust
  arc_2d(
    pos,
    angle,
    arc_angle,
    radius,
    color
  )
  ```
  - after: 
  ```rust
  arc_2d(
// this `+ arc_angle * 0.5` quirk is only if you want to preserve the
previous behavior
    // with the new API.
// feel free to try to fix this though since your current calls to this
function most likely
// involve some computations to counter-act that quirk in the first
place
    Isometry2d::new(pos, Rot2::radians(angle + arc_angle * 0.5),
    arc_angle,
    radius,
    color
  )
  ```
2024-08-26 17:57:57 +00:00
Stepan Koltsov
2e36b2719c
ImageSampler::init_descriptor (#11113)
Shortcut to avoid repetition in code like
https://github.com/bevyengine/bevy/pull/11109.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-26 17:56:37 +00:00
JMS55
6cc96f4c1f
Meshlet software raster + start of cleanup (#14623)
# Objective
- Faster meshlet rasterization path for small triangles
- Avoid having to allocate and write out a triangle buffer
- Refactor gpu_scene.rs

## Solution
- Replace the 32bit visbuffer texture with a 64bit visbuffer buffer,
where the left 32 bits encode depth, and the right 32 bits encode the
existing cluster + triangle IDs. Can't use 64bit textures, wgpu/naga
doesn't support atomic ops on textures yet.
- Instead of writing out a buffer of packed cluster + triangle IDs (per
triangle) to raster, the culling pass now writes out a buffer of just
cluster IDs (per cluster, so less memory allocated, cheaper to write
out).
  - Clusters for software raster are allocated from the left side
- Clusters for hardware raster are allocated in the same buffer, from
the right side
- The buffer size is fixed at MeshletPlugin build time, and should be
set to a reasonable value for your scene (no warning on overflow, and no
good way to determine what value you need outside of renderdoc - I plan
to fix this in a future PR adding a meshlet stats overlay)
- Currently I don't have a heuristic for software vs hardware raster
selection for each cluster. The existing code is just a placeholder. I
need to profile on a release scene and come up with a heuristic,
probably in a future PR.
- The culling shader is getting pretty hard to follow at this point, but
I don't want to spend time improving it as the entire shader/pass is
getting rewritten/replaced in the near future.
- Software raster is a compute workgroup per-cluster. Each workgroup
loads and transforms the <=64 vertices of the cluster, and then
rasterizes the <=64 triangles of the cluster.
- Two variants are implemented: Scanline for clusters with any larger
triangles (still smaller than hardware is good at), and brute-force for
very very tiny triangles
- Once the shader determines that a pixel should be filled in, it does
an atomicMax() on the visbuffer to store the results, copying how Nanite
works
- On devices with a low max workgroups per dispatch limit, an extra
compute pass is inserted before software raster to convert from a 1d to
2d dispatch (I don't think 3d would ever be necessary).
- I haven't implemented the top-left rule or subpixel precision yet, I'm
leaving that for a future PR since I get usable results without it for
now
- Resources used:
https://kristoffer-dyrkorn.github.io/triangle-rasterizer and chapters
6-8 of
https://fgiesen.wordpress.com/2013/02/17/optimizing-sw-occlusion-culling-index
- Hardware raster now spawns 64*3 vertex invocations per meshlet,
instead of the actual meshlet vertex count. Extra invocations just
early-exit.
- While this is slower than the existing system, hardware draws should
be rare now that software raster is usable, and it saves a ton of memory
using the unified cluster ID buffer. This would be fixed if wgpu had
support for mesh shaders.
- Instead of writing to a color+depth attachment, the hardware raster
pass also does the same atomic visbuffer writes that software raster
uses.
- We have to bind a dummy render target anyways, as wgpu doesn't
currently support render passes without any attachments
- Material IDs are no longer written out during the main rasterization
passes.
- If we had async compute queues, we could overlap the software and
hardware raster passes.
- New material and depth resolve passes run at the end of the visbuffer
node, and write out view depth and material ID depth textures

### Misc changes
- Fixed cluster culling importing, but never actually using the previous
view uniforms when doing occlusion culling
- Fixed incorrectly adding the LOD error twice when building the meshlet
mesh
- Splitup gpu_scene module into meshlet_mesh_manager, instance_manager,
and resource_manager
- resource_manager is still too complex and inefficient (extract and
prepare are way too expensive). I plan on improving this in a future PR,
but for now ResourceManager is mostly a 1:1 port of the leftover
MeshletGpuScene bits.
- Material draw passes have been renamed to the more accurate material
shade pass, as well as some other misc renaming (in the future, these
will be compute shaders even, and not actual draw calls)

---

## Migration Guide
- TBD (ask me at the end of the release for meshlet changes as a whole)

---------

Co-authored-by: vero <email@atlasdostal.com>
2024-08-26 17:54:34 +00:00
Sludge
7bb76ab74b
Add VertexBufferLayout::offset_locations (#9805)
# Objective

When using instancing, 2 `VertexBufferLayout`s are needed, one for
per-vertex and one for per-instance data. Shader locations of all
attributes must not overlap, so one of the layouts needs to start its
locations at an offset. However,
`VertexBufferLayout::from_vertex_formats` will always start locations at
0, requiring manual adjustment, which is currently pretty verbose.

## Solution

Add `VertexBufferLayout::offset_locations`, which adds an offset to all
attribute locations.

Code using this method looks like this:

```rust
VertexState {
    shader: BACKBUFFER_SHADER_HANDLE.typed(),
    shader_defs: Vec::new(),
    entry_point: "vertex".into(),
    buffers: vec![
        VertexBufferLayout::from_vertex_formats(
            VertexStepMode::Vertex,
            [VertexFormat::Float32x2],
        ),
        VertexBufferLayout::from_vertex_formats(
            VertexStepMode::Instance,
            [VertexFormat::Float32x2, VertexFormat::Float32x3],
        )
        .offset_locations(1),
    ],
}
```

Alternative solutions include:

- Pass the starting location to `from_vertex_formats` – this is a bit
simpler than my solution here, but most calls don't need an offset, so
they'd always pass 0 there.
- Do nothing and make the user hand-write this.

---

## Changelog

- Add `VertexBufferLayout::offset_locations` to simplify buffer layout
construction when using instancing.

---------

Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-26 17:54:33 +00:00
charlotte
1caa64d948
Refactor AsBindGroup to use a associated SystemParam. (#14909)
# Objective

Adding more features to `AsBindGroup` proc macro means making the trait
arguments uglier. Downstream implementors of the trait without the proc
macro might want to do different things than our default arguments.

## Solution

Make `AsBindGroup` take an associated `Param` type.

## Migration Guide

`AsBindGroup` now allows the user to specify a `SystemParam` to be used
for creating bind groups.
2024-08-25 20:16:34 +00:00
Gino Valente
3892adcb47
bevy_reflect: Add Type type (#14838)
# Objective

Closes #7622.

I was working on adding support for reflecting generic functions and
found that I wanted to use an argument's `TypeId` for hashing and
comparison, but its `TypePath` for debugging and error messaging.

While I could just keep them separate, place them in a tuple or a local
struct or something, I think I see an opportunity to make a dedicate
type for this.

Additionally, we can use this type to clean up some duplication amongst
the type info structs in a manner similar to #7622.

## Solution

Added the `Type` type. This should be seen as the most basic
representation of a type apart from `TypeId`. It stores both the
`TypeId` of the type as well as its `TypePathTable`.

The `Hash` and `PartialEq` implementations rely on the `TypeId`, while
the `Debug` implementation relies on the `TypePath`.

This makes it especially useful as a key in a `HashMap` since we get the
speed of the `TypeId` hashing/comparisons with the readability of
`TypePath`.

With this type, we're able to reduce the duplication across the type
info structs by removing individual fields for `TypeId` and
`TypePathTable`, replacing them with a single `Type` field. Similarly,
we can remove many duplicate methods and replace it with a macro that
delegates to the stored `Type`.

### Caveats

It should be noted that this type is currently 3x larger than `TypeId`.
On my machine, it's 48 bytes compared to `TypeId`'s 16. While this
doesn't matter for `TypeInfo` since it would contain that data
regardless, it is something to keep in mind when using elsewhere.

## Testing

All tests should pass as normal:

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

---

## Showcase

`bevy_reflect` now exports a `Type` struct. This type contains both the
`TypeId` and the `TypePathTable` of the given type, allowing it to be
used like `TypeId` but have the debuggability of `TypePath`.

```rust
// We can create this for any type implementing `TypePath`:
let ty = Type::of::<String>();

// It has `Hash` and `Eq` impls powered by `TypeId`, making it useful for maps:
let mut map = HashMap::<Type, i32>::new();
map.insert(ty, 25);

// And it has a human-readable `Debug` representation:
let debug = format!("{:?}", map);
assert_eq!(debug, "{alloc::string::String: 25}");
```

## Migration Guide

Certain type info structs now only return their item types as `Type`
instead of exposing direct methods on them.

The following methods have been removed:

- `ArrayInfo::item_type_path_table`
- `ArrayInfo::item_type_id`
- `ArrayInfo::item_is`
- `ListInfo::item_type_path_table`
- `ListInfo::item_type_id`
- `ListInfo::item_is`
- `SetInfo::value_type_path_table`
- `SetInfo::value_type_id`
- `SetInfo::value_is`
- `MapInfo::key_type_path_table`
- `MapInfo::key_type_id`
- `MapInfo::key_is`
- `MapInfo::value_type_path_table`
- `MapInfo::value_type_id`
- `MapInfo::value_is`

Instead, access the `Type` directly using one of the new methods:

- `ArrayInfo::item_ty`
- `ListInfo::item_ty`
- `SetInfo::value_ty`
- `MapInfo::key_ty`
- `MapInfo::value_ty`

For example:

```rust
// BEFORE
let type_id = array_info.item_type_id();

// AFTER
let type_id = array_info.item_ty().id();
```
2024-08-25 17:57:07 +00:00
Sorseg
f9d7a2ca02
Implement std::fmt::Debug for ecs::observer::Trigger (#14857)
# Objective
I tried writing something like this in my project
```rust
.observe(|e: Trigger<OnAdd, Skeleton>| {
    panic!("Skeletoned! {e:?}");
});
```
and it didn't compile.
Having `Debug` trait defined on `Trigger` event will ease debugging the
observers a little bit.

## Solution

Add a bespoke `Debug` implementation when both the bundle and the event
have `Debug` implemented for them.

## Testing

I've added `println!("{trigger:#?}");` to the [observers
example](938d810766/examples/ecs/observers.rs (L124))
and it compiled!

Caveats with this PR are: 
- removing this implementation if for any reason we will need it, will
be a breaking change
- the implementation is manually generated, which adds potential toil
when changing the `Trigger` structure

## Showcase

Log output:
```rust
on_add_mine: Trigger {
    event: OnAdd,
    propagate: false,
    trigger: ObserverTrigger {
        observer: 2v1#4294967298,
        event_type: ComponentId(
            0,
        ),
        entity: 454v1#4294967750,
    },
    _marker: PhantomData<observers::Mine>,
}
```

Thank you for maintaining this engine! 🧡
2024-08-25 16:55:54 +00:00
akimakinai
89a5c741f7
Fix Gizmo joint rendering in webgpu (#14721)
# Objective

- Gizmo rendering on WebGPU has been fixed by #14653, but gizmo joints
still cause error
(https://github.com/bevyengine/bevy/issues/14696#issuecomment-2283689669)
when enabled.

## Solution

- Applies the same fix as #14653 to Gizmo joints.

I'm noob and just copied their solution, please correct me if I did
something wrong.

## Testing

- Tested 2d-gizmos and 3d-gizmos examples in WebGPU on Chrome. No
rendering errors, and the gizmo joints are apparently rendered ok.
2024-08-25 14:52:03 +00:00
Chris Russell
335f2903d9
SystemParamBuilder - Support dynamic system parameters (#14817)
# Objective

Support building systems with parameters whose types can be determined
at runtime.

## Solution

Create a `DynSystemParam` type that can be built using a
`SystemParamBuilder` of any type and then downcast to the appropriate
type dynamically.

## Example

```rust
let system = (
    DynParamBuilder::new(LocalBuilder(3_usize)),
    DynParamBuilder:🆕:<Query<()>>(QueryParamBuilder::new(|builder| {
        builder.with::<A>();
    })),
    DynParamBuilder:🆕:<&Entities>(ParamBuilder),
)
    .build_state(&mut world)
    .build_system(
        |mut p0: DynSystemParam, mut p1: DynSystemParam, mut p2: DynSystemParam| {
            let local = p0.downcast_mut::<Local<usize>>().unwrap();
            let query_count = p1.downcast_mut::<Query<()>>().unwrap();
            let entities = p2.downcast_mut::<&Entities>().unwrap();
        },
    );
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Periwink <charlesbour@gmail.com>
2024-08-25 14:23:44 +00:00
MichiRecRoom
94d40d206e
Replace the wgpu_trace feature with a field in bevy_render::settings::WgpuSettings (#14842)
# Objective
- Remove the `wgpu_trace` feature while still making it easy/possible to
record wgpu traces for debugging.
- Close #14725.
- Get a taste of the bevy codebase. :P

## Solution
This PR performs the above objective by removing the `wgpu_trace`
feature from all `Cargo.toml` files.

However, wgpu traces are still useful for debugging - but to record
them, you need to pass in a directory path to store the traces in. To
avoid forcing users into manually creating the renderer,
`bevy_render::settings::WgpuSettings` now has a `trace_path` field, so
that all of Bevy's automatic initialization can happen while still
allowing for tracing.

## Testing
- Did you test these changes? If so, how?
- I have tested these changes, but only via running `cargo run -p ci`. I
am hoping the Github Actions workflows will catch anything I missed.
- Are there any parts that need more testing?
  - I do not believe so.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If you want to test these changes, I have updated the debugging guide
(`docs/debugging.md`) section on WGPU Tracing.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- I ran the above command on a Windows 10 64-bit (x64) machine, using
the `stable-x86_64-pc-windows-msvc` toolchain. I do not have anything
set up for other platforms or targets (though I can't imagine this needs
testing on other platforms).

---

## Migration Guide

1. The `bevy/wgpu_trace`, `bevy_render/wgpu_trace`, and
`bevy_internal/wgpu_trace` features no longer exist. Remove them from
your `Cargo.toml`, CI, tooling, and what-not.
2. Follow the instructions in the updated `docs/debugging.md` file in
the repository, under the WGPU Tracing section.

Because of the changes made, you can now generate traces to any path,
rather than the hardcoded `%WorkspaceRoot%/wgpu_trace` (where
`%WorkspaceRoot%` is... the root of your crate's workspace) folder.

(If WGPU hasn't restored tracing functionality...) Do note that WGPU has
not yet restored tracing functionality. However, once it does, the above
should be sufficient to generate new traces.

---------

Co-authored-by: TrialDragon <31419708+TrialDragon@users.noreply.github.com>
2024-08-25 14:16:11 +00:00
Rob Parrett
2c3f5a00ac
Add AnimationGraph::from_clips and simplify animated_fox example (#14853)
# Objective

Add a convenience constructor to make simple animation graphs easier to
build.

I've had some notes about attempting this since #11989 that I just
remembered after seeing #14852.

This partially addresses #14852, but I don't really know animation well
enough to write all of the documentation it's asking for.

## Solution

Add `AnimationGraph::from_clips` and use it to simplify `animated_fox`.

Do some other little bits of incidental cleanup and documentation .

## Testing

I ran `cargo run --example animated_fox`.
2024-08-25 14:16:04 +00:00
Zachary Harrold
6250698b56
Added on_unimplemented Diagnostic for IntoObserverSystem (#14840)
# Objective

- Fixes #14658.

## Solution

- Added `on_unimplemented` Diagnostic for `IntoObserverSystem` calling
out argument ordering in a `note`
- Added an example to the documentation on `App::observe` to provide
some explanation to users.

## Testing

- Ran CI locally
- Deliberately introduced a parameter order error in the
`ecs/observers.rs` example as a test.

---

## Showcase

<details>
  <summary>Error Before</summary>

```
error[E0277]: the trait bound `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>` is not satisfied
   --> examples/ecs/observers.rs:19:13
    |
18  |           .observe(
    |            ------- required by a bound introduced by this call
19  | /             |mines: Query<&Mine>,
20  | |             trigger: Trigger<ExplodeMines>,
21  | |             index: Res<SpatialIndex>,
22  | |              mut commands: Commands| {
...   |
34  | |                 }
35  | |             },
    | |_____________^ the trait `bevy::prelude::IntoSystem<bevy::prelude::Trigger<'static, _, _>, (), _>` is not implemented for closure `{closure@examples/ecs/observers.rs:19:13: 22:37}`, which is required by `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>`
    |
    = note: required for `{closure@examples/ecs/observers.rs:19:13: 22:37}` to implement `IntoObserverSystem<_, _, _>`
note: required by a bound in `bevy::prelude::App::observe`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:995:24
    |
993 |     pub fn observe<E: Event, B: Bundle, M>(
    |            ------- required by a bound in this associated function
994 |         &mut self,
995 |         observer: impl IntoObserverSystem<E, B, M>,
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::observe`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `bevy` (example "observers") due to 1 previous error
```

</details>

<details>
  <summary>Error After</summary>

```
error[E0277]: `{closure@examples/ecs/observers.rs:19:13: 22:37}` cannot become an `ObserverSystem`
    --> examples/ecs/observers.rs:19:13
     |
18   |           .observe(
     |            ------- required by a bound introduced by this call
19   | /             |mines: Query<&Mine>,
20   | |             trigger: Trigger<ExplodeMines>,
21   | |             index: Res<SpatialIndex>,
22   | |              mut commands: Commands| {
...    |
34   | |                 }
35   | |             },
     | |_____________^ the trait `IntoObserverSystem` is not implemented
     |
     = help: the trait `bevy::prelude::IntoSystem<bevy::prelude::Trigger<'static, _, _>, (), _>` is not implemented for closure `{closure@examples/ecs/observers.rs:19:13: 22:37}`, which is required by `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>`
     = note: for function `ObserverSystem`s, ensure the first argument is a `Trigger<T>` and any subsequent ones are `SystemParam`
     = note: required for `{closure@examples/ecs/observers.rs:19:13: 22:37}` to implement `IntoObserverSystem<_, _, _>`
note: required by a bound in `bevy::prelude::App::observe`
    --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:1025:24
     |
1023 |     pub fn observe<E: Event, B: Bundle, M>(
     |            ------- required by a bound in this associated function
1024 |         &mut self,
1025 |         observer: impl IntoObserverSystem<E, B, M>,
     |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::observe`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `bevy` (example "observers") due to 1 previous error
```

</details>
2024-08-25 14:15:49 +00:00
charlotte
d9527c101c
Rewrite screenshots. (#14833)
# Objective

Rewrite screenshotting to be able to accept any `RenderTarget`.

Closes #12478 

## Solution

Previously, screenshotting relied on setting a variety of state on the
requested window. When extracted, the window's `swap_chain_texture_view`
property would be swapped out with a texture_view created that frame for
the screenshot pipeline to write back to the cpu.

Besides being tightly coupled to window in a way that prevented
screenshotting other render targets, this approach had the drawback of
relying on the implicit state of `swap_chain_texture_view` being
returned from a `NormalizedRenderTarget` when view targets were
prepared. Because property is set every frame for windows, that wasn't a
problem, but poses a problem for render target images. Namely, to do the
equivalent trick, we'd have to replace the `GpuImage`'s texture view,
and somehow restore it later.

As such, this PR creates a new `prepare_view_textures` system which runs
before `prepare_view_targets` that allows a new `prepare_screenshots`
system to be sandwiched between and overwrite the render targets texture
view if a screenshot has been requested that frame for the given target.

Additionally, screenshotting itself has been changed to use a component
+ observer pattern. We now spawn a `Screenshot` component into the
world, whose lifetime is tracked with a series of marker components.
When the screenshot is read back to the CPU, we send the image over a
channel back to the main world where an observer fires on the screenshot
entity before being despawned the next frame. This allows the user to
access resources in their save callback that might be useful (e.g.
uploading the screenshot over the network, etc.).

## Testing


![image](https://github.com/user-attachments/assets/48f19aed-d9e1-4058-bb17-82b37f992b7b)


TODO:
- [x] Web
- [ ] Manual texture view

---

## Showcase

render to texture example:
<img
src="https://github.com/user-attachments/assets/612ac47b-8a24-4287-a745-3051837963b0"
width=200/>

web saving still works:
<img
src="https://github.com/user-attachments/assets/e2a15b17-1ff5-4006-ab2a-e5cc74888b9c"
width=200/>

## Migration Guide

`ScreenshotManager` has been removed. To take a screenshot, spawn a
`Screenshot` entity with the specified render target and provide an
observer targeting the `ScreenshotCaptured` event. See the
`window/screenshot` example to see an example.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-08-25 14:14:32 +00:00
Kumikaya
9a2eb878a2
Fix underflow panic in InitTriInfo (#14893)
# Objective

- Fix #14874

## Solution

- Change the place where a panic occurs from `t < iNrTrianglesIn - 1` to
`t + 1 < iNrTrianglesIn`.

## Testing

- After the fix, the following code runs successfully without any panic.

```rust
use bevy::prelude::Mesh;
use bevy_render::{
    mesh::{Indices, PrimitiveTopology},
    render_asset::RenderAssetUsages,
};

const POSITIONS: &[[f32; 3]] = &[[0.0, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]];

const NORMALS: &[[f32; 3]] = &[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]];

const INDICES: &[u32] = &[0, 1, 2];

const UVS: &[[f32; 2]] = &[[0.0, 1.0], [0.0, 0.0], [0.0, 1.0]];

fn main() {
    let mut mesh = Mesh::new(
        PrimitiveTopology::TriangleList,
        RenderAssetUsages::default(),
    );

    mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, POSITIONS.to_vec());
    mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, UVS.to_vec());
    mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, NORMALS.to_vec());
    mesh.insert_indices(Indices::U32(INDICES.to_vec()));
    mesh.generate_tangents().ok();

}

```

## Migration Guide

- No breaking changes introduced.
2024-08-25 14:13:23 +00:00
Chris Russell
01cce9b11c
Make the field of ParamSetBuilder pub so it's actually usable. (#14896)
# Objective

`ParamSetBuilder` is supposed to be used as a tuple constructor, but the
field was not marked `pub` so it's not actually usable outside of its
module.

## Solution

Mark the field `pub`.  

Realize one advantage of doc tests over unit tests is that they test the
public API.

Add a doc test example that uses the field so that this would have been
caught.
2024-08-25 14:12:24 +00:00
Ben Frankel
48bd810451
Rename Commands::register_one_shot_system -> register_system (#14910)
# Objective

Improve naming consistency for functions that deal with one-shot systems
via `SystemId`:

- `App::register_system`
- `SubApp::register_system`
- `World::run_system`
- `World::register_system`
- `Commands::run_system`
-  `Commands::register_one_shot_system`

## Solution

Rename `Commands::register_one_shot_system` -> `register_system`.

## Testing

Not tested besides CI.

## Migration Guide

`Commands::register_one_shot_system` has been renamed to
`register_system`.
2024-08-25 14:12:13 +00:00
Robin KAY
28faafdc41
Fix tiny seam in Annulus geometry. (#14913)
# Objective

There is a tiny seam at the top of the annulus caused by normal
floating-point error in calculating the coordinates. When generating the
last pair of triangles, given `n == i` then `(TAU / n) * i` does not
equal `TAU` exactly.

Fixes https://github.com/komadori/bevy_mod_outline/issues/42

## Solution

This can be fixed by changing the calculation so that `(TAU / n) * (i %
n) == 0.0`, which is equivalent for trigonometric purposes.

## Testing

Added the unit test
`bevy_render::mesh::primitives::dim2::tests::test_annulus`.
2024-08-25 14:11:58 +00:00
aecsocket
eb6e97c18e
Make ActiveAnimation::set_weight return &mut Self (#14914)
# Objective

Fixes #14907.

## Solution

Changes `ActiveAnimation::set_weight` to return `&mut Self`.

## Testing

Simple API change, I don't think this needs explicit testing.
2024-08-25 13:44:52 +00:00
Thomas Alban
0070bdccd8
Add helper methods on Visibility (#14898)
Fixes #14825

Edit: After feedback, these are the updated methods:

- `toggle_inherited_visible(&mut self)`
- Toggles between `Visibility::Inherited` and `Visibility::Visible`. If
the value is `Visibility::Hidden`, it remains unaffected.
- `toggle_inherited_hidden(&mut self)`
- Toggles between `Visibility::Inherited` and `Visibility::Hidden`. If
the value is `Visibility::Visible`, it remains unaffected.
- `toggle_visible_hidden(&mut self)`
- Toggles between `Visibility::Visible` and `Visibility::Hidden`. If the
value is `Visibility::Inherited`, it remains unaffected.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2024-08-24 13:49:54 +00:00
Cian O
cccc1137b4
Remove dead links to example code in the bevy_ecs README (#14899)
We elected to remove these links instead of keeping them updated or
pinning them to latest.
Closes #14707
2024-08-24 13:43:18 +00:00
Jiří Švejda
3cf70ba4f9
Fix fog density texture offset seam (#14900)
# Objective

- There is a flaw in the implementation of `FogVolume`'s
`density_texture_offset` from #14868. Because of the way I am wrapping
the UVW coordinates in the volumetric fog shader, a seam is visible when
the 3d texture is wrapping around from one side to the other:


![density_texture_offset_seam](https://github.com/user-attachments/assets/89527ef2-5e1b-4b90-8e73-7a3e607697d4)

## Solution

- This PR fixes the issue by removing the wrapping from the shader and
instead leaving it to the user to configure the 3d noise texture to use
`ImageAddressMode::Repeat` if they want it to repeat. Using
`ImageAddressMode::Repeat` is the proper solution to avoid the obvious
seam:


![density_texture_seam_fixed](https://github.com/user-attachments/assets/06e871a6-2db1-4501-b425-4141605f9b26)

- The sampler cannot be implicitly configured to use
`ImageAddressMode::Repeat` because that's not always desirable. For
example, the `fog_volumes` example wouldn't work properly because the
texture from the edges of the volume would overflow to the other sides,
which would be bad in this instance (but it's good in the case of the
`scrolling_fog` example). So leaving it to the user to decide on their
own whether they want the density texture to repeat seems to be the best
solution.

## Testing

- The `scrolling_fog` example still looks the same, it was just changed
to explicitly declare that the density texture should be repeating when
loading the asset. The `fog_volumes` example is unaffected.
<details>
<summary>Minimal reproduction example on current main</summary>
<pre>
use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle,
TemporalAntiAliasPlugin};
use bevy::pbr::{FogVolume, VolumetricFogSettings, VolumetricLight};
use bevy::prelude::*;<br>
fn main() {
    App::new()
        .add_plugins((DefaultPlugins, TemporalAntiAliasPlugin))
        .add_systems(Startup, setup)
        .run();
}<br>
fn setup(mut commands: Commands, assets: Res&lt;AssetServer&gt;) {
    commands.spawn((
        Camera3dBundle {
            transform: Transform::from_xyz(3.5, -1.0, 0.4)
                .looking_at(Vec3::new(0.0, 0.0, 0.4), Vec3::Y),
            msaa: Msaa::Off,
            ..default()
        },
        TemporalAntiAliasBundle::default(),
        VolumetricFogSettings {
            ambient_intensity: 0.0,
            jitter: 0.5,
            ..default()
        },
    ));<br>
    commands.spawn((
        DirectionalLightBundle {
            transform: Transform::from_xyz(-6.0, 5.0, -9.0)
                .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
            directional_light: DirectionalLight {
                illuminance: 32_000.0,
                shadows_enabled: true,
                ..default()
            },
            ..default()
        },
        VolumetricLight,
    ));<br>
    commands.spawn((
        SpatialBundle {
            visibility: Visibility::Visible,
transform: Transform::from_xyz(0.0, 0.0,
0.0).with_scale(Vec3::splat(3.0)),
            ..default()
        },
        FogVolume {
density_texture: Some(assets.load("volumes/fog_noise.ktx2")),
            density_texture_offset: Vec3::new(0.0, 0.0, 0.4),
            scattering: 1.0,
            ..default()
        },
    ));
}
</pre>
</details>
2024-08-24 00:56:39 +00:00
Jan Hohenheim
c92ee31779
Allow ordering variable timesteps around fixed timesteps (#14881)
# Objective

- Fixes #14873, see that issue for a whole lot of context

## Solution

- Add a blessed system set for this stuff. See [this Discord
discussion](https://discord.com/channels/691052431525675048/749335865876021248/1276262931327094908).

Note that the gizmo systems,
[LWIM](https://github.com/Leafwing-Studios/leafwing-input-manager/pull/522/files#diff-9b59ee4899ad0a5d008889ea89a124a7291316532e42f9f3d6ae842b906fb095R154)
and now a new plugin I'm working on are all already ordering against
`run_fixed_main_schedule`, so having a dedicated system set should be
more robust and hopefully also more discoverable.

---

## ~~Showcase~~

~~I can add a little video of a smooth camera later if this gets merged
:)~~
Apparently a release note is not needed, so I'll leave it out. See the
changes in the fixed timestep example for usage showcase and the video
in #14873 for a more or less accurate video of the effect (it does not
use the same solution though, so it is not quite the same)

## Migration Guide


[run_fixed_main_schedule](https://docs.rs/bevy/latest/bevy/time/fn.run_fixed_main_schedule.html)
is no longer public. If you used to order against it, use the new
dedicated `RunFixedMainLoopSystem` system set instead. You can replace
your usage of `run_fixed_main_schedule` one for one by
`RunFixedMainLoopSystem::FixedMainLoop`, but it is now more idiomatic to
place your systems in either
`RunFixedMainLoopSystem::BeforeFixedMainLoop` or
`RunFixedMainLoopSystem::AfterFixedMainLoop`

Old:
```rust
app.add_systems(
    RunFixedMainLoop,
    some_system.before(run_fixed_main_schedule)
);
```

New:
```rust
app.add_systems(
    RunFixedMainLoop,
    some_system.in_set(RunFixedMainLoopSystem::BeforeFixedMainLoop)
);
```

---------

Co-authored-by: Tau Gärtli <git@tau.garden>
2024-08-23 16:19:42 +00:00
Andrew
f1f07bec09
Fix Gizmos warnings and doc errors when a subset of features are selected (#14887)
# Objective

When trying to test a gizmos change I ran `cargo test -p bevy_gizmos`
and the output had a lot of noise from warnings and failed doc errors.
This was because I didn't have all of the features enabled.

## Solution

I admit this might be pedantic, and am happy if the concensus is to
reject it. Although it does reduce the lines of code, testing noise, and
the amount of code compiled. I don't think it affects the complexity of
public code, and it doesn't change much to the complexity of internal
code.

I've removed un-needed `bevy_render` imports in all of the gizmos docs
examples, there's probably other unnecessary ones there too, but I
haven't looked exhaustively. It isn't needed for those docs, and isn't
available except in a subset of `cfg` combinations.

I've also made several of the `use` statements slightly more specific. I
shouldn't have changed the public interfaces, except that
`GizmoMeshConfig` requires either `bevy_sprite` or `bevy_pbr`, as it
does nothing without them.

I've also avoided adding some systems and plugins in situations where
they can't work. An example of this is where the `light` module depends
on `all(feature = "bevy_pbr", feature = "bevy_render")`, but it has
`use` statements that only require `bevy_render`.

## Testing

During development I ran:
```
cargo check -p bevy_gizmos && cargo check -p bevy_gizmos --features=bevy_pbr && cargo check -p bevy_gizmos --features=bevy_sprite && cargo check -p bevy_gizmos --features=bevy_render
```
Afterwards I ran this just to be sure:
```
cargo check && cargo check --features=bevy_pbr && cargo check --features=bevy_sprite && cargo check --features=bevy_render
```

Finally I ran:
```
cargo test -p bevy_gizmos && cargo test -p bevy_gizmos --features=bevy_pbr && test check -p bevy_gizmos --features=bevy_sprite && cargo test -p bevy_gizmos --features=bevy_render
```

## Migration Guide

There shouldn't be any reason to migrate, although if for some reason
you use `GizmoMeshConfig` and `bevy_render` but not `bevy_pbr` or
`bevy_sprite` (such that it does nothing), then you will get an error
that it no longer exists.
2024-08-23 16:19:06 +00:00
Andrew
e07119a0f9
Update Grid Gizmo to use Color (#14886)
# Objective

It looks like `Gizmos::grid*` was missed in the colour migration.

## Solution

This updates the `grid` methods and implementation to use `Color`
instead of `LinearRgba`.

It looks like `ExtractedPointLight` and `ExtractedDirectionalLight` also
use `LinearRgba`, although I think in extracted structures it's probably
fine to make more assumptions about what you want?

## Testing

I ran `cargo test --all -- bevy_gizmos` and it passed.

## Migration Guide

This shouldn't be adding anything that isn't already in a migration
guide? I assume as it uses `impl Into<...>` in the public interfaces
that any users of these APIs shouldn't have to make any code changes.
2024-08-23 02:54:45 +00:00
Lubba64
f9fbd08f9f
Implement Reflect for std::ops::Bound (#14861)
# Objective

- Fixes #14844

## Solution

- implement reflect using the `impl_reflect_value` macro

## Testing

- I wrote a test locally to understand and learn how reflection worked
on a basic level and to confirm that yes indeed the bound struct could
use the reflection traits that have been implemented for it.

note: I did remove a line that asked for bound to not have reflect
implemented in a test, since that's the point of this PR and the test
worked without the line so I am not sure what that was about, not sure
if that uncovers a deeper issue or not.
2024-08-22 23:01:38 +00:00
Jiří Švejda
510fce9af3
Allow fog density texture to be scrolled over time with an offset (#14868)
# Objective

- The goal of this PR is to make it possible to move the density texture
of a `FogVolume` over time in order to create dynamic effects like fog
moving in the wind.
- You could theoretically move the `FogVolume` itself, but this is not
ideal, because the `FogVolume` AABB would eventually leave the area. If
you want an area to remain foggy while also creating the impression that
the fog is moving in the wind, a scrolling density texture is a better
solution.

## Solution

- The PR adds a `density_texture_offset` field to the `FogVolume`
component. This offset is in the UVW coordinates of the density texture,
meaning that a value of `(0.5, 0.0, 0.0)` moves the 3d texture by half
along the x-axis.
- Values above 1.0 are wrapped, a 1.5 offset is the same as a 0.5
offset. This makes it so that the density texture wraps around on the
other side, meaning that a repeating 3d noise texture can seamlessly
scroll forever. It also makes it easy to move the density texture over
time by simply increasing the offset every frame.

## Testing

- A `scrolling_fog` example has been added to demonstrate the feature.
It uses the offset to scroll a repeating 3d noise density texture to
create the impression of fog moving in the wind.
- The camera is looking at a pillar with the sun peaking behind it. This
highlights the effect the changing density has on the volumetric
lighting interactions.
- Temporal anti-aliasing combined with the `jitter` option of
`VolumetricFogSettings` is used to improve the quality of the effect.

---

## Showcase


https://github.com/user-attachments/assets/3aa50ebd-771c-4c99-ab5d-255c0c3be1a8
2024-08-22 19:43:14 +00:00
Thomas Alban
e4b740840f
Add filter_map_unchanged to Mut<T> (#14837)
Closes #14836.

`filter_map_unchanged` optionally maps to an inner value by applying a
function to the contained reference. This is useful in a situation where
you need to convert a `Mut<T>` to a `Mut<U>`, but only if `T` contains
`U`.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2024-08-22 17:51:21 +00:00
Lubba64
b922896080
Expose bevy math ops (#14863)
# Objective

- Fixes #14796 

## Solution

- Copy docs for wrapper methods, make sure they are consistent with the
original docs except for the section on precision.
2024-08-22 17:07:00 +00:00
Rob Parrett
3e86787e93
Clarify docs for RenderLayers::layer (#14871)
# Objective

`RenderLayers` was marketed as being unlimited in the Bevy 0.14 release
notes, but the most obvious constructor doesn't actually support
unlimited layers.

We should explicitly document this.

## Solution

Add some docs mentioning the limit and pointing the user to `with` or
`from_layers` if they need an arbitrary number of layers.
2024-08-22 16:37:31 +00:00
EdJoPaTo
938d810766
Apply unused_qualifications lint (#14828)
# Objective

Fixes #14782

## Solution

Enable the lint and fix all upcoming hints (`--fix`). Also tried to
figure out the false-positive (see review comment). Maybe split this PR
up into multiple parts where only the last one enables the lint, so some
can already be merged resulting in less many files touched / less
potential for merge conflicts?

Currently, there are some cases where it might be easier to read the
code with the qualifier, so perhaps remove the import of it and adapt
its cases? In the current stage it's just a plain adoption of the
suggestions in order to have a base to discuss.

## Testing

`cargo clippy` and `cargo run -p ci` are happy.
2024-08-21 12:29:33 +00:00
Kees van Beilen
7499b74bbf
Added Sprite::sized(custom_size) (#14849)
# Objective
add a quick shorthand for creating a sprite with an custom size. This is
often desired when working with custom units or scaled sprites and
allows for a cleaner syntax in those cases/

## Solution

Implemented a `sized` function on the Sprite struct which creates a
Sprite, sets the custom size and leaves the rest at their default values

---

## Changelog

- Added `Sprite::sized(custom_size: Vec2)`
2024-08-21 12:24:16 +00:00
robtfm
6e2f96f222
check sampler type in as_bind_group derives (#12637)
# Objective

currently if we use an image with the wrong sampler type in a material,
wgpu panics with an invalid texture format. turn this into a warning and
fail more gracefully.

## Solution

the expected sampler type is specified in the AsBindGroup derive, so we
can just check the image sampler is what it should be.

i am not totally sure about the mapping of image sampler type to
#[sampler(type)], i assumed:

```
    "filtering" => [ TextureSampleType::Float { filterable: true } ],
    "non_filtering" => [
        TextureSampleType::Float { filterable: false },
        TextureSampleType::Sint,
        TextureSampleType::Uint,
    ],
    "comparison" => [ TextureSampleType::Depth ],
```
2024-08-21 01:41:31 +00:00
Zachary Harrold
f59a6a971a
Added Documentation to all_tuples_with_size (#14832)
# Objective

- Fixes #14684

## Solution

- Added documentation to `all_tuples_with_size` based on existing
`all_tuples` documentation.
- Updated `all_tuples` documentation to match formatting of and link
back to `all_tuples_with_size`

## Testing

- Doctests ran locally.

## Notes

Formatting changes I have proposed make the documentation a little
cleaner in my opinion, but I am open to reverting them and amending
`all_tuples_with_size` to match if there are any reasonable objections.
2024-08-20 11:12:44 +00:00
Alice Cecile
ba2847929f
Revert "Add conversions between Visibility and bool (#14784)" (#14830)
This reverts commit e37bf18e2b, added in
#14784.

# Objective

The PR was fine, but the work was very poorly motivated and the
resulting API is not actually very nice. The actual user need is likely
better addressed by #14825.

## Solution

Revert the offending PR.
2024-08-20 11:08:46 +00:00
Zachary Harrold
491aec8e5b
Generalized Into<AssetSourceId> and Into<AssetPath> Implementations over Lifetime (#10823)
# Objective

- Fixes #10478

## Solution

Generalised `From/Into` implementations over `&str` and `Option<&str>`
for `AssetSourceId` and `AssetPath` across all lifetimes, not just
static. To maintain access to the `'static`-only specialisation, these
types (and `CowArc`) now include an `as_static` method which will apply
the specialisation.

```rust
// Snipped from `AssetApp`
fn register_asset_source(
    &mut self,
    id: impl Into<AssetSourceId<'static>>,
    //                          ^^^^^^^
    //                          | as_static is only available for 'static lifetimes
    source: AssetSourceBuilder,
) -> &mut Self {
    let id = id.into().as_static();
    //          ^^^^^^ ^^^^^^^^^
    //          |      | Specialized (internally storing CowArc::Static)
    //          | Generic Into (internally storing CowArc::Borrowed)
    
    // ...
}
```

This post-fix specialisation is available here because the actual
specialisation performed is only a marker for if/when modification or
ownership is required, making the transform a very cheap operation. For
cleanliness, I've also added `from_static`, which wraps this behaviour
in a clean shorthand designed to replace `from` calls.

---

## Changelog

- Generalised the following implementations over a generic lifetime:
  - `From<&'static str> for AssetSourceId<'static>`
  - `From<Option<&'static str>> for AssetSourceId<'static>`
  - `From<&'static str> for AssetPath<'static>`
  - `From<&'static Path> for AssetPath<'static>`
- Added `as_static` specialisation to:
  - `CowArc`
  - `AssetSourceId`
  - `AssetPath`
- Added `from_static` specialised constructor to:
  - `AssetSourceId`
  - `AssetPath`

## Migration Guide

In areas where these implementations where being used, you can now add
`from_static` in order to get the original specialised implementation
which avoids creating an `Arc` internally.

```rust
// Before
let asset_path = AssetPath::from("my/path/to/an/asset.ext");

// After
let asset_path = AssetPath::from_static("my/path/to/an/asset.ext");
```

To be clear, this is only required if you wish to maintain the
performance benefit that came with the specialisation. Existing code is
_not_ broken by this change.
2024-08-19 23:41:46 +00:00
Gino Valente
2b4180ca8f
bevy_reflect: Function reflection terminology refactor (#14813)
# Objective

One of the changes in #14704 made `DynamicFunction` effectively the same
as `DynamicClosure<'static>`. This change meant that the de facto
function type would likely be `DynamicClosure<'static>` instead of the
intended `DynamicFunction`, since the former is much more flexible.

We _could_ explore ways of making `DynamicFunction` implement `Copy`
using some unsafe code, but it likely wouldn't be worth it. And users
would likely still reach for the convenience of
`DynamicClosure<'static>` over the copy-ability of `DynamicFunction`.

The goal of this PR is to fix this confusion between the two types.

## Solution

Firstly, the `DynamicFunction` type was removed. Again, it was no
different than `DynamicClosure<'static>` so it wasn't a huge deal to
remove.

Secondly, `DynamicClosure<'env>` and `DynamicClosureMut<'env>` were
renamed to `DynamicFunction<'env>` and `DynamicFunctionMut<'env>`,
respectively.

Yes, we still ultimately kept the naming of `DynamicFunction`, but
changed its behavior to that of `DynamicClosure<'env>`. We need a term
to refer to both functions and closures, and "function" was the best
option.


[Originally](https://discord.com/channels/691052431525675048/1002362493634629796/1274091992162242710),
I was going to go with "callable" as the replacement term to encompass
both functions and closures (e.g. `DynamciCallable<'env>`). However, it
was
[suggested](https://discord.com/channels/691052431525675048/1002362493634629796/1274653581777047625)
by @SkiFire13 that the simpler "function" term could be used instead.

While "callable" is perhaps the better umbrella term—being truly
ambiguous over functions and closures— "function" is more familiar, used
more often, easier to discover, and is subjectively just
"better-sounding".

## Testing

Most changes are purely swapping type names or updating documentation,
but you can verify everything still works by running the following
command:

```
cargo test --package bevy_reflect
```
2024-08-19 21:52:36 +00:00
robtfm
75738ed80f
catch asset loader panics (#14809)
# Objective

currently if an asset loader panics, the asset is left in a perpetual
`Loading` state. this can occur with external crates (eg the image crate
panics on bad data). catch this panic and resolve the asset to `Failed`

## Solution

`AssertUnwindSafe(loader.load).catch_unwind()` and map the panic to an
`AssetLoadError`

separated out from #13170
2024-08-19 21:50:39 +00:00
Rob Parrett
618cf7f51d
Remove useless Direction field (#14793)
# Objective

Delete some code that isn't actually doing anything. This was actually
discovered way back in this obsolete PR: #5513.

Also Fixes #6286

## Solution

Delete it

## Alternatives

Make `Direction` do things. But it's not totally clear to me if it's
possible to override cosmic-text's unicode bidi stuff.

## Migration Guide

`Style` no longer has a `direction` field, and `Direction` has been
deleted. They didn't do anything, so you can delete any references to
them as well.
2024-08-19 21:45:28 +00:00
Stanisław Kawulok
e37bf18e2b
Add conversions between Visibility and bool (#14784)
# Objective

Fixes #14521. 

## Solution

Added to methods to the VIsibility. 
```rs
is_visible() -> Result<bool, String>
```
 and 
```rs
visbility_from_bool(bool) -> Visibility
```

## Testing

Ran 
* `cargo run -p ci -- lints`
* `cargo run -p ci -- test`
* `cargo run -p ci -- compile`
it seems to be working. 
However I got few error messages :`ERROR bevy_log: could not set global
logger and tracing subscriber as they are already set. Consider
disabling LogPlugin` in `cargo run -p ci -- test`, even though all test
passed. I'm not sure if that's expected behaviour

Ps. I'm new to contributing, please correct me if anything is wrong
2024-08-19 21:40:54 +00:00
Robert Walter
d2fa55db6b
New utility methods on InfinitePlane3d (#14651)
# Objective

Some algorithms don't really work well or are not efficient in 3D space.
When we know we have points on an `InfinitePlane3d` it would be helpful
to have some utility methods to reversibly transform points on the plane
to 2D space to apply some algorithms there.

## Solution

This PR adds a few of methods to project 3D points on a plane to 2D
points and inject them back. Additionally there are some other small
common helper methods.

## Testing

- added some tests that cover the new methods

---------

Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-08-19 21:36:18 +00:00
Periwink
eaa805102d
add docs explaining the two accesses of a System meta (#14580)
# Objective

When reading the ECS code it is sometimes confusing to understand why we
have 2 accesses, one of ComponentId and one of ArchetypeComponentId


## Solution

Make the usage of these 2 accesses more explicit

---------

Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2024-08-19 21:32:45 +00:00
Luca Della Vedova
6d3b2faf8a
Fix commands not being Send / Sync in 0.14 (#14392)
# Objective

Fixes Commands not being `Send` or `Sync` anymore in 0.14 by
implementing `Send` and `Sync` for `RawCommandQueue`.

## Solution

Reference discussion in
[discord](https://discord.com/channels/691052431525675048/691052431974465548/1259464518539411570).
It seems that in https://github.com/bevyengine/bevy/pull/13249, when
adding a `RawCommandQueue` variant to the `InternalQueue`, the `Send /
Sync` traits were not implemented for it, which bubbled up all the way
to `Commands` not being `Send / Sync` anymore.
I am not very familiar with the ECS internals so I can't say whether the
`RawCommandQueue` is safe to be shared between threads, but I know for
sure that before the linked PR `Commands` were indeed `Send` and `Sync`
so that PR broke "some workflows" (mandatory
[xkcd](https://xkcd.com/1172/)).

## Testing

This PR itself includes a compile test to make sure `Commands` will
implement `Send` and `Sync`. The test itself fails without the
implementation and succeeds with it.
Furthermore, if I cherry pick the test to a previous release (i.e. 0.13)
it indeed succeeds, showing that this is a regression specific to 0.14.

---------

Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
2024-08-19 21:29:30 +00:00
Robin KAY
defeeb375b
Fix size of MeshVertexAttributeId to be platform independent (#6624)
# Objective

`MeshVertexAttributeId` is currently a wrapper type around a `usize`.
Application developers are exposed to the `usize` whenever they need to
define a new custom vertex attribute, which requires them to generate a
random `usize` ID to avoid clashes with any other custom vertex
attributes in the same application. As the range of a `usize` is
platform dependent, developers on 64-bit machines may inadvertently
generate random values which will fail to compile for a 32-bit target.
The use of a `usize` here encourages non-portable behaviour and should
be replaced with a fixed width type.

## Solution

In this PR I have changed the ID type from `usize` to `u64`, but equally
a `u32` could be used at the risk of breaking some extant non-portable
programs and increasing the chance of an ID collision.
2024-08-19 21:09:20 +00:00
Gino Valente
423285cf1c
bevy_reflect: Store functions as DynamicClosure<'static> in FunctionRegistry (#14704)
# Objective

#14098 added the `FunctionRegistry` for registering functions such that
they can be retrieved by name and used dynamically. One thing we chose
to leave out in that initial PR is support for closures.

Why support closures? Mainly, we don't want to prohibit users from
injecting environmental data into their registered functions. This
allows these functions to not leak their internals to the public API.

For example, let's say we're writing a library crate that allows users
to register callbacks for certain actions. We want to perform some
actions before invoking the user's callback so we can't just call it
directly. We need a closure for this:

```rust
registry.register("my_lib::onclick", move |event: ClickEvent| {
    // ...other work...

    user_onclick.call(event); // <-- Captured variable
});
```

We could have made our callback take a reference to the user's callback.
This would remove the need for the closure, but it would change our
desired API to place the burden of fetching the correct callback on the
caller.

## Solution

Modify the `FunctionRegistry` to store registered functions as
`DynamicClosure<'static>` instead of `DynamicFunction` (now using
`IntoClosure` instead of `IntoFunction`).

Due to limitations in Rust and how function reflection works,
`DynamicClosure<'static>` is functionally equivalent to
`DynamicFunction`. And a normal function is considered a subset of
closures (it's a closure that doesn't capture anything), so there
shouldn't be any difference in usage: all functions that satisfy
`IntoFunction` should satisfy `IntoClosure`.

This means that the registration API introduced in #14098 should require
little-to-no changes on anyone following `main`.

### Closures vs Functions

One consideration here is whether we should keep closures and functions
separate.

This PR unifies them into `DynamicClosure<'static>`, but we can consider
splitting them up. The reasons we might want to do so are:

- Simplifies mental model and terminology (users don't have to
understand that functions turn into closures)
- If Rust ever improves its function model, we may be able to add
additional guarantees to `DynamicFunction` that make it useful to
separate the two
- Adding support for generic functions may be less confusing for users
since closures in Rust technically can't be generic

The reasons behind this PR's unification approach are:

- Reduces the number of methods needed on `FunctionRegistry`
- Reduces the number of lookups a user may have to perform (i.e.
"`get_function` or else `get_closure`")
- Establishes `DynamicClosure<'static>` as the de facto dynamic callable
(similar to how most APIs in Rust code tend to prefer `impl Fn() ->
String` over `fn() -> String`)

I'd love to hear feedback on this matter, and whether we should continue
with this PR's approach or switch to a split model.

## Testing

You can test locally by running:

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

---

## Showcase

Closures can now be registered into the `FunctionRegistry`:

```rust
let punct = String::from("!!!");

registry.register_with_name("my_crate::punctuate", move |text: String| {
  format!("{}{}", text, punct)
});
```
2024-08-17 00:20:47 +00:00
Alice Cecile
da529ff09e
Ignore PipelineCache ambiguities (#14772)
# Objective

The `prepare_view_upscaling_pipelines` system has dozens of ambiguities,
which makes it harder to spot and prevent new ambiguities.

Closes https://github.com/bevyengine/bevy/issues/14770.

## Solution

Just exclude the system from ambiguity detection. See the linked issue
for more context on why this resolution was chosen.

## Testing

Running the `ambiguity_detection` example now reports dozens fewer
`Render` app ambiguities.
2024-08-16 23:43:40 +00:00
Vitaliy Sapronenko
bc445bb5c6
Add feature requirement info to image loading docs (#13712)
# Objective

- Add "Available on crate feature <image format> only." for docs of
image format related types/functions
- Add warning "WARN bevy_render::texture::image: feature "<image
format>" is not enabled" on load attempt
- Fixes #13468 .

## Solution

- Added #[cfg(feature = "<image format>")] for types and warn!("feature
\"<image format>\" is not enabled"); for ImageFormat enum conversions

## Testing

ran reproducing example from issue #13468 and saw in logs
`WARN bevy_render::texture::image: feature "exr" is not enabled`

generated docs with command `RUSTDOCFLAGS="-Zunstable-options
--cfg=docsrs" cargo +nightly doc --workspace --all-features --no-deps
--document-private-items --open` and saw

![image](https://github.com/bevyengine/bevy/assets/17225606/820262bb-b4e6-4a5e-a306-bddbe9c40852)
that docs contain `Available on crate feature <image format> only.`
marks

![image](https://github.com/bevyengine/bevy/assets/17225606/57463440-a2ea-435f-a2c2-50d34f7f55a9)

## Migration Guide
Image format related entities are feature gated, if there are
compilation errors about unknown names there are some of features in
list (`exr`, `hdr`, `basis-universal`, `png`, `dds`, `tga`, `jpeg`,
`bmp`, `ktx2`, `webp` and `pnm`) should be added.
2024-08-16 23:43:20 +00:00
Robert Walter
d7cb781977
Switch rotation & translation in grid gizmos (#14656)
# Objective

- Fixes #14655

## Solution

Rotation should happen first as this is more easier to conceptualize in
the mind: We rotate around the coordinate origin `Vec3::ZERO` and then
we just shift the geometry so that its center is exactly on the
specified position

## Testing && Showcase

Code:

```rust
    gizmos.grid(
        Vec3::ONE * 10.0,
        Quat::from_rotation_x(PI / 3. * 2.),
        UVec2::splat(20),
        Vec2::new(2., 2.),
        PURPLE,
    );
    gizmos.sphere(Vec3::ONE * 10.0, Quat::default(), 1.0, PURPLE);
```

Before picture:


![image](https://github.com/user-attachments/assets/7fea2e71-e62b-4763-9f9f-7a1ecd630ada)

After picture:


![image](https://github.com/user-attachments/assets/899dad64-010a-4e4b-86ae-53b85fef0bbc)


## Migration Guide

- Users might have to double check their already existing calls to all
the `grid` methods. It should be more intuitive now though.
2024-08-16 23:40:06 +00:00
nsarlin
313db39912
Add try_insert_with_new (#14787)
# Objective
Fix #14771 by adding a `try_insert_if_new` method to the
`EntityCommands`

## Solution
This simply calls the  `try_insert` function with `InsertMode::Keep`

## Testing
I did not add any test because `EntityCommands::try_insert` does not
seem to be tested either. I can add some if needed.
2024-08-16 21:25:11 +00:00
Nihilistas
ae74df3464
#14143 - fix bevy_ui padding (#14777)
# Objective

fixes #14143

## Solution

- removed the temporary blocker if statement when setting padding in
`Style`
- adjusted the `layout_location` and `layout_size` so they use
`layout.padding` which we already get from Taffy

## Testing

- this is the test code I used:
```rust
use bevy::prelude::*;

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

fn setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
){
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    commands.spawn(Camera2dBundle::default());

    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Px(200.),
                height: Val::Px(100.),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                align_self: AlignSelf::Center,
                justify_self: JustifySelf::Center,
                ..Default::default()
            },
            background_color: BackgroundColor(Color::srgb(0.,1., 1.)),
            ..Default::default()
        })
        .with_children(|builder| {
            builder.spawn((TextBundle::from_section(
                    "Hello World",
                    TextStyle {
                        font,
                        font_size: 32.0,
                        color: Color::WHITE,
                        },
                ).with_style(Style {
                    padding: UiRect::all(Val::Px(10.)),
                    width: Val::Px(100.),
                    height: Val::Px(100.),
                    ..Default::default()
                }).with_background_color(Color::srgb(1.,0., 0.)),
            ));
            // spawn an image bundle
            builder.spawn(ImageBundle {
                style: Style {
                    padding: UiRect::all(Val::Px(10.)),
                    width: Val::Px(100.),
                    height: Val::Px(100.),
                    ..Default::default()
                },
                image: asset_server.load("square.png").into(),
                ..Default::default()
            });
        });
}
```

- I tested 5 cases: 10px padding from all sides, and 10px padding from
left, right, bottom, and top separately

- **For reviewers**: please check more cases or try to run it on some
more complicated real-world UI

## Showcase

<img width="374" alt="Screenshot 2024-08-16 at 09 28 04"
src="https://github.com/user-attachments/assets/59b85b00-e255-4669-be13-a287ef35d4d9">
<img width="288" alt="Screenshot 2024-08-16 at 09 28 47"
src="https://github.com/user-attachments/assets/170a79b1-ec9c-45f9-82f5-ba7fa4029334">
<img width="274" alt="Screenshot 2024-08-16 at 09 45 16"
src="https://github.com/user-attachments/assets/e3fd9b59-b41f-427d-8c07-5acdf1dc5ecf">
<img width="292" alt="Screenshot 2024-08-16 at 09 45 36"
src="https://github.com/user-attachments/assets/c4f708aa-3f0d-4ff3-b779-0d4ed5f6ba73">
<img width="261" alt="Screenshot 2024-08-16 at 09 45 58"
src="https://github.com/user-attachments/assets/eba1e26f-04ca-4178-87c8-3a79daff3a9a">

---------

Co-authored-by: dpeke <dpekelis@funstage.com>
2024-08-16 21:22:44 +00:00
Robert Walter
f88ab5a1f2
add consts to curve module functions (#14785)
Just a really minor polish of the ongoing curve RFC implementation
effort
2024-08-16 19:28:29 +00:00
Sam
cf69488982
Enables bevy_render feature for bevy_gizmos dependency in bevy_dev_tools (#14765)
# Objective

Fixes #14736

## Solution

Enables feature `bevy_render` for dependency `bevy_gizmos` in
`bevy_dev_tools` cargo.

`bevy_dev_tools` has `bevy_render` as a required dependency, whereas it
is optional for `bevy_gizmos`. When building with no default features,
this causes gizmos to not compile with `bevy_render` features, meaning
some fields and code are not available. Since these features are
required in dev tools, it makes sense to ensure they are enabled. Making
`bevy_render` optional would introduce additional and potentially
unwanted change wake. in dev tools.

## Testing
Reproed and tested on Windows 10, issue originally reported on Ubuntu
and MacOS.

- Original issue command completed without error: `cargo c -p bevy
--no-default-features -F bevy_dev_tools`
- Ran full ci validations with `cargo run -p ci`
2024-08-15 21:53:55 +00:00
Matty
20a9b921a0
A Curve trait for general interoperation — Part II (#14700)
# Objective

Finish what we started in #14630. The Curve RFC is
[here](https://github.com/bevyengine/rfcs/blob/main/rfcs/80-curve-trait.md).

## Solution

This contains the rest of the library from my branch. The main things
added here are:
- Bulk sampling / resampling methods on `Curve` itself
- Data structures supporting the above
- The `cores` submodule that those data structures use to encapsulate
sample interpolation

The weirdest thing in here is probably `ChunkedUnevenCore` in `cores`,
which is not used by anything in the Curve library itself but which is
required for efficient storage of glTF animation curves. (See #13105.)
We can move it into a different PR if we want to; I don't have strong
feelings either way.

## Testing

New tests related to resampling are included. As I write this, I realize
we could use some tests in `cores` itself, so I will add some on this
branch before too long.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Robert Walter <26892280+RobWalt@users.noreply.github.com>
2024-08-15 21:49:02 +00:00
Alice Cecile
5243fe6956
Remove manual apply_deferred in bevy_ui (#14768)
# Objective

This `apply_deferred` doesn't seem to have any effect, pointlessly
restricts parallelism and is responsible for a large number of system
order ambiguities. Spotted as part of #7386.

## Solution

Remove it.

This is the *only* manual apply_deferred in the code base currently.

## Testing

I've checked various UI examples and `split_screen`, and couldn't
discern any difference.

This looks like a remnant of a `(a, apply_deferred, b).chain()` pattern
where `b` got removed, leaving us with a weird vestige.
2024-08-15 20:51:25 +00:00
Jeff Petkau
b2529bf100
feat: add insert_if_new (#14397) (#14646)
# Objective

Often there are reasons to insert some components (e.g. Transform)
separately from the rest of a bundle (e.g. PbrBundle). However `insert`
overwrites existing components, making this difficult.

See also issue #14397

Fixes #2054.

## Solution

This PR adds the method `insert_if_new` to EntityMut and Commands, which
is the same as `insert` except that the old component is kept in case of
conflicts.

It also renames some internal enums (from `ComponentStatus::Mutated` to
`Existing`), to reflect the possible change in meaning.

## Testing

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

Added basic unit tests; used the new behavior in my project.

*Are there any parts that need more testing?*

There should be a test that the change time isn't set if a component is
not overwritten; I wasn't sure how to write a test for that case.

*How can other people (reviewers) test your changes? Is there anything
specific they need to know?*

`cargo test` in the bevy_ecs project.

*If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?*

Only tested on Windows, but it doesn't touch anything platform-specific.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
2024-08-15 20:31:41 +00:00
Alice Cecile
a2fc9de16d
Add RenderSet::FinalCleanup for World::clear_entities (#14764)
# Objective

`World::clear_entities` is ambiguous with all of the other systems in
`RenderSet::Cleanup` because it access `&mut World`.

## Solution

I've added another system set variant, and made sure that this runs
after everything else.
 
## Testing

The `ambiguity_detection` example

## Migration Guide

`World::clear_entities` is now part of `RenderSet::PostCleanup` rather
than `RenderSet::Cleanup`. Your cleanup systems should likely stay in
`RenderSet::Cleanup`.

## Additional context

Spotted when working on #7386: this was responsible for a large number
of ambiguities.

This should be removed if / when #14449 is merged: there's no need to
call `clear_entities` at all if the rendering world is retained!
2024-08-15 18:48:43 +00:00
Brian Reavis
ac29bdfc86
Fix pass_span drop panic obscuring transparent 2d render errors (#14758)
# Objective

When an item in the transparent 2d phase fails to render, bevy crashes
with _"PassSpanScope::end was never called"_ instead of outputting the
actual error to the console. This PR fixes this so that phase errors are
output to the console. It also makes bevy not crash.

```
thread '<unnamed>' panicked at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/diagnostic/mod.rs:157:9:
PassSpanScope::end was never called
stack backtrace:
   0: rust_begin_unwind
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:72:14
   2: <bevy_render::diagnostic::PassSpanGuard<R,P> as core::ops::drop::Drop>::drop
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/diagnostic/mod.rs:157:9
   3: core::ptr::drop_in_place<bevy_render::diagnostic::PassSpanGuard<core::option::Option<alloc::sync::Arc<bevy_render::diagnostic::internal::DiagnosticsRecorder>>,bevy_render::render_phase::draw_state::TrackedRenderPass>>
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ptr/mod.rs:514:1
   4: <bevy_core_pipeline::core_2d::main_transparent_pass_2d_node::MainTransparentPass2dNode as bevy_render::render_graph::node::ViewNode>::run
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs:75:9
   5: <bevy_render::render_graph::node::ViewNodeRunner<T> as bevy_render::render_graph::node::Node>::run
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/render_graph/node.rs:406:9
   6: bevy_render::renderer::graph_runner::RenderGraphRunner::run_graph
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/renderer/graph_runner.rs:226:21
   7: bevy_render::renderer::graph_runner::RenderGraphRunner::run_graph
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/renderer/graph_runner.rs:233:21
   8: bevy_render::renderer::graph_runner::RenderGraphRunner::run
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/renderer/graph_runner.rs:81:9
   9: bevy_render::renderer::render_system
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_render/src/renderer/mod.rs:40:15
  10: core::ops::function::FnMut::call_mut
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:166:5
  11: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:294:13
  12: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run::call_inner
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_ecs/src/system/exclusive_function_system.rs:229:21
  13: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_ecs/src/system/exclusive_function_system.rs:232:17
  14: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run::{{closure}}
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_ecs/src/system/exclusive_function_system.rs:124:23
  15: bevy_ecs::world::World::last_change_tick_scope
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_ecs/src/world/mod.rs:2383:9
  16: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run
             at /Users/brianreavis/Repositories/project/bevy/crates/bevy_ecs/src/system/exclusive_function_system.rs:116:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```

## Solution

Matched the behavior of the other render phases ([like
here](9ca5540b75/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs (L98-L101)))
2024-08-15 18:41:01 +00:00
Giacomo Stevanato
e9e9e5e15d
Add query reborrowing (#14690)
# Objective

- Sometimes some method or function takes an owned `Query`, but we don't
want to give up ours;
- transmuting it technically a solution, but it more costly than
necessary.
- Make query iterators more flexible
- this would allow the equivalent of
`slice::split_first`/`slice::split_first_mut` for query iterators
  - helps with requests like #14685

## Solution

- Add a way for reborrowing queries, that is going from a `&'a mut
Query<'w, 's, D, F>` to a `Query<'a, 's, D, F>`:
- this is safe because the original query will be borrowed while the new
query exists and thus no aliased access can happen;
- it's basically the equivalent of going from `&'short mut &'long mut T`
to `&'short mut T` the the compiler automatically implements.
- Add a way for getting the remainder of a query iterator:
- this is interesting also because the original iterator keeps its
position, which was not possible before;
- this in turn requires a way to reborrow query fetches, which I had to
add to `WorldQuery`.

## Showcase

- You can now reborrow a `Query`, getting an equivalent `Query` with a
shorter lifetime. Previously this was possible for read-only queries by
using `Query::to_readonly`, now it's possible for mutable queries too;
- You can now separately iterate over the remainder of `QueryIter`.

## Migration Guide

- `WorldQuery` now has an additional `shrink_fetch` method you have to
implement if you were implementing `WorldQuery` manually.
2024-08-15 17:38:56 +00:00
callym
9d5837769c
Add Reflect derive to bevy_a11y::Focus (#14763)
Closes #14727
2024-08-15 17:33:20 +00:00
Alice Cecile
dbf0d7071e
Don't ask for ResMut in queue_view_auto_exposure_pipelines (#14762)
This was creating a spurious ambiguity: `PipelineCache` uses interior
mutability.

Spotted as part of #7386.
2024-08-15 17:15:31 +00:00
callym
ad5e8355b5
Remove Component derive for DepthOfFieldMode (#14761)
Fixes #14592
2024-08-15 17:14:49 +00:00
Chris Russell
340c749d16
Remove redundant ArchetypeComponentId lookup in Res and ResMut (#14691)
# Objective

`Res` and `ResMut` perform redundant lookups of the resource storage,
first to initialize the `ArchetypeComponentId` and then to retrieve it.

## Solution

Use the `archetype_component_id` returned from
`initialize_resource_internal` to avoid an extra lookup and `unwrap()`.
2024-08-15 16:12:03 +00:00
robtfm
9ca5540b75
apply finished animations (#14743)
# Objective

fix #14742

## Solution

the issue arises because "finished" animations (where current time >=
last keyframe time) are not applied at all.
when transitioning from a finished animation to another later-indexed
anim, the transition kind-of works because the finished anim is skipped,
then the new anim is applied with a lower weight (weight / total_weight)
when transitioning from a finished animation to another earlier-indexed
anim, the transition is instant as the new anim is applied with 1.0 (as
weight == total_weight for the first applied), then the finished
animation is skipped.

to fix this we can always apply every animation based on the nearest 2
keyframes, and clamp the interpolation between them to [0,1].

pros:
- finished animations can be transitioned out of correctly
- blended animations where some curves have a last-keyframe before the
end of the animation will blend properly
- animations will actually finish on their last keyframe, rather than a
fraction of a render-frame before the end

cons:
- we have to re-apply finished animations every frame whether it's
necessary or not. i can't see a way to avoid this.
2024-08-15 15:10:23 +00:00
TotalKrill
6adf31babf
hooking up observers and clicking for ui node (#14695)
Makes the newly merged picking usable for UI elements. 

currently it both triggers the events, as well as sends them as throught
commands.trigger_targets. We should probably figure out if this is
needed for them all.

# Objective

Hooks up obserers and picking for a very simple example

## Solution

upstreamed the UI picking backend from bevy_mod_picking

## Testing

tested with the new example picking/simple_picking.rs


---

---------

Co-authored-by: Lixou <82600264+DasLixou@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-08-15 14:43:55 +00:00
Chris Russell
0ea46663b0
Use map_unchanged in reflection instead of creating a Mut manually. (#14692)
# Objective

The code to create `ReflectComponent` and `ReflectResource` instances
manually constructs a `Mut<dyn Reflect>` by copying everything but
`value`. That can be done more concisely and better respecting
encapsulation by calling the `map_unchanged()` method.

## Solution

Use `map_unchanged` instead of creating a `Mut` manually.

---------

Co-authored-by: radiish <cb.setho@gmail.com>
2024-08-15 14:26:57 +00:00
Ben Frankel
d849941dac
Add entity .trigger() methods (#14752)
# Objective

Fix https://github.com/bevyengine/bevy/issues/14233.

## Solution

Add `EntityCommands::trigger` and `EntityWorldMut::trigger`.

## Testing

- Not tested.
2024-08-15 14:16:06 +00:00
eckz
a44278aee6
Making DynamicEnum::is_dynamic() return true (#14732)
# Objective

- Right now `DynamicEnum::is_dynamic()` is returning `false`. I don't
think this was expected, since the rest of `Dynamic*` types return
`true`.

## Solution

- Making `DynamicEnum::is_dynamic()` return true

## Testing

- Added an extra unit test to verify that `.is_dynamic()` returns
`true`.
2024-08-15 14:10:52 +00:00
IceSentry
9de25ad330
Add AlphaMask2d phase (#14724)
# Objective

- Bevy now supports an opaque phase for mesh2d, but it's very common for
2d textures to have a transparent alpha channel.

## Solution

- Add an alpha mask phase identical to the one in 3d. It will do the
alpha masking in the shader before drawing the mesh.
- Uses the BinnedRenderPhase
- Since it's an opaque draw it also correctly writes to depth

## Testing

- Tested the mes2d_alpha_mode example and the bevymark example with
alpha mask mode enabled

---

## Showcase


![image](https://github.com/user-attachments/assets/9e5e4561-d0a7-4aa3-b049-d4b1247d5ed4)

The white logo on the right is rendered with alpha mask enabled.

Running the bevymark example I can get 65fps for 120k mesh2d all using
alpha mask.

## Notes

This is one more step for mesh2d improvements
https://github.com/bevyengine/bevy/issues/13265

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-08-15 14:10:37 +00:00
re0312
3bd039e821
Skip empty archetype/table (#14749)
# Objective

- As sander commneted on discord
[link](https://discord.com/channels/691052431525675048/749335865876021248/1273414144091230228),

![image](https://github.com/user-attachments/assets/62f2b6f3-1aaf-49d9-bafa-bf62b83b10be)





## Performance

![image](https://github.com/user-attachments/assets/11122940-1547-42ae-9576-0e1a93fd9f5f)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
2024-08-15 14:07:20 +00:00
Ben Frankel
6da2305e49
Add Command and co. to prelude (#14751)
# Objective

Make it easier to write and work with custom `Command`s and
`EntityCommand`s. See
https://discord.com/channels/691052431525675048/692572690833473578/1273030340235100214
for (brief) context.

## Solution

Re-export `Command`, `EntityCommand`, and `EntityCommands` in the
`bevy_ecs::prelude`, where `Commands` is already re-exported.
2024-08-15 13:33:32 +00:00
Christian Hughes
7d3068e6c3
Fix world borrow for DeferredWorld::query (#14744)
# Objective

As is, calling
[`DeferredWorld::query`](https://docs.rs/bevy/latest/bevy/ecs/world/struct.DeferredWorld.html#method.query)
requires you to first `reborrow()` the world in order to use it at all.

Simple reproduction:
```rust
fn test<'w>(mut world: DeferredWorld<'w>, mut state: QueryState<(), ()>) {
    let query = world.query(&mut state);
    // let query = world.reborrow().query(&mut state); // << Required
}
```

Error message:
```
error[E0597]: `world` does not live long enough
    |
444 | fn test<'w>(mut world: DeferredWorld<'w>, mut state: QueryState<(), ()>) {
    |         --  --------- binding `world` declared here
    |         |
    |         lifetime `'w` defined here
445 |     let query = world.query(&mut state);
    |                 ^^^^^------------------
    |                 |
    |                 borrowed value does not live long enough
    |                 argument requires that `world` is borrowed for `'w`
446 | }
    |  - `world` dropped here while still borrowed

```

## Solution

Fix the world borrow lifetime on the `query` method, which now correctly
allows the above usage.
2024-08-14 18:59:19 +00:00
eckz
46e8c6b662
Consistency between Wireframe2d and Wireframe (#14720)
# Objective

- Wireframe plugins have inconsistencies between 3D and 2D versions.
This PR addresses the following
  - 2d version uses `Srgba` for colors, 3d version uses `Color`.

  
## Solution

- This PR brings consistency by doing the following change
  - `Wireframe2d` now uses `Color` instead of `Srgba`

## Testing

- `wireframe_2d` and `wireframe` examples were verified and they work as
before.

---

## Migration Guide

- `Wireframe2dConfig`.`default_color` type is now `Color` instead of
`Srgba`. Use `.into()` to convert between them.
- `Wireframe2dColor`.`color` type is now `Color` instead of `Srgba`. Use
`.into()` to convert between them.
2024-08-13 18:57:47 +00:00
Josiah Putman
882973a528
Expose max_mip_dimension and uv_offset in BloomSettings. (#14512)
# Objective

By default, Bevy's bloom effect shows square artifacts on small bright
particles due to a low max mip resolution. This PR makes this
configurable via BloomSettings so users can customize these parameters
instead of having them in private module constants.

## Solution

Expose max_mip_dimension and uv_offset in BloomSettings.

## Testing

I tested these changes by running the Bloom 2D / 3D examples.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-13 15:01:42 +00:00
Gino Valente
6183b56b5d
bevy_reflect: Reflect remote types (#6042)
# Objective

The goal with this PR is to allow the use of types that don't implement
`Reflect` within the reflection API.

Rust's [orphan
rule](https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type)
prevents implementing a trait on an external type when neither type nor
trait are owned by the implementor. This means that if a crate,
`cool_rust_lib`, defines a type, `Foo`, then a user cannot use it with
reflection. What this means is that we have to ignore it most of the
time:

```rust
#[derive(Reflect)]
struct SomeStruct {
  #[reflect(ignore)]
  data: cool_rust_lib::Foo
}
```

Obviously, it's impossible to implement `Reflect` on `Foo`. But does it
*have* to be?

Most of reflection doesn't deal with concrete types— it's almost all
using `dyn Reflect`. And being very metadata-driven, it should
theoretically be possible. I mean,
[`serde`](https://serde.rs/remote-derive.html) does it.

## Solution

> Special thanks to @danielhenrymantilla for their help reviewing this
PR and offering wisdom wrt safety.

Taking a page out of `serde`'s book, this PR adds the ability to easily
use "remote types" with reflection. In this context, a "remote type" is
the external type for which we have no ability to implement `Reflect`.

This adds the `#[reflect_remote(...)]` attribute macro, which is used to
generate "remote type wrappers". All you have to do is define the
wrapper exactly the same as the remote type's definition:

```rust
// Pretend this is our external crate
mod cool_rust_lib {
  #[derive(Default)]
  struct Foo {
    pub value: String
  }
}

#[reflect_remote(cool_rust_lib::Foo)]
struct FooWrapper {
  pub value: String
}
```

> **Note:** All fields in the external type *must* be public. This could
be addressed with a separate getter/setter attribute either in this PR
or in another one.

The macro takes this user-defined item and transforms it into a newtype
wrapper around the external type, marking it as `#[repr(transparent)]`.
The fields/variants defined by the user are simply used to build out the
reflection impls.

Additionally, it generates an implementation of the new trait,
`ReflectRemote`, which helps prevent accidental misuses of this API.

Therefore, the output generated by the macro would look something like:

```rust
#[repr(transparent)]
struct FooWrapper(pub cool_rust_lib::Foo);

impl ReflectRemote for FooWrapper {
  type Remote = cool_rust_lib::Foo;

  // transmutation methods...
}

// reflection impls...
// these will acknowledge and make use of the `value` field
```

Internally, the reflection API will pass around the `FooWrapper` and
[transmute](https://doc.rust-lang.org/std/mem/fn.transmute.html) it
where necessary. All we have to do is then tell `Reflect` to do that. So
rather than ignoring the field, we tell `Reflect` to use our wrapper
using the `#[reflect(remote = ...)]` field attribute:

```rust
#[derive(Reflect)]
struct SomeStruct {
  #[reflect(remote = FooWrapper)]
  data: cool_rust_lib::Foo
}
```

#### Other Macros & Type Data

Because this macro consumes the defined item and generates a new one, we
can't just put our macros anywhere. All macros that should be passed to
the generated struct need to come *below* this macro. For example, to
derive `Default` and register its associated type data:

```rust
//  GOOD
#[reflect_remote(cool_rust_lib::Foo)]
#[derive(Default)]
#[reflect(Default)]
struct FooWrapper {
  pub value: String
}

//  BAD
#[derive(Default)]
#[reflect_remote(cool_rust_lib::Foo)]
#[reflect(Default)]
struct FooWrapper {
  pub value: String
}
```

#### Generics

Generics are forwarded to the generated struct as well. They should also
be defined in the same order:

```rust
#[reflect_remote(RemoteGeneric<'a, T1, T2>)]
struct GenericWrapper<'a, T1, T2> {
  pub foo: &'a T1,
  pub bar: &'a T2,
}
```

> Naming does *not* need to match the original definition's. Only order
matters here.

> Also note that the code above is just a demonstration and doesn't
actually compile since we'd need to enforce certain bounds (e.g. `T1:
Reflect`, `'a: 'static`, etc.)

#### Nesting

And, yes, you can nest remote types:

```rust
#[reflect_remote(RemoteOuter)]
struct OuterWrapper {
  #[reflect(remote = InnerWrapper)]
  pub inner: RemoteInner
}

#[reflect_remote(RemoteInner)]
struct InnerWrapper(usize);
```

#### Assertions

This macro will also generate some compile-time assertions to ensure
that the correct types are used. It's important we catch this early so
users don't have to wait for something to panic. And it also helps keep
our `unsafe` a little safer.

For example, a wrapper definition that does not match its corresponding
remote type will result in an error:

```rust
mod external_crate {
  pub struct TheirStruct(pub u32);
}

#[reflect_remote(external_crate::TheirStruct)]
struct MyStruct(pub String); // ERROR: expected type `u32` but found `String`
```

<details>
<summary>Generated Assertion</summary>

```rust
const _: () = {
  #[allow(non_snake_case)]
  #[allow(unused_variables)]
  #[allow(unused_assignments)]
  #[allow(unreachable_patterns)]
  #[allow(clippy::multiple_bound_locations)]
  fn assert_wrapper_definition_matches_remote_type(
    mut __remote__: external_crate::TheirStruct,
  ) {
    __remote__.0 = (|| -> ::core::option::Option<String> { None })().unwrap();
  }
};
```

</details>

Additionally, using the incorrect type in a `#[reflect(remote = ...)]`
attribute should result in an error:

```rust
mod external_crate {
  pub struct TheirFoo(pub u32);
  pub struct TheirBar(pub i32);
}

#[reflect_remote(external_crate::TheirFoo)]
struct MyFoo(pub u32);

#[reflect_remote(external_crate::TheirBar)]
struct MyBar(pub i32);

#[derive(Reflect)]
struct MyStruct {
  #[reflect(remote = MyBar)] // ERROR: expected type `TheirFoo` but found struct `TheirBar`
  foo: external_crate::TheirFoo
}
```

<details>
<summary>Generated Assertion</summary>

```rust
const _: () = {
    struct RemoteFieldAssertions;
    impl RemoteFieldAssertions {
        #[allow(non_snake_case)]
        #[allow(clippy::multiple_bound_locations)]
        fn assert__foo__is_valid_remote() {
            let _: <MyBar as bevy_reflect::ReflectRemote>::Remote = (|| -> ::core::option::Option<external_crate::TheirFoo> {
              None
            })().unwrap();
        }
    }
};
```

</details>

### Discussion

There are a couple points that I think still need discussion or
validation.

- [x] 1. `Any` shenanigans

~~If we wanted to downcast our remote type from a `dyn Reflect`, we'd
have to first downcast to the wrapper then extract the inner type. This
PR has a [commit](b840db9f74cb6d357f951cb11b150d46bac89ee2) that
addresses this by making all the `Reflect::*any` methods return the
inner type rather than the wrapper type. This allows us to downcast
directly to our remote type.~~

~~However, I'm not sure if this is something we want to do. For
unknowing users, it could be confusing and seemingly inconsistent. Is it
worth keeping? Or should this behavior be removed?~~

I think this should be fine. The remote wrapper is an implementation
detail and users should not need to downcast to the wrapper type. Feel
free to let me know if there are other opinions on this though!

- [x] 2. Implementing `Deref/DerefMut` and `From`

~~We don't currently do this, but should we implement other traits on
the generated transparent struct? We could implement `Deref`/`DerefMut`
to easily access the inner type. And we could implement `From` for
easier conversion between the two types (e.g. `T: Into<Foo>`).~~ As
mentioned in the comments, we probably don't need to do this. Again, the
remote wrapper is an implementation detail, and should generally not be
used directly.
     
- [x] 3. ~~Should we define a getter/setter field attribute in this PR
as well or leave it for a future one?~~ I think this should be saved for
a future PR

- [ ] 4. Any foreseeable issues with this implementation?

#### Alternatives

One alternative to defining our own `ReflectRemote` would be to use
[bytemuck's
`TransparentWrapper`](https://docs.rs/bytemuck/1.13.1/bytemuck/trait.TransparentWrapper.html)
(as suggested by @danielhenrymantilla).

This is definitely a viable option, as `ReflectRemote` is pretty much
the same thing as `TransparentWrapper`. However, the cost would be
bringing in a new crate— though, it is already in use in a few other
sub-crates like bevy_render.

I think we're okay just defining `ReflectRemote` ourselves, but we can
go the bytemuck route if we'd prefer offloading that work to another
crate.

---

## Changelog

* Added the `#[reflect_remote(...)]` attribute macro to allow `Reflect`
to be used on remote types
* Added `ReflectRemote` trait for ensuring proper remote wrapper usage
2024-08-12 19:12:53 +00:00
Tau Gärtli
aab1f8e435
Use #[doc(fake_variadic)] to improve docs readability (#14703)
# Objective

- Fixes #14697

## Solution

This PR modifies the existing `all_tuples!` macro to optionally accept a
`#[doc(fake_variadic)]` attribute in its input. If the attribute is
present, each invocation of the impl macro gets the correct attributes
(i.e. the first impl receives `#[doc(fake_variadic)]` while the other
impls are hidden using `#[doc(hidden)]`.
Impls for the empty tuple (unit type) are left untouched (that's what
the [standard
library](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq-for-())
and
[serde](https://docs.rs/serde/latest/serde/trait.Serialize.html#impl-Serialize-for-())
do).

To work around https://github.com/rust-lang/cargo/issues/8811 and to get
impls on re-exports to correctly show up as variadic, `--cfg docsrs_dep`
is passed when building the docs for the toplevel `bevy` crate.

`#[doc(fake_variadic)]` only works on tuples and fn pointers, so impls
for structs like `AnyOf<(T1, T2, ..., Tn)>` are unchanged.

## Testing

I built the docs locally using `RUSTDOCFLAGS='--cfg docsrs'
RUSTFLAGS='--cfg docsrs_dep' cargo +nightly doc --no-deps --workspace`
and checked the documentation page of a trait both in its original crate
and the re-exported version in `bevy`.
The description should correctly mention for how many tuple items the
trait is implemented.

I added `rustc-args` for docs.rs to the `bevy` crate, I hope there
aren't any other notable crates that re-export `#[doc(fake_variadic)]`
traits.

---

## Showcase

`bevy_ecs::query::QueryData`:
<img width="1015" alt="Screenshot 2024-08-12 at 16 41 28"
src="https://github.com/user-attachments/assets/d40136ed-6731-475f-91a0-9df255cd24e3">

`bevy::ecs::query::QueryData` (re-export):
<img width="1005" alt="Screenshot 2024-08-12 at 16 42 57"
src="https://github.com/user-attachments/assets/71d44cf0-0ab0-48b0-9a51-5ce332594e12">

## Original Description

<details>

Resolves #14697

Submitting as a draft for now, very WIP.

Unfortunately, the docs don't show the variadics nicely when looking at
reexported items.
For example:

`bevy_ecs::bundle::Bundle` correctly shows the variadic impl:

![image](https://github.com/user-attachments/assets/90bf8af1-1d1f-4714-9143-cdd3d0199998)

while `bevy::ecs::bundle::Bundle` (the reexport) shows all the impls
(not good):

![image](https://github.com/user-attachments/assets/439c428e-f712-465b-bec2-481f7bf5870b)

Built using `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --workspace
--no-deps` (`--no-deps` because of wgpu-core).

Maybe I missed something or this is a limitation in the *totally not
private* `#[doc(fake_variadic)]` thingy. In any case I desperately need
some sleep now :))

</details>
2024-08-12 18:54:33 +00:00
radiish
6ab8767d3b
reflect: implement the unique reflect rfc (#7207)
# Objective

- Implements the [Unique Reflect
RFC](https://github.com/nicopap/rfcs/blob/bevy-reflect-api/rfcs/56-better-reflect.md).

## Solution

- Implements the RFC.
- This implementation differs in some ways from the RFC:
- In the RFC, it was suggested `Reflect: Any` but `PartialReflect:
?Any`. During initial implementation I tried this, but we assume the
`PartialReflect: 'static` in a lot of places and the changes required
crept out of the scope of this PR.
- `PartialReflect::try_into_reflect` originally returned `Option<Box<dyn
Reflect>>` but i changed this to `Result<Box<dyn Reflect>, Box<dyn
PartialReflect>>` since the method takes by value and otherwise there
would be no way to recover the type. `as_full` and `as_full_mut` both
still return `Option<&(mut) dyn Reflect>`.

---

## Changelog

- Added `PartialReflect`.
- `Reflect` is now a subtrait of `PartialReflect`.
- Moved most methods on `Reflect` to the new `PartialReflect`.
- Added `PartialReflect::{as_partial_reflect, as_partial_reflect_mut,
into_partial_reflect}`.
- Added `PartialReflect::{try_as_reflect, try_as_reflect_mut,
try_into_reflect}`.
- Added `<dyn PartialReflect>::{try_downcast_ref, try_downcast_mut,
try_downcast, try_take}` supplementing the methods on `dyn Reflect`.

## Migration Guide

- Most instances of `dyn Reflect` should be changed to `dyn
PartialReflect` which is less restrictive, however trait bounds should
generally stay as `T: Reflect`.
- The new `PartialReflect::{as_partial_reflect, as_partial_reflect_mut,
into_partial_reflect, try_as_reflect, try_as_reflect_mut,
try_into_reflect}` methods as well as `Reflect::{as_reflect,
as_reflect_mut, into_reflect}` will need to be implemented for manual
implementors of `Reflect`.

## Future Work

- This PR is designed to be followed up by another "Unique Reflect Phase
2" that addresses the following points:
- Investigate making serialization revolve around `Reflect` instead of
`PartialReflect`.
- [Remove the `try_*` methods on `dyn PartialReflect` since they are
stop
gaps](https://github.com/bevyengine/bevy/pull/7207#discussion_r1083476050).
- Investigate usages like `ReflectComponent`. In the places they
currently use `PartialReflect`, should they be changed to use `Reflect`?
- Merging this opens the door to lots of reflection features we haven't
been able to implement.
- We could re-add [the `Reflectable`
trait](8e3488c880/crates/bevy_reflect/src/reflect.rs (L337-L342))
and make `FromReflect` a requirement to improve [`FromReflect`
ergonomics](https://github.com/bevyengine/rfcs/pull/59). This is
currently not possible because dynamic types cannot sensibly be
`FromReflect`.
  - Since this is an alternative to #5772, #5781 would be made cleaner.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-08-12 17:01:41 +00:00
callym
7b81ae7e40
Update WGPU to version 22 (#14401)
Upgrading to WGPU 22.

Needs `naga_oil` to upgrade first, I've got a fork that compiles but
fails tests, so until that's fixed and the crate is officially
updated/released this will be blocked.

---------

Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
2024-08-12 16:55:18 +00:00
re0312
032fd486c7
View filter for batch_and_prepare_render_phase (#14713)
# Objective
- batch_and_prepare_render_phase will iterate all living entities ,which
potentially causes a lot of unnecessary look up
- from
https://github.com/bevyengine/bevy/pull/14449#issuecomment-2282876034

## Solution

- added View filter
2024-08-12 16:15:54 +00:00
Matty
61a1530c56
Make bevy_math's libm feature use libm for all f32methods with unspecified precision (#14693)
# Objective

Closes #14474

Previously, the `libm` feature of bevy_math would just pass the same
feature flag down to glam. However, bevy_math itself had many uses of
floating-point arithmetic with unspecified precision. For example,
`f32::sin_cos` and `f32::powi` have unspecified precision, which means
that the exact details of their output are not guaranteed to be stable
across different systems and/or versions of Rust. This means that users
of bevy_math could observe slightly different behavior on different
systems if these methods were used.

The goal of this PR is to make it so that the `libm` feature flag
actually guarantees some degree of determinacy within bevy_math itself
by switching to the libm versions of these functions when the `libm`
feature is enabled.

## Solution

bevy_math now has an internal module `bevy_math::ops`, which re-exports
either the standard versions of the operations or the libm versions
depending on whether the `libm` feature is enabled. For example,
`ops::sin` compiles to `f32::sin` without the `libm` feature and to
`libm::sinf` with it.

This approach has a small shortfall, which is that `f32::powi` (integer
powers of floating point numbers) does not have an equivalent in `libm`.
On the other hand, this method is only used for squaring and cubing
numbers in bevy_math. Accordingly, this deficit is covered by the
introduction of a trait `ops::FloatPow`:
```rust
pub(crate) trait FloatPow {
    fn squared(self) -> Self;
    fn cubed(self) -> Self;
}
```

Next, each current usage of the unspecified-precision methods has been
replaced by its equivalent in `ops`, so that when `libm` is enabled, the
libm version is used instead. The exception, of course, is that
`.powi(2)`/`.powi(3)` have been replaced with `.squared()`/`.cubed()`.

Finally, the usage of the plain `f32` methods with unspecified precision
is now linted out of bevy_math (and hence disallowed in CI). For
example, using `f32::sin` within bevy_math produces a warning that tells
the user to use the `ops::sin` version instead.

## Testing

Ran existing tests. It would be nice to check some benchmarks on NURBS
things once #14677 merges. I'm happy to wait until then if the rest of
this PR is fine.

---

## Discussion

In the future, it might make sense to actually expose `bevy_math::ops`
as public if any downstream Bevy crates want to provide similar
determinacy guarantees. For now, it's all just `pub(crate)`.

This PR also only covers `f32`. If we find ourselves using `f64`
internally in parts of bevy_math for better robustness, we could extend
the module and lints to cover the `f64` versions easily enough.

I don't know how feasible it is, but it would also be nice if we could
standardize the bevy_math tests with the `libm` feature in CI, since
their success is currently platform-dependent (e.g. 8 of them fail on my
machine when run locally).

---------

Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
2024-08-12 16:13:36 +00:00
databasedav
c8d30edf1a
add SystemIdMarker Component to enable filtering for SystemId Entitys (#14584)
# Objective

Enables writing queries like `Query<Entity, With<SystemIdMarker>>` to
filter `Entity`s that are, or are not (with `Without`), `SystemId`s.

## Solution

Simple unit struct `SystemIdMarker` added during
`World::register_boxed_system`; `World::remove_system` already despawns
the entity, removing the marker.

## Testing

No tests, but happy to write some with direction.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-12 16:11:06 +00:00
databasedav
c3111bebb8
document using ObserverState as filter for Observer Entitys (#14669)
# Objective

~~Enables writing queries like `Query<Entity, With<ObserverMarker>>` to
filter `Entity`s that are, or are not (with `Without`), `Observer`s.~~

~~`Observer` version of [similar
PR](https://github.com/bevyengine/bevy/pull/14584) for `SystemId`s.~~

just adding a line to the docs :)

## Solution

~~Simple unit struct `ObserverMarker` added in `Observer`'s `.on_add`
component hook.~~

## Testing

No tests, but happy to write some with direction.
2024-08-12 16:07:03 +00:00
Sarthak Singh
2c4ef37b76
Changed Mesh::attributes* functions to return MeshVertexAttribute (#14394)
# Objective

Fixes #14365 

## Migration Guide

- When using the iterator returned by `Mesh::attributes` or
`Mesh::attributes_mut` the first value of the tuple is not the
`MeshVertexAttribute` instead of `MeshVertexAttributeId`. To access the
`MeshVertexAttributeId` use the `MeshVertexAttribute.id` field.

Signed-off-by: Sarthak Singh <sarthak.singh99@gmail.com>
2024-08-12 15:54:28 +00:00
Eero Lehtinen
47c4e3084a
Add custom cursors (#14284)
# Objective

- Add custom images as cursors
- Fixes #9557 

## Solution

- Change cursor type to accommodate both native and image cursors
- I don't really like this solution because I couldn't use
`Handle<Image>` directly. I would need to import `bevy_assets` and that
causes a circular dependency. Alternatively we could use winit's
`CustomCursor` smart pointers, but that seems hard because the event
loop is needed to create those and is not easily accessable for users.
So now I need to copy around rgba buffers which is sad.
- I use a cache because especially on the web creating cursor images is
really slow
- Sorry to #14196 for yoinking, I just wanted to make a quick solution
for myself and thought that I should probably share it too.

Update:
- Now uses `Handle<Image>`, reads rgba data in `bevy_render` and uses
resources to send the data to `bevy_winit`, where the final cursors are
created.

## Testing

- Added example which works fine at least on Linux Wayland (winit side
has been tested with all platforms).
- I haven't tested if the url cursor works.

## Migration Guide

- `CursorIcon` is no longer a field in `Window`, but a separate
component can be inserted to a window entity. It has been changed to an
enum that can hold custom images in addition to system icons.
- `Cursor` is renamed to `CursorOptions` and `cursor` field of `Window`
is renamed to `cursor_options`
- `CursorIcon` is renamed to `SystemCursorIcon`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-08-12 15:49:03 +00:00
Chris Russell
d4ec80d5d2
Support more kinds of system params in buildable systems. (#14050)
# Objective

Support more kinds of system params in buildable systems, such as a
`ParamSet` or `Vec` containing buildable params or tuples of buildable
params.

## Solution

Replace the `BuildableSystemParam` trait with `SystemParamBuilder` to
make it easier to compose builders. Provide implementations for existing
buildable params, plus tuples, `ParamSet`, and `Vec`.

## Examples

```rust
// ParamSet of tuple: 
let system = (ParamSetBuilder((
    QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
    QueryParamBuilder::new(|builder| { builder.with::<C>(); }),
)),)
    .build_state(&mut world)
    .build_system(|mut params: ParamSet<(Query<&mut A>, Query<&mut A>)>| {
        params.p0().iter().count() + params.p1().iter().count()
    });
	
// ParamSet of Vec:
let system = (ParamSetBuilder(vec![
    QueryParamBuilder::new_box(|builder| { builder.with::<B>(); }),
    QueryParamBuilder::new_box(|builder| { builder.with::<C>(); }),
]),)
    .build_state(&mut world)
    .build_system(|mut params: ParamSet<Vec<Query<&mut A>>>| {
        let mut count = 0;
        params.for_each(|mut query| count += query.iter_mut().count());
        count
    });
```

## Migration Guide

The API for `SystemBuilder` has changed. Instead of constructing a
builder with a world and then adding params, you first create a tuple of
param builders and then supply the world.

```rust
// Before
let system = SystemBuilder::<()>::new(&mut world)
    .local::<u64>()
    .builder::<Local<u64>>(|x| *x = 10)
    .builder::<Query<&A>>(|builder| { builder.with::<B>(); })
    .build(system);

// After
let system = (
    ParamBuilder,
    LocalBuilder(10),
    QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
)
    .build_state(&mut world)
    .build_system(system);
```

## Possible Future Work

Here are a few possible follow-up changes. I coded them up to prove that
this API can support them, but they aren't necessary for this PR.

* chescock/bevy#1
* chescock/bevy#2
* chescock/bevy#3
2024-08-12 15:45:35 +00:00
IceSentry
9d6a4fbc85
Use BinnedRenderPhase for Opaque2d (#13091)
Based on top of #12982  and #13069 

# Objective

- Opaque2d was implemented with SortedRenderPhase but BinnedRenderPhase
should be much faster

## Solution

- Implement BinnedRenderPhase for Opaque2d

## Notes

While testing this PR, before the change I had ~14 fps in bevymark with
100k entities. After this change I get ~71 fps, compared to using
sprites where I only get ~63 fps. This means that after this PR mesh2d
with opaque meshes will be faster than the sprite path. This is not a 1
to 1 comparison since sprites do alpha blending.
2024-08-12 15:38:24 +00:00
Christian Hughes
7f658cabf7
Replace UnsafeCell<World> usage with UnsafeWorldCell in CombinatorSystem (#14706)
# Objective

Replace usage of `UnsafeCell<World>` with our standard `UnsafeWorldCell`
that seemed to have been missed.

## Solution

Do just that.
2024-08-11 13:58:10 +00:00
TotalKrill
3e10fd8534
Mod picking upstream 2 (#14686)
Ci fixed  version of: #14541 

Upstream the remainder of bevy_picking_core and all of
bevy_picking_input.

This work is intentionally nonfunctional and has minimal changes, but
does compile. More work is necessary to replace bevy_eventlistener with
propagating observers.

This work is being coordinated as part of "bevy_mod_picking upstream"
working group. Come say hi on discord!

---------

Co-authored-by: Miles Silberling-Cook <nth.tensor@gmail.com>
Co-authored-by: Aevyrie <aevyrie@gmail.com>
2024-08-09 23:16:37 +00:00
re0312
e490b919df
inline iter_combinations (#14680)
# Objective
- fix #14679 
- bevy's performance highly depends on compiler optimization,inline hot
function could greatly help compiler to optimize our program
2024-08-09 17:44:37 +00:00
Matty
23e87270df
A Curve trait for general interoperation — Part I (#14630)
# Objective

This PR implements part of the [Curve
RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/80-curve-trait.md).
See that document for motivation, objectives, etc.

## Solution

For purposes of reviewability, this PR excludes the entire part of the
RFC related to taking multiple samples, resampling, and interpolation
generally. (This means the entire `cores` submodule is also excluded.)
On the other hand, the entire `Interval` type and all of the functional
`Curve` adaptors are included.

## Testing

Test modules are included and can be run locally (but they are also
included in CI).

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-09 14:19:44 +00:00
re0312
66bf160ec5
Explicit using clone_from (#14670)
# Objective

- after #14502 ,explicit using clone_from should has better performance
because it could reuse the resources to avoid unnecessary allocations.
2024-08-09 14:17:13 +00:00
AFKessen
e14f3cf402
Fix 3D Gizmo webgpu rendering (#14653)
# Objective

The changes made in https://github.com/bevyengine/bevy/pull/12252
introduced an previously fixed bug in webgpu rendering.

## Solution

This fix is based on https://github.com/bevyengine/bevy/pull/8910 and
applies the same vertex buffer layout assignment for the LineGizmo
Pipeline.

## Testing

- Tested the 3D Gizmo example in webgpu and webgl environments

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-09 02:55:56 +00:00
Gino Valente
297c0a3954
bevy_reflect: Add DynamicSet to dynamic_types example (#14665)
# Objective

The `dynamic_types` example was missing a reference to the newly added
`DynamicSet` type.

## Solution

Add `DynamicSet` to the `dynamic_types` example.

For parity with the other dynamic types, I also implemented
`FromIterator<T: Reflect>`, `FromIterator<Box<dyn Reflect>>`, and
`IntoIterator for &DynamicSet`.

## Testing

You can run the example locally:

```
cargo run --example dynamic_types
```
2024-08-08 22:26:18 +00:00
Gino Valente
aeef1c0f20
bevy_reflect: Update internal docs regarding anonymous function type names (#14666)
# Objective

As pointed out by @SkiFire13 on
[Discord](https://discord.com/channels/691052431525675048/1002362493634629796/1270624366119485441),
I was incorrect in #14641 regarding the type name of anonymous
functions. I had stated that they will return something like `fn(i32,
i32) -> i32`, but this is wrong. They actually behave like closures
(despite not technically being closures) and return something more like
`foo::bar::{{closure}}`.

This isn't a major issue because the reasoning behind #14641 still
stands. However, the internal documentation should probably be updated
so future contributors don't believe the lies I left behind.

## Solution

Updated the internal documentation for `create_info` to reflect the
actual type name of an anonymous function.

In that same module, I also added a test for function pointers and
updated all tests to include sanity checks for the `std::any::type_name`
of each category of callable.

## Testing

You can test locally by running:

```
cargo test --package bevy_reflect
```
2024-08-08 22:01:42 +00:00
Gino Valente
3f47273b72
bevy_state: Make reflect module public (#14667)
# Objective

CI is
[failing](https://github.com/bevyengine/bevy/actions/runs/10308658332/job/28536587448)
due to certain methods not being used.

## Solution

Make the `reflect` module public so that these warnings go away and so
that the `pub` items in these modules can be used.

## Testing

CI should pass.
2024-08-08 20:15:38 +00:00
eckz
8c2e70b744
Adding Reflect data types for States and FreelyMutableState. (#14643)
# Objective

- While developing a debug tool I saw the gap where it was not possible
to get all existing states from a World using reflection.
- This PR allows to iterate over all `States` types that exist in a
world, and modify them in case they implement `FreelyMutableState`.
- Two new methods are available on `App` and `SubApp` as helper to
register the data types:
  -  `register_state_reflect` and `register_mutable_state_reflect`

## Solution

- Two new data types are added:
- `ReflectState`: Allows to extract the current value of a state from
the World.
- `ReflectFreelyMutableState`: Allows to set the next state in a world,
similar to call `NextState::set`.
- There is no distinction between `States`, `SubStates` and
`ComputedStates`:
- `States` can register both `ReflectState` and
`ReflectFreelyMutableState`.
- `SubStates` can register both `ReflectState` and
`ReflectFreelyMutableState`.
  -  `ComputedStates` can register only `ReflectState` .

## Testing

- Added tests inside the `bevy_state` crate.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-08-08 00:07:00 +00:00
charlotte
994312ac6d
Fix TAA on camera with viewport (#14582)
# Objective

Closes #14526 

## Solution

The history texture was being created incorrectly with the viewport size
rather than target size. When viewport < target, this meant that the
render attachments would differer in size which causes a wgpu validation
error.

## Testing

Example in linked issue works.
2024-08-07 23:59:38 +00:00
Gino Valente
a0cc636ea3
bevy_reflect: Anonymous function parsing (#14641)
# Objective

### TL;DR

#14098 added the `FunctionRegistry` but had some last minute
complications due to anonymous functions. It ended up going with a
"required name" approach to ensure anonymous functions would always have
a name.

However, this approach isn't ideal for named functions since, by
definition, they will always have a name.

Therefore, this PR aims to modify function reflection such that we can
make function registration easier for named functions, while still
allowing anonymous functions to be registered as well.

### Context

Function registration (#14098) ran into a little problem: anonymous
functions.

Anonymous functions, including function pointers, have very non-unique
type names. For example, the anonymous function `|a: i32, b: i32| a + b`
has the type name of `fn(i32, i32) -> i32`. This obviously means we'd
conflict with another function like `|a: i32, b: i32| a - b`.

The solution that #14098 landed on was to always require a name during
function registration.

The downside with this is that named functions (e.g. `fn add(a: i32, b:
i32) -> i32 { a + b }`) had to redundantly provide a name. Additionally,
manually constructed `DynamicFunction`s also ran into this ergonomics
issue.

I don't entirely know how the function registry will be used, but I have
a strong suspicion that most of its registrations will either be named
functions or manually constructed `DynamicFunction`s, with anonymous
functions only being used here and there for quick prototyping or adding
small functionality.

Why then should the API prioritize the anonymous function use case by
always requiring a name during registration?

#### Telling Functions Apart

Rust doesn't provide a lot of out-of-the-box tools for reflecting
functions. One of the biggest hurdles in attempting to solve the problem
outlined above would be to somehow tell the different kinds of functions
apart.

Let's briefly recap on the categories of functions in Rust:

| Category           | Example                                   |
| ------------------ | ----------------------------------------- |
| Named function     | `fn add(a: i32, b: i32) -> i32 { a + b }` |
| Closure            | `\|a: i32\| a + captured_variable`          |
| Anonymous function | `\|a: i32, b: i32\| a + b`                  |
| Function pointer   | `fn(i32, i32) -> i32`                     |

My first thought was to try and differentiate these categories based on
their size. However, we can see that this doesn't quite work:

| Category           | `size_of` |
| ------------------ | --------- |
| Named function     | 0         |
| Closure            | 0+        |
| Anonymous function | 0         |
| Function pointer   | 8         |

Not only does this not tell anonymous functions from named ones, but it
struggles with pretty much all of them.

My second then was to differentiate based on type name:

| Category           | `type_name`             |
| ------------------ | ----------------------- |
| Named function     | `foo::bar::baz`         |
| Closure            | `foo::bar::{{closure}}` |
| Anonymous function | `fn() -> String`        |
| Function pointer   | `fn() -> String`        |

This is much better. While it can't distinguish between function
pointers and anonymous functions, this doesn't matter too much since we
only care about whether we can _name_ the function.

So why didn't we implement this in #14098?

#### Relying on `type_name`

While this solution was known about while working on #14098, it was left
out from that PR due to it being potentially controversial.

The [docs](https://doc.rust-lang.org/stable/std/any/fn.type_name.html)
for `std::any::type_name` state:

> The returned string must not be considered to be a unique identifier
of a type as multiple types may map to the same type name. Similarly,
there is no guarantee that all parts of a type will appear in the
returned string: for example, lifetime specifiers are currently not
included. In addition, the output may change between versions of the
compiler.

So that's it then? We can't use `type_name`?

Well, this statement isn't so much a rule as it is a guideline. And Bevy
is no stranger to bending the rules to make things work or to improve
ergonomics. Remember that before `TypePath`, Bevy's scene system was
entirely dependent on `type_name`. Not to mention that `type_name` is
being used as a key into both the `TypeRegistry` and the
`FunctionRegistry`.

Bevy's practices aside, can we reliably use `type_name` for this?

My answer would be "yes".

Anonymous functions are anonymous. They have no name. There's nothing
Rust could do to give them a name apart from generating a random string
of characters. But remember that this is a diagnostic tool, it doesn't
make sense to obfuscate the type by randomizing the output. So changing
it to be anything other than what it is now is very unlikely.

The only changes that I could potentially see happening are:

1. Closures replace `{{closure}}` with the name of their variable
2. Lifetimes are included in the output

I don't think the first is likely to happen, but if it does then it
actually works out in our favor: closures are now named!

The second point is probably the likeliest. However, adding lifetimes
doesn't mean we can't still rely on `type_name` to determine whether or
not a function is named. So we should be okay in this case as well.

## Solution

Parse the `type_name` of the function in the `TypedFunction` impl to
determine if the function is named or anonymous.

This once again makes `FunctionInfo::name` optional. For manual
constructions of `DynamicFunction`, `FunctionInfo::named` or
``FunctionInfo::anonymous` can be used.

The `FunctionRegistry` API has also been reworked to account for this
change.

`FunctionRegistry::register` no longer takes a name and instead takes it
from the supplied function, returning a
`FunctionRegistrationError::MissingName` error if the name is `None`.
This also doubles as a replacement for the old
`FunctionRegistry::register_dynamic` method, which has been removed.

To handle anonymous functions, a `FunctionRegistry::register_with_name`
method has been added. This works in the same way
`FunctionRegistry::register` used to work before this PR.

The overwriting methods have been updated in a similar manner, with
modifications to `FunctionRegistry::overwrite_registration`, the removal
of `FunctionRegistry::overwrite_registration_dynamic`, and the addition
of `FunctionRegistry::overwrite_registration_with_name`.

This PR also updates the methods on `App` in a similar way:
`App::register_function` no longer requires a name argument and
`App::register_function_with_name` has been added to handle anonymous
functions (and eventually closures).

## Testing

You can run the tests locally by running:

```
cargo test --package bevy_reflect --features functions
```

---

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

> [!note]
> This list is not exhaustive. It only contains some of the most
important changes.

`FunctionRegistry::register` no longer requires a name string for named
functions. Anonymous functions, however, need to be registered using
`FunctionRegistry::register_with_name`.

```rust
// BEFORE
registry
  .register(std::any::type_name_of_val(&foo), foo)?
  .register("bar", || println!("Hello world!"));

// AFTER
registry
  .register(foo)?
  .register_with_name("bar", || println!("Hello world!"));
```

`FunctionInfo::name` is now optional. Anonymous functions and closures
will now have their name set to `None` by default. Additionally,
`FunctionInfo::new` has been renamed to `FunctionInfo::named`.
2024-08-07 03:11:08 +00:00
IceSentry
5abc32ceda
Add 2d opaque phase with depth buffer (#13069)
This PR is based on top of #12982

# Objective

- Mesh2d currently only has an alpha blended phase. Most sprites don't
need transparency though.
- For some 2d games it can be useful to have a 2d depth buffer

## Solution

- Add an opaque phase to render Mesh2d that don't need transparency
- This phase currently uses the `SortedRenderPhase` to make it easier to
implement based on the already existing transparent phase. A follow up
PR will switch this to `BinnedRenderPhase`.
- Add a 2d depth buffer
- Use that depth buffer in the transparent phase to make sure that
sprites and transparent mesh2d are displayed correctly

## Testing

I added the mesh2d_transforms example that layers many opaque and
transparent mesh2d to make sure they all get displayed correctly. I also
confirmed it works with sprites by modifying that example locally.

---

## Changelog

- Added `AlphaMode2d`
- Added `Opaque2d` render phase
- Camera2d now have a `ViewDepthTexture` component

## Migration Guide

- `ColorMaterial` now contains `AlphaMode2d`. To keep previous
behaviour, use `AlphaMode::BLEND`. If you know your sprite is opaque,
use `AlphaMode::OPAQUE`

## Follow up PRs

- See tracking issue: #13265

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
2024-08-07 00:22:09 +00:00
Periwink
2334638556
Fix access conflicts for resources (#14635)
# Objective

- I made a mistake when fixing the merge conflicts here:
https://github.com/bevyengine/bevy/pull/14579#discussion_r1705377452

It wasn't caught because there's no easy way to trigger access conflicts
with resources without triggering them with components first.
2024-08-06 14:35:41 +00:00
Lubba64
8e20a3e313
Fix gizmos regression (#14633)
# Objective

- Fixes #14142

## Solution

- Make sure a regression test is written on this case that fails for the
current code base but works with the suggested patch linked in the
aforementioned issue. After this is confirmed to be working, apply the
patch.

## Testing

- Run the regression test in both contexts, outputs were as expected.
2024-08-06 14:00:32 +00:00
Zhixing Zhang
5fd0661c15
Making bevy_render an optional dependency for bevy_gizmos (#14448)
# Objective

This PR makes `bevy_render` an optional dependency for `bevy_gizmos`,
thereby allowing `bevy_gizmos` to be used with alternative rendering
backend.

Previously `bevy_gizmos` assumes that one of `bevy_pbr` or `bevy_sprite`
will be enabled. Here we introduced a new feature named `bevy_render`
which disables all rendering-related code paths. An alternative renderer
will then take the `LineGizmo` assets (made public in this PR) and issue
draw calls on their own. A new field `config_ty` was added to
`LineGizmo` to help looking up the related configuration info.

---

## Migration Guide
No user-visible changes needed from the users.
2024-08-06 13:09:10 +00:00
Periwink
e85c072372
Fix soudness issue with Conflicts involving read_all and write_all (#14579)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/14575
- There is a soundness issue because we use `conflicts()` to check for
system ambiguities + soundness issues. However since the current
conflicts is a `Vec<T>`, we cannot express conflicts where there is no
specific `ComponentId` at fault. For example `q1: Query<EntityMut>, q2:
Query<EntityMut>`
There was a TODO to handle the `write_all` case but it was never
resolved


## Solution

- Introduce an `AccessConflict` enum that is either a list of specific
ids that are conflicting or `All` if all component ids are conflicting

## Testing

- Introduced a new unit test to check for the `EntityMut` case

## Migration guide

The `get_conflicts` method of `Access` now returns an `AccessConflict`
enum instead of simply a `Vec` of `ComponentId`s that are causing the
access conflict. This can be useful in cases where there are no
particular `ComponentId`s conflicting, but instead **all** of them are;
for example `fn system(q1: Query<EntityMut>, q2: Query<EntityRef>)`
2024-08-06 10:55:31 +00:00
charlotte
3360b45153
Expose winit's MonitorHandle (#13669)
# Objective

Adds a new `Monitor` component representing a winit `MonitorHandle` that
can be used to spawn new windows and check for system monitor
information.

Closes #12955.

## Solution

For every winit event, check available monitors and spawn them into the
world as components.

## Testing

TODO:
- [x] Test plugging in and unplugging monitor during app runtime
- [x] Test spawning a window on a second monitor by entity id
- [ ] Since this touches winit, test all platforms

---

## Changelog

- Adds a new `Monitor` component that can be queried for information
about available system monitors.

## Migration Guide

- `WindowMode` variants now take a `MonitorSelection`, which can be set
to `MonitorSelection::Primary` to mirror the old behavior.

---------

Co-authored-by: Pascal Hertleif <pascal@technocreatives.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2024-08-06 10:54:37 +00:00
Lubba64
897625c899
Add Reflect to OnReplace (#14620)
# Objective

- Fixes #14337 

## Solution

- Add a `cfg_attr` that derives `Refect` for this type. 

## Testing

- I am going to make sure the tests pass on this PR before requesting
review, If more testing is necessary let me know some good action steps
to take.
2024-08-06 01:31:13 +00:00
Gino Valente
0caeaa2ca9
bevy_reflect: Update serde tests for Set (#14616)
# Objective

Support for reflecting set-like types (e.g. `HashSet`) was added in
#13014. However, we didn't add any serialization tests to verify that
serialization works as expected.

## Solution

Update the serde tests.

## Testing

You can test locally by running:

```
cargo test --package bevy_reflect
```
2024-08-06 01:29:15 +00:00
Robert Walter
70a18d26e2
Glam 0.28 update - adopted (#14613)
Basically it's https://github.com/bevyengine/bevy/pull/13792 with the
bumped versions of `encase` and `hexasphere`.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-06 01:28:00 +00:00
Christian Hughes
039bf90817
Improve documentation on Update vs FixedUpdate schedule dichotomy (#14600)
# Objective

When looking at documentation for the `Update` schedule, its not
entirely obvious that developers should actually be using the
`FixedUpdate` schedule for most of their game logic. We should directly
cross-link between the two, and give examples of which systems to put in
which schedules.

## Solution

Do just that.
2024-08-06 01:26:37 +00:00
Periwink
3a664b052d
Separate component and resource access (#14561)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/13139
- Fixes https://github.com/bevyengine/bevy/issues/7255
- Separates component from resource access so that we can correctly
handles edge cases like the issue above
- Inspired from https://github.com/bevyengine/bevy/pull/14472

## Solution

- Update access to have `component` fields and `resource` fields

## Testing

- Added some unit tests
2024-08-06 01:19:39 +00:00
Lixou
0d0f77a7ab
Add invert_winding for triangle list meshes (#14555)
# Objective

Implements #14547 

## Solution

Add a function `invert_winding` for `Mesh` that inverts the winding for
`LineList`, `LineStrip`, `TriangleList` and `TriangleStrip`.

## Testing

Tests added

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alix Bott <bott.alix@gmail.com>
2024-08-06 01:16:43 +00:00
barsoosayque
5f2570eb4c
Export glTF skins as a Gltf struct (#14343)
# Objective

- Make skin data of glTF meshes available for users, so it would be
possible to create skinned meshes without spawning a scene.
- I believe it contributes to
https://github.com/bevyengine/bevy/issues/13681 ?

## Solution

- Add a new `GltfSkin`, representing skin data from a glTF file, new
member `skin` to `GltfNode` and both `skins` + `named_skins` to `Gltf`
(a la meshes/nodes).
- Rewrite glTF nodes resolution as an iterator which sorts nodes by
their dependencies (nodes without dependencies first). So when we create
`GltfNodes` with their associated `GltfSkin` while iterating, their
dependencies already have been loaded.
- Make a distinction between `GltfSkin` and
`SkinnedMeshInverseBindposes` in assets: prior to this PR,
`GltfAssetLabel::Skin(n)` was responsible not for a skin, but for one of
skin's components. Now `GltfAssetLabel::InverseBindMatrices(n)` will map
to `SkinnedMeshInverseBindposes`, and `GltfAssetLabel::Skin(n)` will map
to `GltfSkin`.

## Testing

- New test `skin_node` does just that; it tests whether or not
`GltfSkin` was loaded properly.

## Migration Guide

- Change `GltfAssetLabel::Skin(..)` to
`GltfAssetLabel::InverseBindMatrices(..)`.
2024-08-06 01:14:42 +00:00
Gino Valente
df61117850
bevy_reflect: Function registry (#14098)
# Objective

#13152 added support for reflecting functions. Now, we need a way to
register those functions such that they may be accessed anywhere within
the ECS.

## Solution

Added a `FunctionRegistry` type similar to `TypeRegistry`.

This allows a function to be registered and retrieved by name.

```rust
fn foo() -> i32 {
    123
}

let mut registry = FunctionRegistry::default();
registry.register("my_function", foo);

let function = registry.get_mut("my_function").unwrap();
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
```

Additionally, I added an `AppFunctionRegistry` resource which wraps a
`FunctionRegistryArc`. Functions can be registered into this resource
using `App::register_function` or by getting a mutable reference to the
resource itself.

### Limitations

#### `Send + Sync`

In order to get this registry to work across threads, it needs to be
`Send + Sync`. This means that `DynamicFunction` needs to be `Send +
Sync`, which means that its internal function also needs to be `Send +
Sync`.

In most cases, this won't be an issue because standard Rust functions
(the type most likely to be registered) are always `Send + Sync`.
Additionally, closures tend to be `Send + Sync` as well, granted they
don't capture any `!Send` or `!Sync` variables.

This PR adds this `Send + Sync` requirement, but as mentioned above, it
hopefully shouldn't be too big of an issue.

#### Closures

Unfortunately, closures can't be registered yet. This will likely be
explored and added in a followup PR.

### Future Work

Besides addressing the limitations listed above, another thing we could
look into is improving the lookup of registered functions. One aspect is
in the performance of hashing strings. The other is in the developer
experience of having to call `std::any::type_name_of_val` to get the
name of their function (assuming they didn't give it a custom name).

## Testing

You can run the tests locally with:

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

---

## Changelog

- Added `FunctionRegistry`
- Added `AppFunctionRegistry` (a `Resource` available from `bevy_ecs`)
- Added `FunctionRegistryArc`
- Added `FunctionRegistrationError`
- Added `reflect_functions` feature to `bevy_ecs` and `bevy_app`
- `FunctionInfo` is no longer `Default`
- `DynamicFunction` now requires its wrapped function be `Send + Sync`

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

`DynamicFunction` (both those created manually and those created with
`IntoFunction`), now require `Send + Sync`. All standard Rust functions
should meet that requirement. Closures, on the other hand, may not if
they capture any `!Send` or `!Sync` variables from its environment.
2024-08-06 01:09:48 +00:00
Periwink
ec4cf024f8
Add a ComponentIndex and update QueryState creation/update to use it (#13460)
# Objective

To implement relations we will need to add a `ComponentIndex`, which is
a map from a Component to the list of archetypes that contain this
component.
One of the reasons is that with fragmenting relations the number of
archetypes will explode, so it will become inefficient to create and
update the query caches by iterating through the list of all archetypes.

In this PR, we introduce the `ComponentIndex`, and we update the
`QueryState` to make use of it:
- if a query has at least 1 required component (i.e. something other
than `()`, `Entity` or `Option<>`, etc.): for each of the required
components we find the list of archetypes that contain it (using the
ComponentIndex). Then, we select the smallest list among these. This
gives a small subset of archetypes to iterate through compared with
iterating through all new archetypes
- if it doesn't, then we keep using the current approach of iterating
through all new archetypes


# Implementation
- This breaks query iteration order, in the sense that we are not
guaranteed anymore to return results in the order in which the
archetypes were created. I think this should be fine because this wasn't
an explicit bevy guarantee so users should not be relying on this. I
updated a bunch of unit tests that were failing because of this.

- I had an issue with the borrow checker because iterating the list of
potential archetypes requires access to `&state.component_access`, which
was conflicting with the calls to
```
  if state.new_archetype_internal(archetype) {
      state.update_archetype_component_access(archetype, access);
  }
```
which need a mutable access to the state.

The solution I chose was to introduce a `QueryStateView` which is a
temporary view into the `QueryState` which enables a "split-borrows"
kind of approach. It is described in detail in this blog post:
https://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/

# Test

The unit tests pass.

Benchmark results:
```
❯ critcmp main pr
group                                  main                                   pr
-----                                  ----                                   --
iter_fragmented/base                   1.00   342.2±25.45ns        ? ?/sec    1.02   347.5±16.24ns        ? ?/sec
iter_fragmented/foreach                1.04   165.4±11.29ns        ? ?/sec    1.00    159.5±4.27ns        ? ?/sec
iter_fragmented/foreach_wide           1.03      3.3±0.04µs        ? ?/sec    1.00      3.2±0.06µs        ? ?/sec
iter_fragmented/wide                   1.03      3.1±0.06µs        ? ?/sec    1.00      3.0±0.08µs        ? ?/sec
iter_fragmented_sparse/base            1.00      6.5±0.14ns        ? ?/sec    1.02      6.6±0.08ns        ? ?/sec
iter_fragmented_sparse/foreach         1.00      6.3±0.08ns        ? ?/sec    1.04      6.6±0.08ns        ? ?/sec
iter_fragmented_sparse/foreach_wide    1.00     43.8±0.15ns        ? ?/sec    1.02     44.6±0.53ns        ? ?/sec
iter_fragmented_sparse/wide            1.00     29.8±0.44ns        ? ?/sec    1.00     29.8±0.26ns        ? ?/sec
iter_simple/base                       1.00      8.2±0.10µs        ? ?/sec    1.00      8.2±0.09µs        ? ?/sec
iter_simple/foreach                    1.00      3.8±0.02µs        ? ?/sec    1.02      3.9±0.03µs        ? ?/sec
iter_simple/foreach_sparse_set         1.00     19.0±0.26µs        ? ?/sec    1.01     19.3±0.16µs        ? ?/sec
iter_simple/foreach_wide               1.00     17.8±0.24µs        ? ?/sec    1.00     17.9±0.31µs        ? ?/sec
iter_simple/foreach_wide_sparse_set    1.06     95.6±6.23µs        ? ?/sec    1.00     90.6±0.59µs        ? ?/sec
iter_simple/sparse_set                 1.00     19.3±1.63µs        ? ?/sec    1.01     19.5±0.29µs        ? ?/sec
iter_simple/system                     1.00      8.1±0.10µs        ? ?/sec    1.00      8.1±0.09µs        ? ?/sec
iter_simple/wide                       1.05     37.7±2.53µs        ? ?/sec    1.00     35.8±0.57µs        ? ?/sec
iter_simple/wide_sparse_set            1.00     95.7±1.62µs        ? ?/sec    1.00     95.9±0.76µs        ? ?/sec
par_iter_simple/with_0_fragment        1.04     35.0±2.51µs        ? ?/sec    1.00     33.7±0.49µs        ? ?/sec
par_iter_simple/with_1000_fragment     1.00     50.4±2.52µs        ? ?/sec    1.01     51.0±3.84µs        ? ?/sec
par_iter_simple/with_100_fragment      1.02     40.3±2.23µs        ? ?/sec    1.00     39.5±1.32µs        ? ?/sec
par_iter_simple/with_10_fragment       1.14     38.8±7.79µs        ? ?/sec    1.00     34.0±0.78µs        ? ?/sec
```
2024-08-06 00:57:15 +00:00
Giacomo Stevanato
68ec6f4f50
Make QueryState::transmute&co validate the world of the &Components used (#14631)
# Objective

- Fix #14629

## Solution

- Make `QueryState::transmute`, `QueryState::transmute_filtered`,
`QueryState::join` and `QueryState::join_filtered` take a `impl
Into<UnsafeWorldCell>` instead of a `&Components` and validate their
`WorldId`

## Migration Guide

- `QueryState::transmute`, `QueryState::transmute_filtered`,
`QueryState::join` and `QueryState::join_filtered` now take a `impl
Into<UnsafeWorldCell>` instead of a `&Components`

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-08-05 22:39:31 +00:00
Rob Parrett
e164e5a873
Add link to with_children in with_child doc (#14604)
# Objective

Discourage users from using `with_child` for spawning multiple children.

## Solution

Add link to `with_children` in docs for `with_child`.
2024-08-04 13:36:52 +00:00
Ben Frankel
9b254aab1e
Explicitly order CameraUpdateSystem before UiSystem::Prepare (#14609)
# Objective

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

May also fix https://github.com/bevyengine/bevy/issues/14255, needs
verification.

## Solution

Explicitly order `CameraUpdateSystem` before `UiSystem::Prepare`, so
that when the window resizes, `camera_system` will update the `Camera`'s
viewport size before `ui_layout_system` also reacts to the window resize
and tries to read the new `Camera` viewport size to set UI node sizes
accordingly.

## Testing

I tested that explicitly ordering `CameraUpdateSystem` _after_ triggers
the buggy behavior, and explicitly ordering it _before_ does not trigger
the buggy behavior or crash the app (which also demonstrates that the
system sets are ambiguous).

---

## Migration Guide

`CameraUpdateSystem` is now explicitly ordered before
`UiSystem::Prepare` instead of being ambiguous with it.
2024-08-04 13:34:51 +00:00
radiish
4b20d822e9
update hashbrown to 0.14.2 (#14603)
# Objective

- We previously had a dependency in `bevy_utils`, `hashbrown = 0.14`,
and used the `hashbrown::hash_table` api, which was introduced in
`0.14.2`.

## Solution

- Bump `hashbrown` to `0.14.2`

## Testing

- Now compiles with the minimum declared `hashbrown` version.

---
2024-08-04 13:23:28 +00:00
re0312
8235daaea0
Opportunistically use dense iteration for archetypal iteration (#14049)
# Objective
- currently, bevy employs sparse iteration if any of the target
components in the query are stored in a sparse set. it may lead to
increased cache misses in some cases, potentially impacting performance.
- partial fixes #12381 

## Solution

- use dense iteration when an archetype and its table have the same
entity count.
- to avoid introducing complicate unsafe noise, this pr only implement
for `for_each ` style iteration.
- added a benchmark to test performance for hybrid iteration.


## Performance


![image](https://github.com/bevyengine/bevy/assets/45868716/5cce13cf-6ff2-4861-9576-e75edc63bd46)

nearly 2x win in specific scenarios, and no performance degradation in
other test cases.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
2024-08-02 21:18:15 +00:00
Lixou
7c80ae7313
Add depth_ndc_to_view_z for cpu-side (#14590)
# Objective

I want to get the visual depth (after view proj matrix stuff) of the
object beneath my cursor.
Even when having a write-back of the depth texture, you would still need
to convert the NDC depth to a logical value.

## Solution

This is done on shader-side by [this
function](e6261b0f5f/crates/bevy_pbr/src/render/view_transformations.wgsl (L151)),
which I ported over to the cpu-side.

I also added `world_to_viewport_with_depth` to get a `Vec3` instead of
`Vec2`.

---

If anyone knows a smarter solution to get the visual depth instead of
going `screen -> viewport ray -> screen`, please let me know :>
2024-08-02 15:37:29 +00:00
Rob Parrett
5b29402cc8
Add with_child to simplify spawning when there will only be one child (#14594)
# Objective

This idea came up in the context of a hypothetical "text sections as
entities" where text sections are children of a text bundle.

```rust
commands
    .spawn(TextBundle::default())
    .with_children(|parent} {
        parent.spawn(TextSection::from("Hello"));
    });
```

This is a bit cumbersome (but powerful and probably the way things are
headed). [`bsn!`](https://github.com/bevyengine/bevy/discussions/14437)
will eventually make this nicer, but in the mean time, this might
improve ergonomics for the common case where there is only one
`TextSection`.

## Solution

Add a `with_child` method to the `BuildChildren` trait that spawns a
single bundle and adds it as a child to the entity.

```rust
commands
    .spawn(TextBundle::default())
    .with_child(TextSection::from("Hello"));
```

## Testing

I added some tests, and modified the `button` example to use the new
method.

If any potential co-authors want to improve the tests, that would be
great.

## Alternatives

- Some sort of macro. See
https://github.com/tigregalis/bevy_spans_ent/blob/main/examples/macro.rs#L20.
I don't love this, personally, and it would probably be obsoleted by
`bsn!`.
- Wait for `bsn!`
- Add `with_children_batch` that takes an `Into<Iterator>` of bundles.
  ```rust
  with_children_batch(vec![TextSection::from("Hello")])
  ```
This is maybe not as useful as it sounds -- it only works with
homogeneous bundles, so no marker components or styles.
- If this doesn't seem valuable, doing nothing is cool with me.
2024-08-02 15:37:15 +00:00
Lixou
4c2cef2223
Reflection for DepthOfFieldSettings (#14588)
# Objective

I can't mutate the dof settings via tools like `bevy_inspector_egui`

## Solution

Add `Reflect` for `DepthOfFieldSettings` and `DepthOfFieldMode`
2024-08-02 15:36:39 +00:00
Joona Aalto
e6261b0f5f
Add Dir2::from_xy_unchecked and Dir3::from_xyz_unchecked (#14587)
# Objective

Bevy's direction types have `new` and `new_unchecked` constructors, but
no unchecked variant for the `Dir2::from_xy` and `Dir3::from_xyz`
methods.

For me, this has several times lead to constructing directions like
this, in cases where the components of the direction are already known
to be normalized:

```rust
let normal = Dir2::new_unchecked(Vec2::new(-ray.direction.x.signum(), 0.0));
```

```rust
segment.direction =
    Dir2::new_unchecked(Vec2::new(-segment.direction.x, segment.direction.y));
```

For consistency and ergonomics, it would be nice to have unchecked
variants of `Dir2::from_xy` and `Dir3::from_xyz`:

```rust
let normal = Dir2::from_xy_unchecked(-ray.direction.x.signum(), 0.0);
```

```rust
segment.direction = Dir2::from_xy_unchecked(-segment.direction.x, segment.direction.y);
```

## Solution

Add `Dir2::from_xy_unchecked` and `Dir3::from_xyz_unchecked`.
2024-08-02 13:10:13 +00:00
James O'Brien
b98d15f278
Skip batching for phase items from other pipelines (#14296)
# Objective

- Fix #14295

## Solution

- Early out when `GFBD::get_index_and_compare_data` returns None.

## Testing

- Tested on a selection of examples including `many_foxes` and
`3d_shapes`.
- Resolved the original issue in `bevy_vector_shapes`.
2024-08-02 00:15:42 +00:00
JJJimbo1
56c9d4489b
fix asymmetrical 9-slicing (#14148)
# Objective

Fixes #14147.

## Solution

Modify the slicing checks and algorithm to fully allow asymmetrical
textures to work.
Some opinionated code cleanup.

## Testing

Tested using the ui_texture_slice example and a custom asymmetrical
texture.

Before:

![asymmetrical_texture_slice_before](https://github.com/bevyengine/bevy/assets/88861660/00dafce1-904a-41ac-b5d9-faaf087b0681)

After:

![asymmetrical_texture_slice_after](https://github.com/bevyengine/bevy/assets/88861660/f3d742f3-6157-4d35-b383-aee4b8f6e7d0)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-01 20:03:23 +00:00
Brian Reavis
4c4a6c4506
Don’t prepare lights (and shadow map textures) for 2D cameras (#14574)
# Objective

When running the Metal debugger I noticed that 2D cameras have shadow
map textures from `bevy_pbr` built for them. For a 2560x1440 2D camera,
this PR saves about 40mb of texture memory.


![image](https://github.com/user-attachments/assets/925e9392-2721-41bb-83e9-25c84fd563cd)


![image](https://github.com/user-attachments/assets/0cc3c0a9-cbf7-431c-b444-952c28d4e9d0)


## Solution

- Added `With<Camera3d>` filter to the appropriate view queries.

## Testing

- This is a trivial fix (the examples still work)
2024-08-01 19:29:18 +00:00
Brezak
0c7df881e7
Properly handle repeated window close requests (#14573)
# Objective

Spamming the window close button on window may trigger a panic.

```
thread 'main' panicked at <Bevy repo>\crates\bevy_ecs\src\system\commands\mod.rs:1320:13:
error[B0003]: Could not insert a bundle (of type `bevy_window:🪟:ClosingWindow`) for entity 0v1#4294967296 because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_window::system::close_when_requested`!
2024-08-01T15:00:29.742612Z  WARN bevy_ecs::world::command_queue: CommandQueue has un-applied commands being dropped. Did you forget to call SystemState::apply?
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
error: process didn't exit successfully: `target\debug\bevy.exe` (exit code: 101)
```

## Solution

Don't panic when trying to insert the `ClosingWindow` component into a
entity.

## Testing

Found and tested on windows. I haven't checked if this bug happens on
linux or macos.
For testing I ran this code:

```rust
use std::{thread, time::Duration};

use bevy::prelude::*;

fn lag() {
    thread::sleep(Duration::from_millis(300));
}

fn main() -> AppExit {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Update, lag)
        .run()
}
```

Then spammed the window close button. The panic no longer occurs.
2024-08-01 16:15:28 +00:00
SpecificProtagonist
0685d2da4d
B0003: Print caller (#14556)
# Objective

B0003 indicates that you tried to act upon a nonexistant entity, but
does not mention where the error occured:
```
2024-07-31T15:46:25.954840Z  WARN bevy_ecs::world: error[B0003]: Could not despawn entity Entity { index: 4294967295, generation: 1 } because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
```

## Solution

Include caller location:

```
2024-07-31T15:46:25.954840Z  WARN bevy_ecs::world: error[B0003]: src/main.rs:18:11: Could not despawn entity Entity { index: 4294967295, generation: 1 } because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
```

Open question: What should the exact message format be?

## Testing

None, this doesn't change any logic.
2024-08-01 00:14:48 +00:00
Guillaume Gomez
0e86675177
Add freebsd support for sysinfo (#14553)
I'm not sure if bevy works on FreeBSD or not. But in case it does,
better allow `sysinfo` to be used as well if users want.
2024-07-31 21:41:40 +00:00
Jan Hohenheim
6f7c554daa
Fix common capitalization errors in documentation (#14562)
WASM -> Wasm
MacOS -> macOS

Nothing important, just something that annoyed me for a while :)
2024-07-31 21:16:05 +00:00
Lixou
20264d0810
Make AnimationPlayer::start and ::play work accordingly to documentation (#14546)
# Objective

While scrolling through the animation crate, I was confused by the docs
and code for the two methods. One does nothing for resetting an
animation, the other just resets the weights for whatever reason.

## Solution

Made the functions work accordingly to their documentation.
`start` now replays the animation.
And `play` doesn't reset the weight anymore. I have no clue why it
should. `play` is there to don't do anything to an already existing
animation.

## Testing

I tested the current 0.14 code with bevy playground in the Animated Fox
exampled and changed it such that on pressing space, either `play` or
`start` would be called. Neither changed anything.
I then inlined the function for start there and it restarted the
animation, so it should work.

---

## Migration Guide

`AnimationPlayer::start` now correspondingly to its docs restarts a
running animation.
`AnimationPlayer::play` doesn't reset the weight anymore.
2024-07-31 14:07:53 +00:00
Guillaume Gomez
68dc7a8b8b
Update sysinfo version to 0.31.0 (#14551)
This release will likely remove a few dependencies in bevy since you
only need the `system` feature.
2024-07-31 14:06:52 +00:00
Rich Churcher
e579622a65
time_system is ambiguous_with event_update_system (#14544)
# Objective

Resolve possible ambiguity detection panic between `time_system` and
`event_update_system`.

Fixes #14524

## Solution

Sets `.ambiguous_with(event_update_system)` on `time_system`. This is
slightly new territory for me, so please treat with scepticism.

## Testing

As described in the issue, added
```
        .configure_schedules(ScheduleBuildSettings {
            ambiguity_detection: LogLevel::Error,
            ..default()
        })
```
to the `time` example and ran it.
2024-07-31 12:13:17 +00:00
Zeenobit
023e0e5bde
Fix Entity Debug Format (#14539)
# Objective

Fixes #12139

## Solution

See this comment on original issue for my proposal:
https://github.com/bevyengine/bevy/issues/12139#issuecomment-2241915791

This PR is an implementation of this proposal.

I modified the implementation of `fmt::Debug` to instead display
`0v0#12345` to ensure entity index, generation, and raw bits are all
present in the output for debug purposes while still keeping log message
concise.

`fmt::Display` remains as is (`0v0`) to offer an even shorter output.

To me, this is the most non-intrusive fix for this issue.

## Testing

Add `fn entity_debug` test

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-31 01:36:41 +00:00
BD103
399219a2c7
Fix rust beta lints (#14537)
# Objective

- Fixes #14517.

## Solution

- Replace two instances of `map()` with `inspect()`.
- `#[allow(dead_code)]` on `Bundle` derive macro tests.

## Testing

You need to install the beta toolchain, since these lints are not stable
yet.

```bash
cargo +beta clippy --workspace
cargo +beta test --workspace
```
2024-07-31 01:27:26 +00:00
Robin KAY
3d1c9ca87f
Change SceneInstanceReady to trigger an observer. (#13859)
# Objective

The `SceneInstanceReady` event would be more ergonomic (and potentially
efficient) if it could be delivered to listeners attached to the scene
entities becoming ready rather than into a World-global queue.

This is an evolution of @Shatur's work in #9313.

## Solution

The scene spawner is changed to trigger observers on the scene entity
when it is ready rather than enqueue an event with `EventWriter`.

This addresses the two outstanding feature requests mentioned on #2218,
that i) the events should be "scoped" in some way and ii) that the
`InstanceId` should be included in the event.

## Testing

Modified the `scene_spawner::tests::event` test to use the new
mechanism.

---

## Changelog

- Changed `SceneInstanceReady` to trigger an entity observer rather than
be written to an event queue.
- Changed `SceneInstanceReady` to carry the `InstanceId` of the scene.

## Migration Guide

If you have a system which read `SceneInstanceReady` events:

> ```fn ready_system(ready_events: EventReader<'_, '_,
SceneInstanceReady>) {```

It must be rewritten as an observer:

> ```commands.observe(|trigger: Trigger<SceneInstanceReady>| {```

Or, if you were expecting the event in relation to a specific entity or
entities, as an entity observer:

> ```commands.entity(entity).observe(|trigger:
Trigger<SceneInstanceReady>| {```
2024-07-30 21:23:48 +00:00
s-puig
ba09f35474
Fix UI texture atlas with offset (#13620)
# Objective

- Fixes #11219 

## Solution

- Scaling calculations use texture dimensions instead of layout
dimensions.

## Testing

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

All UI examples look fine.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

Example in #11219

## Migration Guide

```diff
let ui_node = ExtractedUiNode {
                    stack_index,
                    transform,
                    color,
                    rect,
                    image,
-                   atlas_size: Some(atlas_size * scale_factor),      
+                   atlas_scaling: Some(Vec2::splat(scale_factor)),
                    clip,
                    flip_x,
                    flip_y,
                    camera_entity,
                    border,
                    border_radius,
                    node_type,
                },
```

```diff
let computed_slices = ComputedTextureSlices {
    slices,
-    image_size,
}
```
2024-07-30 15:31:58 +00:00
BD103
d722fef23d
Remove deprecated bevy_dynamic_plugin (#14534)
# Objective

- Dynamic plugins were deprecated in #13080 due to being unsound. The
plan was to deprecate them in 0.14 and remove them in 0.15.

## Solution

- Remove all dynamic plugin functionality.
- Update documentation to reflect this change.

---

## Migration Guide

Dynamic plugins were deprecated in 0.14 for being unsound, and they have
now been fully removed. Please consider using the alternatives listed in
the `bevy_dynamic_plugin` crate documentation, or worst-case scenario
you may copy the code from 0.14.
2024-07-30 15:31:08 +00:00
Aevyrie
9575b20d31
Track source location in change detection (#14034)
# Objective

- Make it possible to know *what* changed your component or resource.
- Common need when debugging, when you want to know the last code
location that mutated a value in the ECS.
- This feature would be very useful for the editor alongside system
stepping.

## Solution

- Adds the caller location to column data.
- Mutations now `track_caller` all the way up to the public API.
- Commands that invoke these functions immediately call
`Location::caller`, and pass this into the functions, instead of the
functions themselves attempting to get the caller. This would not work
for commands which are deferred, as the commands are executed by the
scheduler, not the user's code.

## Testing

- The `component_change_detection` example now shows where the component
was mutated:

```
2024-07-28T06:57:48.946022Z  INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(0.0)
2024-07-28T06:57:49.004371Z  INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(1.0)
2024-07-28T06:57:49.012738Z  WARN component_change_detection: Change detected!
        -> value: Ref(MyComponent(1.0))
        -> added: false
        -> changed: true
        -> changed by: examples/ecs/component_change_detection.rs:36:23
```

- It's also possible to inspect change location from a debugger:
<img width="608" alt="image"
src="https://github.com/user-attachments/assets/c90ecc7a-0462-457a-80ae-42e7f5d346b4">


---

## Changelog

- Added source locations to ECS change detection behind the
`track_change_detection` flag.

## Migration Guide

- Added `changed_by` field to many internal ECS functions used with
change detection when the `track_change_detection` feature flag is
enabled. Use Location::caller() to provide the source of the function
call.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-30 12:02:38 +00:00
Rostyslav Toch
455c1bfbe8
Optimize cloning for Access-related structs (#14502)
# Objective

Optimize the cloning process for Access-related structs in the ECS
system, specifically targeting the `clone_from` method.

Previously, profiling showed that 1% of CPU time was spent in
`FixedBitSet`'s `drop_in_place`, due to the default `clone_from`
implementation:

```rust
fn clone_from(&mut self, source: &Self) {
    *self = source.clone()
}
```

This implementation causes unnecessary allocations and deallocations.
However, [FixedBitSet provides a more optimized clone_from
method](https://github.com/petgraph/fixedbitset/blob/master/src/lib.rs#L1445-L1465)
that avoids these allocations and utilizes SIMD instructions for better
performance.

This PR aims to leverage the optimized clone_from method of FixedBitSet
and implement custom clone_from methods for Access-related structs to
take full advantage of this optimization. By doing so, we expect to
significantly reduce CPU time spent on cloning operations and improve
overall system performance.



![image](https://github.com/user-attachments/assets/7526a5c5-c75b-4a9a-b8d2-891f64fd553b)


## Solution

- Implemented custom `clone` and `clone_from` methods for `Access`,
`FilteredAccess`, `AccessFilters`, and `FilteredAccessSet` structs.
- Removed `#[derive(Clone)]` and manually implemented `Clone` trait to
use optimized `clone_from` method from `FixedBitSet`.
- Added unit tests for cloning and `clone_from` methods to ensure
correctness.

## Testing

- Conducted performance testing comparing the original and optimized
versions.
- Measured CPU time consumption for the `clone_from` method:
  - Original version: 1.34% of CPU time
  - Optimized version: 0.338% of CPU time
- Compared FPS before and after the changes (results may vary depending
on the run):

Before optimization:
```
2024-07-28T12:49:11.864019Z  INFO bevy diagnostic: fps        :  213.489463   (avg 214.502488)
2024-07-28T12:49:11.864037Z  INFO bevy diagnostic: frame_time :    4.704746ms (avg 4.682251ms)
2024-07-28T12:49:11.864042Z  INFO bevy diagnostic: frame_count: 7947.000000   (avg 7887.500000)
```


![image](https://github.com/user-attachments/assets/7865a365-0569-4b46-814a-964779d90973)

After optimization:
```
2024-07-28T12:29:42.705738Z  INFO bevy diagnostic: fps        :  220.273721   (avg 220.912227)
2024-07-28T12:29:42.705762Z  INFO bevy diagnostic: frame_time :    4.559127ms (avg 4.544905ms)
2024-07-28T12:29:42.705769Z  INFO bevy diagnostic: frame_count: 7596.000000   (avg 7536.500000)
```


![image](https://github.com/user-attachments/assets/8dd96908-86d0-4850-8e29-f80176a005d6)

---

Reviewers can test these changes by running `cargo run --release
--example ssr`
2024-07-29 23:48:21 +00:00
Tamás Kiss
396153ae59
fix issue with phantom ui node children (#14490)
# Objective

The `ui_layout_system` relies on change detection to sync parent-child
relation to taffy. The children need to by synced before node removal to
avoid trying to set deleted nodes as children (due to how the different
queries collect entities). This however may leave nodes that were
removed set as children to other nodes in special cases.

Fixes #11385

## Solution

The solution is simply to re-sync the changed children after the nodes
are removed.

## Testing

Tested with `sickle_ui` where docking zone highlights would end up
glitched when docking was done in a certain manner:
- run the `docking_zone_splits` example
- pop out a tab from the top
- dock the floating panel in the center right
- grab another tab and try to hover the original static docking zone:
the highlight is semi-stuck
- (NOTE: sometimes it worked even without the fix due to scheduling
order not producing the bugged query results)

After the fix, the issue is no longer present.

NOTE: The performance impact should be minimal, as the child sync relies
on change detection. The change detection was also the reason the parent
nodes remained "stuck" with the phantom children if no other update were
done to them.
2024-07-29 23:42:56 +00:00
Rich Churcher
23cb0f9c54
Add note on StatesPlugin requirement for state code (#14489)
# Objective

Clarify that `StatesPlugin` is a prerequisite for state code.

Closes #14329 .

Edit: am I missing a way to link `DefaultPlugins` correctly other than
using the URL? I guess I expected to be able to refer to it with
`bevy::prelude::DefaultPlugins` or some such 🤔
2024-07-29 23:41:14 +00:00
Matty
601cf6b9e5
Refactor Bounded2d/Bounded3d to use isometries (#14485)
# Objective

Previously, this area of bevy_math used raw translation and rotations to
encode isometries, which did not exist earlier. The goal of this PR is
to make the codebase of bevy_math more harmonious by using actual
isometries (`Isometry2d`/`Isometry3d`) in these places instead — this
will hopefully make the interfaces more digestible for end-users, in
addition to facilitating conversions.

For instance, together with the addition of #14478, this means that a
bounding box for a collider with an isometric `Transform` can be
computed as
```rust
collider.aabb_3d(collider_transform.to_isometry())
```
instead of using manual destructuring. 

## Solution

- The traits `Bounded2d` and `Bounded3d` now use `Isometry2d` and
`Isometry3d` (respectively) instead of `translation` and `rotation`
parameters; e.g.:
  ```rust
  /// A trait with methods that return 3D bounding volumes for a shape.
  pub trait Bounded3d {
/// Get an axis-aligned bounding box for the shape translated and
rotated by the given isometry.
      fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d;
/// Get a bounding sphere for the shape translated and rotated by the
given isometry.
      fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere;
  }
  ```
- Similarly, the `from_point_cloud` constructors for axis-aligned
bounding boxes and bounding circles/spheres now take isometries instead
of separate `translation` and `rotation`; e.g.:
  ```rust
/// Computes the smallest [`Aabb3d`] containing the given set of points,
/// transformed by the rotation and translation of the given isometry.
    ///
    /// # Panics
    ///
    /// Panics if the given set of points is empty.
    #[inline(always)]
    pub fn from_point_cloud(
        isometry: Isometry3d,
        points: impl Iterator<Item = impl Into<Vec3A>>,
    ) -> Aabb3d { //... }
  ```

This has a couple additional results:
1. The end-user no longer interacts directly with `Into<Vec3A>` or
`Into<Rot2>` parameters; these conversions all happen earlier now,
inside the isometry types.
2. Similarly, almost all intermediate `Vec3 -> Vec3A` conversions have
been eliminated from the `Bounded3d` implementations for primitives.
This probably has some performance benefit, but I have not measured it
as of now.

## Testing

Existing unit tests help ensure that nothing has been broken in the
refactor.

---

## Migration Guide

The `Bounded2d` and `Bounded3d` traits now take `Isometry2d` and
`Isometry3d` parameters (respectively) instead of separate translation
and rotation arguments. Existing calls to `aabb_2d`, `bounding_circle`,
`aabb_3d`, and `bounding_sphere` will have to be changed to use
isometries instead. A straightforward conversion is to refactor just by
calling `Isometry2d/3d::new`, as follows:
```rust
// Old:
let aabb = my_shape.aabb_2d(my_translation, my_rotation);

// New:
let aabb = my_shape.aabb_2d(Isometry2d::new(my_translation, my_rotation));
```

However, if the old translation and rotation are 3d
translation/rotations originating from a `Transform` or
`GlobalTransform`, then `to_isometry` may be used instead. For example:
```rust
// Old:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.translation, shape_transform.rotation);

// New:
let bounding_sphere = my_shape.bounding_sphere(shape_transform.to_isometry());
```

This discussion also applies to the `from_point_cloud` construction
method of `Aabb2d`/`BoundingCircle`/`Aabb3d`/`BoundingSphere`, which has
similarly been altered to use isometries.
2024-07-29 23:37:02 +00:00
TheDudeFromCI
7573b3c765
Added serialize flag to bevy_math dep of bevy_ui (#14450)
# Objective

When depending on the `bevy_ui` crate specifically and using the
`serialize` feature flag, the compilation fails due to `bevy_math` not
having the serialize flag enabled.

## Solution

Added the `serialize` flag to the `bevy_math` dependency when using that
flag on `bevy_ui`.

## Testing

Tested by adding `bevy_math = { version = "0.14", features =
["serialize"] }` on a small Bevy library to ensure compilation was
successful.
2024-07-29 23:34:07 +00:00
recatek
87b63af864
bevy_reflect: Adding support for Atomic values (#14419)
Fixes #14418

Note that this does not add AtomicPtr, which would need its own special
casing support, just the regular value types.
Also, I was forced to be opinionated about which Ordering to use, so I
chose SeqCst as the strictest by default.
2024-07-29 23:33:18 +00:00
Matty
74cecb27bb
Disallow empty cubic and rational curves (#14382)
# Objective

Previously, our cubic spline constructors would produce
`CubicCurve`/`RationalCurve` output with no data when they themselves
didn't hold enough control points to produce a well-formed curve.
Attempting to sample the resulting empty "curves" (e.g. by calling
`CubicCurve::position`) would crash the program (😓).

The objectives of this PR are: 
1. Ensure that the curve output of `bevy_math`'s spline constructions
are never invalid as data.
2. Provide a type-level guarantee that `CubicCurve` and `RationalCurve`
actually function as curves.

## Solution

This has a few pieces. Firstly, the curve generator traits
`CubicGenerator`, `CyclicCubicGenerator`, and `RationalGenerator` are
now fallible — they have associated error types, and the
curve-generation functions are allowed to fail:
```rust
/// Implement this on cubic splines that can generate a cubic curve from their spline parameters.
pub trait CubicGenerator<P: VectorSpace> {
    /// An error type indicating why construction might fail.
    type Error;

    /// Build a [`CubicCurve`] by computing the interpolation coefficients for each curve segment.
    fn to_curve(&self) -> Result<CubicCurve<P>, Self::Error>;
}
```

All existing spline constructions use this together with errors that
indicate when they didn't have the right control data and provide curves
which have at least one segment whenever they return an `Ok` variant.

Next, `CubicCurve` and `RationalCurve` have been blessed with a
guarantee that their internal array of segments (`segments`) is never
empty. In particular, this field is no longer public, so that invalid
curves cannot be built using struct instantiation syntax. To compensate
for this shortfall for users (in particular library authors who might
want to implement their own generators), there is a new method
`from_segments` on these for constructing a curve from a list of
segments, failing if the list is empty:
```rust
/// Create a new curve from a collection of segments. If the collection of segments is empty,
/// a curve cannot be built and `None` will be returned instead.
pub fn from_segments(segments: impl Into<Vec<CubicSegment<P>>>) -> Option<Self> { //... }
```

All existing methods on `CyclicCurve` and `CubicCurve` maintain the
invariant, so the direct construction of invalid values by users is
impossible.

## Testing

Run unit tests from `bevy_math::cubic_splines`. Additionally, run the
`cubic_splines` example and try to get it to crash using small numbers
of control points: it uses the fallible constructors directly, so if
invalid data is ever constructed, it is basically guaranteed to crash.

---

## Migration Guide

The `to_curve` method on Bevy's cubic splines is now fallible (returning
a `Result`), meaning that any existing calls will need to be updated by
handling the possibility of an error variant.

Similarly, any custom implementation of `CubicGenerator` or
`RationalGenerator` will need to be amended to include an `Error` type
and be made fallible itself.

Finally, the fields of `CubicCurve` and `RationalCurve` are now private,
so any direct constructions of these structs from segments will need to
be replaced with the new `CubicCurve::from_segments` and
`RationalCurve::from_segments` methods.

---

## Design

The main thing to justify here is the choice for the curve internals to
remain the same. After all, if they were able to cause crashes in the
first place, it's worth wondering why safeguards weren't put in place on
the types themselves to prevent that.

My view on this is that the problem was really that the internals of
these methods implicitly relied on the assumption that the value they
were operating on was *actually a curve*, when this wasn't actually
guaranteed. Now, it's possible to make a bunch of small changes inside
the curve struct methods to account for that, but I think that's worse
than just guaranteeing that the data is valid upstream — sampling is
about as hot a code path as we're going to get in this area, and hitting
an additional branch every time it happens just to check that the struct
contains valid data is probably a waste of resources.

Another way of phrasing this is that even if we're only interested in
solving the crashes, the curve's validity needs to be checked at some
point, and it's almost certainly better to do this once at the point of
construction than every time the curve is sampled.

In cases where the control data is supplied dynamically, users would
already have to deal with empty curve outputs basically not working.
Anecdotally, I ran into this while writing the `cubic_splines` example,
and I think the diff illustrates the improvement pretty nicely — the
code no longer has to anticipate whether the output will be good or not;
it just has to handle the `Result`.

The cost of all this, of course, is that we have to guarantee that the
new invariant is actually maintained whenever we extend the API.
However, for the most part, I don't expect users to want to do much
surgery on the internals of their curves anyway.
2024-07-29 23:25:14 +00:00
Giacomo Stevanato
7de271f992
Add FilteredAccess::empty and simplify the implementatin of update_component_access for AnyOf/Or (#14352)
# Objective

- The implementation of `update_component_access` for `AnyOf`/`Or` is
kinda weird due to special casing the first filter, let's simplify it;
- Fundamentally we want to fold/reduce the various filters using an OR
operation, however in order to do a proper fold we need a neutral
element for the initial accumulator, which for OR is FALSE. However we
didn't have a way to create a `FilteredAccess` value corresponding to
FALSE and thus the only option was reducing, which special cases the
first element as being the initial accumulator.

This is an alternative to https://github.com/bevyengine/bevy/pull/14026

## Solution

- Introduce `FilteredAccess::empty` as a way to create a
`FilteredAccess` corresponding to the logical proposition FALSE;
- Use it as the initial accumulator for the above operations, allowing
to handle all the elements to fold in the same way.

---

## Migration Guide

- The behaviour of `AnyOf<()>` and `Or<()>` has been changed to match no
archetypes rather than all archetypes to naturally match the
corresponding logical operation. Consider replacing them with `()`
instead.
2024-07-29 23:20:06 +00:00
Giacomo Stevanato
71c5f1e3e4
Generate links to definition in source code pages on docs.rs and dev-docs.bevyengine.org (#12965)
# Objective

- Fix issue #2611

## Solution

- Add `--generate-link-to-definition` to all the `rustdoc-args` arrays
in the `Cargo.toml`s (for docs.rs)
- Add `--generate-link-to-definition` to the `RUSTDOCFLAGS` environment
variable in the docs workflow (for dev-docs.bevyengine.org)
- Document all the workspace crates in the docs workflow (needed because
otherwise only the source code of the `bevy` package will be included,
making the argument useless)
- I think this also fixes #3662, since it fixes the bug on
dev-docs.bevyengine.org, while on docs.rs it has been fixed for a while
on their side.

---

## Changelog

- The source code viewer on docs.rs now includes links to the
definitions.
2024-07-29 23:10:16 +00:00
JMS55
29e9f0a7f9
Correct minimum range-alloc version (#14420)
Fixes https://github.com/bevyengine/bevy/issues/14417

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-29 22:11:29 +00:00
Giacomo Stevanato
59a33e6e14
Fix bevy_render's image dependency version (#14505)
# Objective

- `bevy_render` depends on `image 0.25` but uses `image::ImageReader`
which was added only in `image 0.25.2`
- users that have `image 0.25` in their `Cargo.lock` and update to the
latest `bevy_render` may thus get a compilation due to this (at least I
did)

## Solution

- Properly set the correct minimum version of `image` that `bevy_render`
depends on.
2024-07-28 15:48:51 +00:00
Giacomo Stevanato
bc80b95257
Don't debug SystemId's entity field twice (#14499)
# Objective

- `SystemId`'s `Debug` implementation includes its `entity` field twice.
- This was likely an oversight in #11019, since before that PR the
second field was the `PhantomData` one.

## Solution

- Only include it once

Alternatively, this could be changed to match the struct representation
of `SystemId`, thus instructing the formatter to print a named struct
and including the `PhantomData` field.
2024-07-27 16:15:39 +00:00
thatchedroof
4f5b8ca08c
Fix typo in World::observe (#14492)
# Objective

- Fix a typo in the documentation for `World::observe`

## Solution

- Change `Spawn` to `Spawns` and `it's` to `its`
2024-07-27 13:55:44 +00:00
Brian Reavis
724fe49c73
Fix TextureCache memory leak and add is_empty() method (#14480)
# Objective

Fix a memory leak in `TextureCache` caused by the internal HashMap never
having unused entries cleared.

This isn't a giant memory leak, given the unused entries are simply
empty vectors. Though, if someone goes and resizes a window a bunch, it
can lead to hundreds/thousands of TextureDescriptor keys adding up in
the hashmap – which isn't ideal.

## Solution

- Only retain hashmap entries that still have textures.
- I also added an `is_empty()` method to `TextureCache`, which is useful
for 3rd-party higher-level caches that might have individual caches by
view entity or texture type, for example.

## Testing

- Verified the examples still work (this is a trivial change)
2024-07-27 13:16:27 +00:00
BD103
e49527e34d
Fix bevy_winit not building with serialize feature (#14469)
# Objective

- `bevy_winit` fails to build with just the `serialize` feature.
- Caught by [`flag-frenzy`](https://github.com/TheBevyFlock/flag-frenzy)
in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10087486444/job/27891723948),
using the new, nuanced configuration system!

## Solution

- It was failing because `bevy_winit` did not pass the `serialize` flag
to two of its dependencies: `bevy_input` and `bevy_window`.
- To fix this, add these crates to the feature flag.

## Testing

```bash
# On Linux, you must also specify a backend: `x11` or `wayland`.
# You can do this with `-F serialize,x11`, etc.
cargo check -p bevy_winit --no-default-features -F serialize
```
2024-07-26 22:05:36 +00:00
NiseVoid
a8003b4496
Handle 0 height in prepare_bloom_textures (#14423)
# Objective

- Fix a confusing panic when the viewport width is non-zero and the
height is 0, `prepare_bloom_textures` tries to create a `4294967295x1`
texture.

## Solution

- Avoid dividing by zero
- Apps still crash after this, but now on a more reasonable error about
the zero-size viewport

## Testing

- I isolated and tested the math. A height of 0 sets `mip_height_ratio`
to `inf`, causing the width to explode if it isn't also 0
2024-07-26 21:53:36 +00:00
BD103
ee4ed231da
Fix bevy_gltf PBR features not enabling corresponding bevy_pbr flags (#14486)
# Objective

- `bevy_gltf` does not build with only the
`pbr_multi_layer_material_textures` or `pbr_anisotropy_texture`
features.
- Caught by [`flag-frenzy`](https://github.com/TheBevyFlock/flag-frenzy)
in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10087486444/job/27891723948).

## Solution

- This error was due to the feature not enabling the corresponding
feature in `bevy_pbr`. Adding these flags as a dependency fixes this
error.

## Testing

The following commands fail on `main`, but pass with this PR:

```bash
cargo check -p bevy_gltf --no-default-features -F pbr_multi_layer_material_textures
cargo check -p bevy_gltf --no-default-features -F pbr_anisotropy_texture
```
2024-07-26 17:11:38 +00:00
Brian Reavis
c1fedc2e2d
Made ViewUniform fields public (#14482)
# Objective

- Made `ViewUniform` fields public so that 3rd-parties can create this
uniform. This is useful for custom pipelines that use custom views (e.g.
views buffered by a particular amount, for example).
2024-07-26 17:11:29 +00:00
Sludge
1edec4d890
Remove #[cfg] from the From impls of TextSection (#14439)
# Objective

- Not including bevy's default font shouldn't result in code not
compiling anymore.
- Games may want to load their own default font into the default
`Handle<Font>` and not include bevy's default font, but still use these
convenience impls (https://github.com/bevyengine/bevy/issues/12192
currently makes this a bit inconvenient, but it does work).

## Solution

- Include these impls unconditionally.
- Slightly expand the comment on the `font` field to indicate that a
custom font can be used to override the default font.
- (drive-by: add `#[reflect(Default)]` on `TextSection`, since it was
missing a way to construct it via reflection)
2024-07-26 17:11:12 +00:00
radiish
6dbc8b8f6f
ptr: allow Ptr and PtrMut construction for references to values of ?Sized types (#14479)
# Objective

- Currently `bevy_ptr::{Ptr, PtrMut}` have `From` implementations from
references.
- These implementations impose an implicit `Sized` bound so `bevy_ptr`
types cannot be created from references to slices and trait objects.
- I ran into this trying to use `Ptr<'static>` as an untyped `&'static
dyn Any`, and [had to work around
it](f32b41512c/src/registry.rs (L214-L219)).

## Solution

- Relax the `Sized` bound on the relevant `From` implementations.
2024-07-25 23:14:16 +00:00
Brian Reavis
438217035d
Don’t prepare 2D view bind groups for 3D cameras (#14481)
# Objective

- Before this fix, the view query in `prepare_mesh2d_view_bind_groups`
matched all views – leading to 2D view bind groups being prepared for 3D
cameras.

## Solution

- Added `With<Camera2d>` to the views query.

## Testing

- Verified the examples still work.
2024-07-25 20:37:54 +00:00
Matty
5aa998dc07
Conversions for Isometry3d ⟷ Transform/GlobalTransform (#14478)
# Objective

Allow interoperation between `Isometry3d` and the transform types from
bevy_transform. At least in the short term, the primary goal is to allow
the extraction of isometries from transform components by users.

## Solution

- Add explicit `from_isometry`/`to_isometry` methods to `Transform`.
- Add explicit `from_isometry`/`to_isometry` methods to
`GlobalTransform`. The former is hidden (primarily for internal use),
and the latter has the caveats originating in
[`Affine3A::to_scale_rotation_translation`](https://docs.rs/glam/latest/glam/f32/struct.Affine3A.html#method.to_scale_rotation_translation).
- Implement the `TransformPoint` trait for `Isometry3d`.
2024-07-25 20:23:32 +00:00
Ben Frankel
e7e10f2c0f
Fix hue mixing for Lcha and Oklcha (#14468)
# Objective

Fix erroneous hue mixing in `Lcha` and `Oklcha`. Purple + Red == Green
is the current behavior.

## Solution

Use `crate::color_ops::lerp_hue` to handle the wrap-around at 360
degrees, the same way that `Hsla`, `Hsva`, and `Hwba` do it.

## Testing

Game jamming, but tested that the workaround below produces
correct-looking colors in my jam game.
2024-07-25 19:44:18 +00:00
Robert Walter
52a2a3b146
Dedicated Reflect implementation for Set-like things (#13014)
# Objective

I just wanted to inspect `HashSet`s in `bevy-inspector-egui` but I
noticed that it didn't work for some reason. A few minutes later I found
myself looking into the bevy reflect impls noticing that `HashSet`s have
been covered only rudimentary up until now.

## Solution

I'm not sure if this is overkill (especially the first bullet), but
here's a list of the changes:

- created a whole new trait and enum variants for `ReflectRef` and the
like called `Set`
- mostly oriented myself at the `Map` trait and made the necessary
changes until RA was happy
- create macro `impl_reflect_for_hashset!` and call it on `std::HashSet`
and `hashbrown::HashSet`

Extra notes:

- no `get_mut` or `get_mut_at` mirroring the `std::HashSet`
- `insert[_boxed]` and `remove` return `bool` mirroring `std::HashSet`,
additionally that bool is reflect as I thought that would be how we
handle things in bevy reflect, but I'm not sure on this
- ser/de are handled via `SeqAccess`
- I'm not sure about the general deduplication property of this impl of
`Set` that is generally expected? I'm also not sure yet if `Map` does
provide this. This mainly refers to the `Dynamic[...]` structs
- I'm not sure if there are other methods missing from the `trait`, I
felt like `contains` or the set-operations (union/diff/...) could've
been helpful, but I wanted to get out the bare minimum for feedback
first

---

## Changelog

### Added
- `Set` trait for `bevy_reflect`

### Changed
- `std::collections::HashSet` and `bevy_utils::hashbrown::HashSet` now
implement a more complete set of reflect functionalities instead of
"just" `reflect_value`
- `TypeInfo` contains a new variant `Set` that contains `SetInfo`
- `ReflectKind` contains a new variant `Set`
- `ReflectRef` contains a new variant `Set`
- `ReflectMut` contains a new variant `Set`
- `ReflectOwned` contains a new variant `Set`

## Migration Guide

- The new `Set` variants on the enums listed in the change section
should probably be considered by people working with this level of the
lib
### Help wanted! 

I'm not sure if this change is able to break code. From my understanding
it shouldn't since we just add functionality but I'm not sure yet if
theres anything missing from my impl that would be normally provided by
`impl_reflect_value!`
2024-07-24 19:43:26 +00:00
Blake Bedford
eabb58aa04
Add BorderRadius field to ImageBundle (#14457)
# Objective

- Fixes #14453

## Solution

- Added BorderRadius to ImageBundle

## Testing

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

- Tested on a random picture I found in the examples and it added a
border radius.

- Are there any parts that need more testing?

- I don't fink so.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

- Apply a border radius to a random picture.
2024-07-24 18:41:26 +00:00
Dmytro Banin
e9e29d61c6
Add intradoc links for observer triggers (#14458)
# Objective

When using observers you might want to know what the difference is
between `OnAdd` vs `OnReplace` vs `OnInsert` etc. It's not obvious where
to look (`component_hooks.rs`). Added intradoc links for easier
disambiguation.
2024-07-24 18:41:23 +00:00
Joseph
218f78157d
Require &mut self for World::increment_change_tick (#14459)
# Objective

The method `World::increment_change_tick` currently takes `&self` as the
method receiver, which is semantically strange. Even though the interior
mutability is sound, the existence of this method is strange since we
tend to think of `&World` as being a read-only snapshot of a world, not
an aliasable reference to a world with mutability. For those purposes,
we have `UnsafeWorldCell`.

## Solution

Change the method signature to take `&mut self`. Use exclusive access to
remove the need for atomic adds, which makes the method slightly more
efficient. Redirect users to [`UnsafeWorldCell::increment_change_tick`]
if they need to increment the world's change tick from an aliased
context.

In practice I don't think there will be many breakages, if any. In cases
where you need to call `increment_change_tick`, you usually already have
either `&mut World` or `UnsafeWorldCell`.

---

## Migration Guide

The method `World::increment_change_tick` now requires `&mut self`
instead of `&self`. If you need to call this method but do not have
mutable access to the world, consider using
`world.as_unsafe_world_cell_readonly().increment_change_tick()`, which
does the same thing, but is less efficient than the method on `World`
due to requiring atomic synchronization.

```rust
fn my_system(world: &World) {
    // Before
    world.increment_change_tick();

    // After
    world.as_unsafe_world_cell_readonly().increment_change_tick();
}
```
2024-07-24 12:42:28 +00:00
Felix Rath
abceebebba
feat: Add World::get_reflect() and World::get_reflect_mut() (#14416)
# Objective

Sometimes one wants to retrieve a `&dyn Reflect` for an entity's
component, which so far required multiple, non-obvious steps and
`unsafe`-code.
The docs for
[`MutUntyped`](https://docs.rs/bevy/latest/bevy/ecs/change_detection/struct.MutUntyped.html#method.map_unchanged)
contain an example of the unsafe part.

## Solution

This PR adds the two methods:

```rust
// immutable variant
World::get_reflect(&self, entity: Entity, type_id: TypeId) -> Result<&dyn Reflect, GetComponentReflectError>

// mutable variant
World::get_reflect_mut(&mut self, entity: Entity, type_id: TypeId) -> Result<Mut<'_, dyn Reflect>, GetComponentReflectError>
```

which take care of the necessary steps, check required invariants etc.,
and contain the unsafety so the caller doesn't have to deal with it.

## Testing

- Did you test these changes? If so, how?
- Added tests and a doc test, also (successfully) ran `cargo run -p ci`.
- Are there any parts that need more testing?
- Could add tests for each individual error variant, but it's not
required imo.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Run `cargo test --doc --package bevy_ecs --all-features --
world::World::get_reflect --show-output` for the doctest
- Run `cargo test --package bevy_ecs --lib --all-features --
world::tests::reflect_tests --show-output` for the unittests
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - Don't think it's relevant, but tested on 64bit linux (only).

---

## Showcase

Copy of the doctest example which gives a good overview of what this
enables:

```rust
use bevy_ecs::prelude::*;
use bevy_reflect::Reflect;
use std::any::TypeId;

// define a `Component` and derive `Reflect` for it
#[derive(Component, Reflect)]
struct MyComponent;

// create a `World` for this example
let mut world = World::new();

// Note: This is usually handled by `App::register_type()`, but this example can not use `App`.
world.init_resource::<AppTypeRegistry>();
world.get_resource_mut::<AppTypeRegistry>().unwrap().write().register::<MyComponent>();

// spawn an entity with a `MyComponent`
let entity = world.spawn(MyComponent).id();

// retrieve a reflected reference to the entity's `MyComponent`
let comp_reflected: &dyn Reflect = world.get_reflect(entity, TypeId::of::<MyComponent>()).unwrap();

// make sure we got the expected type
assert!(comp_reflected.is::<MyComponent>());
```

## Migration Guide

No breaking changes, but users can use the new methods if they did it
manually before.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-23 16:57:54 +00:00
Shane Celis
8a79185880
feature: Derive Hash for KeyboardInput. (#14263)
# Objective

Derive `Hash` for `KeyboardInput`.

## Problem

I was [writing code](https://github.com/joshka/bevy_ratatui/pull/13) to
take `crossterm` events and republish them as bevy input events. One
scenario requires I check if the same key press was happening
repeatedly; in a regular terminal we don't get key released events, so I
was simulating them.

I was surprised to find that I couldn't put `KeyboardInput` into a
`HashSet`.

## Work Around

My work around was to add a new type that implemented Hash.

```rust
#[derive(Deref, DerefMut, PartialEq, Eq)]
struct KeyInput(KeyboardInput);

impl Hash for KeyInput {
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        self.key_code.hash(state);
        self.logical_key.hash(state);
        self.state.hash(state);
        self.window.hash(state);
    }
}
```

## Solution

A better solution since all members of `KeyboardInput` implement `Hash`
is to have it derive `Hash` as well.

## Testing

My newtype solution works for its purpose.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-07-23 12:29:15 +00:00
Sludge
f0ff7fb544
Add and reflect Default impls for CSS grid types (#14443)
# Objective

- Some types here were not constructible via reflection, and some were
missing fairly obvious `Default` values.
- Some types used `#[reflect_value]` for some unstated reason, making
them opaque to reflection-based code.

## Solution

- Add and reflect some `Default` impls, and stop using
`#[reflect_value]`.
2024-07-22 21:39:59 +00:00
charlotte
abaea01e30
Fixup Msaa docs. (#14442)
Minor doc fixes missed in #14273
2024-07-22 21:37:25 +00:00
IceSentry
3faca1e549
Don't ignore draw errors (#13240)
# Objective

- It's possible to have errors in a draw command, but these errors are
ignored

## Solution

- Return a result with the error

## Changelog

Renamed `RenderCommandResult::Failure` to `RenderCommandResult::Skip`
Added a `reason` string parameter to `RenderCommandResult::Failure`

## Migration Guide
If you were using `RenderCommandResult::Failure` to just ignore an error
and retry later, use `RenderCommandResult::Skip` instead.

This wasn't intentional, but this PR should also help with
https://github.com/bevyengine/bevy/issues/12660 since we can turn a few
unwraps into error messages now.

---------

Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
2024-07-22 19:22:30 +00:00
Ben Frankel
ee88d79d88
Simplify run conditions (#14441)
# Objective

Simplify Bevy-provided functions that return a condition-satisfying
closure instead of just being the condition.

## Solution

Become the condition.

## Testing

I did not test. Game jamming. Hopefully CI passes.

---

## Migration Guide

Some run conditions have been simplified.

```rust
// Before:
app.add_systems(Update, (
    system_0.run_if(run_once()),
    system_1.run_if(resource_changed_or_removed::<T>()),
    system_2.run_if(resource_removed::<T>()),
    system_3.run_if(on_event::<T>()),
    system_4.run_if(any_component_removed::<T>()),
));

// After:
app.add_systems(Update, (
    system_0.run_if(run_once),
    system_1.run_if(resource_changed_or_removed::<T>),
    system_2.run_if(resource_removed::<T>),
    system_3.run_if(on_event::<T>),
    system_4.run_if(any_component_removed::<T>),
));
```
2024-07-22 19:21:47 +00:00
BD103
cd497152bb
Fix error in bevy_ui when building without bevy_text (#14430)
# Objective

- `bevy_ui` does not build without the `bevy_text` feature due to
improper feature gating.
- Specifically, `MeasureArgs<'a>` had an unused lifetime `'a` without
`bevy_text` enabled. This is because it stores a reference to a
`cosmic_text::FontSystem`.
- This was caught by `flag-frenzy` in [this
run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10024258523/job/27706132250).

## Solution

- Add a `PhantomData` to `MeasureArgs<'a>` in order to maintain its
lifetime argument.
- I also named it `font_system`, after the feature-gated argument that
actually needs a lifetime, for usability. Please comment if you have a
better solution!
- Move some unused imports to be behind the `bevy_text` feature gate.

## Testing

```bash
# Fails on main.
cargo check -p bevy_ui --no-default-features
# Succeeds on main.
cargo check -p bevy_ui --no-default-features -F bevy_text
```

---

## Migration Guide

**This is not a breaking change for users migrating from 0.14, since
`MeasureArgs` did not exist then.**

When the `bevy_text` feature is disabled for `bevy_ui`, the type of the
`MeasureArgs::font_system` field is now a `PhantomData` instead of being
removed entirely. This is in order to keep the lifetime parameter, even
though it is unused without text being enabled.
2024-07-22 19:19:10 +00:00
Hannes Karppila
93def2611b
Fix repeated animation transition bug (#14411)
# Objective

Fixes #13910

When a transition is over, the animation is stopped. There was a race
condition; if an animation was started while it also had an active
transition, the transition ending would then incorrectly stop the newly
added animation.

## Solution

When starting an animation, cancel any previous transition for the same
animation.

## Testing

The changes were tested manually, mainly by using the `animated_fox`
example. I also tested with changes from
https://github.com/bevyengine/bevy/pull/13909.

I'd like to have an unit test for this as well, but it seems quite
complex to do, as I'm not sure how I would detect an incorrectly paused
animation.

Reviewers can follow the instructions in #13910 to reproduce.

Tested on macos 14.4 (M3 processor) Should be platform-independent,
though.
2024-07-22 19:17:46 +00:00
Daniel Miller
692840274f
Added AstcBlock and AstcChannel to the forwarded wgpu types. (#14410)
Currently `TextureFormat::Astc` can't be programmatically constructed
without importing wgpu in addition to bevy.

# Objective

Allow programmatic construction of `TextureFormat::Astc` with no
additional imports required.

## Solution

Exported the two component enums `AstcBlock` and `AstcChannel` used in
`TextureFormat::Astc` construction.

## Testing

I did not test this, the change seemed pretty safe. :)
2024-07-22 19:14:14 +00:00
Sebastian J. Hamel
d88be59f92
feat: expose the default font bytes (#14406)
# Objective

- Enables use cases where third-party crates would want to use the
default font as well [see linebender's
use](https://github.com/linebender/bevy_vello/pull/66)

## Solution

- Uses `include_bytes` macro and make it `pub`

---------

Co-authored-by: Spencer C. Imbleau <spencer@imbleau.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-07-22 19:09:39 +00:00
John
d1f4262d7d
Only propagate transforms entities with GlobalTransforms. (#14384)
# Objective
Fixes a performance issue when you have 1000s of entities in a bevy
hierarchy without transforms.

This was prominently happening in `bevy_ecs_tilemap`.

## Solution

Filter out entities that don't have a global transform.

## Testing

CI
We should test some other way...

## Migration Guide

- To avoid surprising performance pitfalls, `Transform` /
`GlobalTransform` propagation is no longer performed down through
hierarchies where intermediate parent are missing a `GlobalTransform`.
To restore the previous behavior, add `GlobalTransform::default` to
intermediate entities.
2024-07-22 19:07:21 +00:00
Coder-Joe458
8f5345573c
Remove manual --cfg docsrs (#14376)
# Objective

- Fixes #14132 

## Solution

- Remove the cfg docsrs
2024-07-22 18:58:04 +00:00
Patrick Walton
d235d41af1
Fix the example regressions from packed growable buffers. (#14375)
The "uberbuffers" PR #14257 caused some examples to fail intermittently
for different reasons:

1. `morph_targets` could fail because vertex displacements for morph
targets are keyed off the vertex index. With buffer packing, the vertex
index can vary based on the position in the buffer, which caused the
morph targets to be potentially incorrect. The solution is to include
the first vertex index with the `MeshUniform` (and `MeshInputUniform` if
GPU preprocessing is in use), so that the shader can calculate the true
vertex index before performing the morph operation. This results in
wasted space in `MeshUniform`, which is unfortunate, but we'll soon be
filling in the padding with the ID of the material when bindless
textures land, so this had to happen sooner or later anyhow.

Including the vertex index in the `MeshInputUniform` caused an ordering
problem. The `MeshInputUniform` was created during the extraction phase,
before the allocations occurred, so the extraction logic didn't know
where the mesh vertex data was going to end up. The solution is to move
the `MeshInputUniform` creation (the `collect_meshes_for_gpu_building`
system) to after the allocations phase. This should be better for
parallelism anyhow, because it allows the extraction phase to finish
quicker. It's also something we'll have to do for bindless in any event.

2. The `lines` and `fog_volumes` examples could fail because their
custom drawing nodes weren't updated to supply the vertex and index
offsets in their `draw_indexed` and `draw` calls. This commit fixes this
oversight.

Fixes #14366.
2024-07-22 18:55:51 +00:00
Rostyslav Toch
d30391b583
Optimize transform propagation (#14373)
# Objective

- Optimize the `propagate_recursive` function in the transform system to
reduce CPU usage.
- Addresses performance bottleneck in transform propagation, especially
for scenes with complex hierarchies.

## Solution

- Avoided unnecessary cloning of `global_transform` when creating the
tuple in the `propagate_recursive` function.
- Used `as_ref()` method on `Mut<GlobalTransform>` when passing it to
the recursive call, avoiding an extra dereference.
- These changes significantly reduced the CPU usage of this function
from 4.91% to 1.16% of self function time.

## Testing

- Performance testing was conducted using the Hotspot GUI tool,
comparing CPU usage before and after the changes.
- `cargo run --release --example many_foxes`
- Tested on Fedora Linux.
---

## Showcase

Here are the PERF GUI results showing the improvement in CPU usage:

### Before

![image](https://github.com/user-attachments/assets/b5c52800-710b-4793-bf75-33e3eb1d2083)

### After

![image](https://github.com/user-attachments/assets/654a4feb-924c-41c8-8ff9-3a1027bd28b9)

As we can see, the CPU usage for the `propagate_recursive` function has
been reduced from 4.91% to 1.16%, resulting in a significant performance
improvement.

## Migration Guide

This change does not introduce any breaking changes. Users of the Bevy
engine will automatically benefit from this performance improvement
without needing to modify their code.
2024-07-22 18:53:16 +00:00
Sludge
4ea8c66321
Unignore Camera.target field for reflection (#14367)
# Objective

- The `RenderTarget` type wasn't being registered, and the `target`
field of `Camera` was marked as ignored, so it wasn't inspectable by
editors.

## Solution

- Remove `#[reflect(ignore)]` from the field
- I've also reordered the `Default` impl of `RenderTarget` because it
looked like it belonged to a different type
2024-07-22 18:46:40 +00:00
Al M.
e06f4d4083
Fix single keyframe animations. (#14344)
# Objective

For clips with more than one curve, only the first was being applied if
there is only one keyframe in it.

## Solution

Continue!
2024-07-22 18:44:27 +00:00
IQuick 143
420f7f72dc
Fast renormalize (#14316)
# Objective

- Addresses part of #14302 .

## Solution

- Add a fast_remormalize method to Dir2/Dir3/Dir3A and Rot2.

## Testing

- Added tests too

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-07-22 18:42:48 +00:00
charlotte
03fd1b46ef
Move Msaa to component (#14273)
Switches `Msaa` from being a globally configured resource to a per
camera view component.

Closes #7194

# Objective

Allow individual views to describe their own MSAA settings. For example,
when rendering to different windows or to different parts of the same
view.

## Solution

Make `Msaa` a component that is required on all camera bundles.

## Testing

Ran a variety of examples to ensure that nothing broke.

TODO:
- [ ] Make sure android still works per previous comment in
`extract_windows`.

---

## Migration Guide

`Msaa` is no longer configured as a global resource, and should be
specified on each spawned camera if a non-default setting is desired.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-07-22 18:28:23 +00:00
Sou1gh0st
462da1e49d
Fix incorrect function calls to hsv_to_rgb in render debug code. (#14260)
# Objective

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

## Solution

- correct the input parameters at these call sites.

## Testing

1. Use a 3D scene example with PBR lighting and shadows enabled, such as
the `shadow_caster_receiver` and `load_gltf` example, for testing.
2. Enable relevant shader defines in crates/bevy_pbr/src/pbr_material.rs
for the StandardMaterial.
```rust
impl Material for StandardMaterial {
    // ...
    fn specialize(
            _pipeline: &MaterialPipeline<Self>,
            descriptor: &mut RenderPipelineDescriptor,
            _layout: &MeshVertexBufferLayoutRef,
            key: MaterialPipelineKey<Self>,
        ) -> Result<(), SpecializedMeshPipelineError> {
            // ...
            // shader_defs.push("CLUSTERED_FORWARD_DEBUG_Z_SLICES".into());
            // shader_defs.push("CLUSTERED_FORWARD_DEBUG_CLUSTER_COHERENCY".into());
            shader_defs.push("DIRECTIONAL_LIGHT_SHADOW_MAP_DEBUG_CASCADES".into());
            // ...
    }
}
``` 

## Showcase
### CLUSTERED_FORWARD_DEBUG_Z_SLICES
- example: examples/3d/shadow_caster_receiver.rs

![Screenshot2024_07_10_143150](https://github.com/bevyengine/bevy/assets/6300263/fbd12712-5cb9-489d-a7d1-ed55f72fb234)

### CLUSTERED_FORWARD_DEBUG_CLUSTER_COHERENCY
- example: examples/3d/shadow_caster_receiver.rs

![Screenshot2024_07_10_143312](https://github.com/bevyengine/bevy/assets/6300263/8eca5d7a-27b6-4ff5-9f8d-d10b49b3f990)

### DIRECTIONAL_LIGHT_SHADOW_MAP_DEBUG_CASCADES
For this one, we need to use a large scene and modity the
`CascadeShadowConfigBuilder`, here is a simple patch for the `load_gltf`
example:
```
diff --git a/examples/3d/load_gltf.rs b/examples/3d/load_gltf.rs
index 358446238..9403aa288 100644
--- a/examples/3d/load_gltf.rs
+++ b/examples/3d/load_gltf.rs
@@ -18,7 +18,7 @@ fn main() {
 fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
     commands.spawn((
         Camera3dBundle {
-            transform: Transform::from_xyz(0.7, 0.7, 1.0)
+            transform: Transform::from_xyz(0.7, 0.7, 2.0)
                 .looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
             ..default()
         },
@@ -39,30 +39,40 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
         // We also adjusted the shadow map to be larger since we're
         // only using a single cascade.
         cascade_shadow_config: CascadeShadowConfigBuilder {
-            num_cascades: 1,
-            maximum_distance: 1.6,
+            num_cascades: 5,
+            maximum_distance: 20.0,
             ..default()
         }
         .into(),
         ..default()
     });
+
     commands.spawn(SceneBundle {
         scene: asset_server
             .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")),
         ..default()
     });
+
+    for i in 1..=10 {
+        commands.spawn(SceneBundle {
+            scene: asset_server
+                .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")),
+            transform: Transform::from_xyz(i as f32 * 0.5, 0.0, i as f32 * -2.0),
+            ..default()
+        });
+    }
 }
 
 fn animate_light_direction(
     time: Res<Time>,
     mut query: Query<&mut Transform, With<DirectionalLight>>,
 ) {
-    for mut transform in &mut query {
-        transform.rotation = Quat::from_euler(
-            EulerRot::ZYX,
-            0.0,
-            time.elapsed_seconds() * PI / 5.0,
-            -FRAC_PI_4,
-        );
-    }
+    // for mut transform in &mut query {
+    //     transform.rotation = Quat::from_euler(
+    //         EulerRot::ZYX,
+    //         0.0,
+    //         time.elapsed_seconds() * PI / 5.0,
+    //         -FRAC_PI_4,
+    //     );
+    // }
 }
``` 

![Screenshot2024_07_10_145737](https://github.com/bevyengine/bevy/assets/6300263/c5c71894-f9f7-45fa-9b4f-598e324b42d0)

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2024-07-22 18:25:54 +00:00
Peter Hayman
b8416b3043
Add some missing reflect attributes (#14259)
# Objective

- Some types are missing reflection attributes, which means we can't use
them in scene serialization etc.
- Effected types
   - `BorderRadius`
   - `AnimationTransitions`
   - `OnAdd`
   - `OnInsert`
   - `OnRemove`
- My use-case for `OnAdd` etc to derive reflect is 'Serializable
Observer Components'. Add the component, save the scene, then the
observer is re-added on scene load.

```rust
#[derive(Reflect)]
struct MySerializeableObserver<T: Event>(#[reflect(ignore)]PhantomData<T>);

impl<T: Event> Component for MySerializeableObserver<T> {
  const STORAGE_TYPE: StorageType  = StorageType::Table;
    fn register_component_hooks(hooks: &mut ComponentHooks) {
      hooks.on_add(|mut world, entity, _| {
        world
          .commands()
          .entity(entity)
          .observe(|_trigger: Trigger<T>| {
            println!("it triggered etc.");
          });
    });
  }
}
```

## Solution

- Add the missing traits

---
2024-07-22 18:24:10 +00:00
ickshonpe
453e0e4fc1
Prevent division by zero in HWBA to HSVA conversions (#14256)
# Problem

Division by zero in `crates/bevy_color/src/hsva.rs` when `blackness` is
`1`:

```rust
impl From<Hwba> for Hsva {
    fn from(
        Hwba {
            hue,
            whiteness,
            blackness,
            alpha,
        }: Hwba,
    ) -> Self {
        // Based on https://en.wikipedia.org/wiki/HWB_color_model#Conversion
        let value = 1. - blackness;
        let saturation = 1. - (whiteness / value);

        Hsva::new(hue, saturation, value, alpha)
    }
}
```

## Solution
With `Hsva` colors if the `value` component is set to `0.` the output
will be pure black regardless of the values of the `hue` or `saturation`
components.

So if `value` is `0`, we don't need to calculate a `saturation` value
and can just set it to `0`:

```rust
impl From<Hwba> for Hsva {
    fn from(
        Hwba {
            hue,
            whiteness,
            blackness,
            alpha,
        }: Hwba,
    ) -> Self {
        // Based on https://en.wikipedia.org/wiki/HWB_color_model#Conversion
        let value = 1. - blackness;
        let saturation = if value != 0. {
            1. - (whiteness / value)
        } else {
            0.
        };

        Hsva::new(hue, saturation, value, alpha)
    }
}

```

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-22 18:22:26 +00:00
Vic
bc36b4e561
implement DoubleEndedIterator for QueryManyIter (#14128)
# Objective

We currently cannot iterate from the back of `QueryManyIter`.

## Solution

Implement `DoubleEndedIterator` for `QueryManyIter` and add a
`fetch_next_back` method. These impls are bounded on the underlying
`entity_iter` implementing `DoubleEndedIterator`.

## Changelog

Added `DoubleEndedIterator` implementation for `QueryManyIter`.
Added the `fetch_next_back` method to `QueryManyIter`.
2024-07-22 18:21:42 +00:00
charlotte
08d3497d87
Fix breaking image 0.25.2 release. (#14421)
Deprecated item breaking ci:
https://github.com/image-rs/image/releases/tag/v0.25.2. See
https://github.com/bevyengine/bevy/actions/runs/10030764981/job/27720434072?pr=14419
for example.
2024-07-21 21:27:07 +00:00
Sunil Thunga
2158f3d91f
Using Cas instead of CAS #14341 (#14357)
# Objective

- Replacing CAS with Cas in CASPlugin
- Closes #14341

## Solution

- Simple replace

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-07-20 18:12:24 +00:00
François Mockers
c0b35d07f3
fix building cargo_gltf with feature dds (#14360)
# Objective

- Building bevy_gltf with feature dds fails:
```
> cargo build -p bevy_gltf --features dds
   Compiling bevy_core_pipeline v0.15.0-dev (crates/bevy_core_pipeline)
error[E0061]: this function takes 7 arguments but 6 arguments were supplied
   --> crates/bevy_core_pipeline/src/tonemapping/mod.rs:442:5
    |
442 |     Image::from_buffer(
    |     ^^^^^^^^^^^^^^^^^^
...
445 |         bytes,
    |         ----- an argument of type `std::string::String` is missing
    |
note: associated function defined here
   --> crates/bevy_render/src/texture/image.rs:709:12
    |
709 |     pub fn from_buffer(
    |            ^^^^^^^^^^^
help: provide the argument
    |
442 |     Image::from_buffer(/* std::string::String */, bytes, image_type, CompressedImageFormats::NONE, false, image_sampler, RenderAssetUsages::RENDER_WORLD)
    |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0061`.
error: could not compile `bevy_core_pipeline` (lib) due to 1 previous error
```
- If you're fixing a specific issue, say "Fixes #X".

## Solution

- enable dds feature in bevy_core_pipeline

## Testing

- `cargo build -p bevy_gltf --features dds`
2024-07-20 17:55:25 +00:00
charlotte
3aa525885b
Set scissor on upscale to match camera viewport (#14287)
# Objective

When the user renders multiple cameras to the same output texture, it
can sometimes be confusing what `ClearColorConfig` is necessary for each
camera to avoid overwriting the previous camera's output. This is
particular true in cases where the user uses mixed HDR cameras, which
means that their scene is being rendered to different internal textures.

## Solution

When a view has a configured viewport, set the GPU scissor in the
upscaling node so we don't overwrite areas that were written to by other
cameras.

## Testing

Ran the `split_screen` example.
2024-07-20 16:45:04 +00:00
Sludge
c0cebfef45
Make Viewport::default() return a 1x1 viewport (#14372)
# Objective

- The current default viewport crashes bevy due to a wgpu validation
error, this PR fixes that
- Fixes https://github.com/bevyengine/bevy/issues/14355

## Solution

- `Viewport::default()` now returns a 1x1 viewport

## Testing

- I modified the `3d_viewport_to_world` example to use
`Viewport::default()`, and it works as expected (only the top-left pixel
is rendered)
2024-07-20 14:18:12 +00:00
Sou1gh0st
9da18cce2a
Add support for environment map transformation (#14290)
# Objective

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

## Solution

- Add a world space transformation for the environment sample direction.

## Testing

- I have tested the newly added `transform` field using the newly added
`rotate_environment_map` example.


https://github.com/user-attachments/assets/2de77c65-14bc-48ee-b76a-fb4e9782dbdb


## Migration Guide

- Since we have added a new filed to the `EnvironmentMapLight` struct,
users will need to include `..default()` or some rotation value in their
initialization code.
2024-07-19 15:00:50 +00:00
Abe
d8d49fdd13
Deprecate is_playing_animation (#14387)
# Objective

Fixes #14386

## Solution

- Added the `#[deprecate]` attribute to the `is_playing_animation`
function.

## Testing

The project successfully builds.

---

## Migration Guide

The user will just need to replace functions named
`is_playing_animation` with `animation_is_playing`.
2024-07-19 11:27:43 +00:00
Patrick Walton
2a6dd3e2e0
Make the GltfNode::children links actually point to children. (#14390)
Due to a bug in `load_gltf`, the `GltfNode::children` links of each node
actually point to the node itself, rather than to the node's children.
This commit fixes that bug.

Note that this didn't affect the scene hierarchy of the instantiated
glTF, only the hierarchy as present in the `GltfNode` assets. This is
likely why the bug was never noticed until now.
2024-07-19 11:24:06 +00:00
re0312
e5bf59d712
Recalibrated observe benchmark (#14381)
# Objective

- The event propagation benchmark is largely derived from
bevy_eventlistener. However, it doesn't accurately reflect performance
of bevy side, as our event bubble propagation is based on observer.


## Solution

- added several new benchmarks that focuse on observer itself rather
than event bubble
2024-07-18 18:25:33 +00:00
Lars Frost
dcbd30200e
Make names of closure systems changable (#14369)
# Objective

When using tracing or
[`bevy_mod_debugdump`](https://github.com/jakobhellermann/bevy_mod_debugdump),
the names of function systems produced by closures are either ambiguous
(like `game::mainapp::{closure}` when tracing) or too long
(`bevy_mod_debugdump` includes full type signature if no name given),
which makes debugging with tracing difficult.

## Solution
Add a function `with_name` to rename a system. The proposed API can be
used in the following way:
```rust
app
    .add_systems(Startup, IntoSystem::into_system(|name: SystemName| {
        println!("System name: {}", name.name().to_owned());
    }).with_name("print_test_system"));
```

## Testing
- There is a test in
`bevy_ecs::system:system_name::test_closure_system_name_regular_param`
2024-07-18 18:07:47 +00:00
Thierry Berger
26fc4c7198
Test for ambiguous system ordering in CI (#13950)
Progress towards https://github.com/bevyengine/bevy/issues/7386.

Following discussion
https://discord.com/channels/691052431525675048/1253260494538539048/1253387942311886960

This Pull Request adds an example to detect system order ambiguities,
and also asserts none exist.

A lot of schedules are ignored in ordered to have the test passing, we
should thrive to make them pass, but in other pull requests.

<details><summary>example output <b>summary</b>, without ignored
schedules</summary>
<p>

```txt
$ cargo run --example ambiguity_detection 2>&1 | grep -C 1 "pairs of syst"
2024-06-21T13:17:55.776585Z  WARN bevy_ecs::schedule::schedule: Schedule First has ambiguities.
1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- bevy_time::time_system (in set TimeSystem) and bevy_ecs::event::event_update_system (in set EventUpdates)
--
2024-06-21T13:17:55.782265Z  WARN bevy_ecs::schedule::schedule: Schedule PreUpdate has ambiguities.
11 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- bevy_pbr::prepass::update_mesh_previous_global_transforms and bevy_asset::server::handle_internal_asset_events
--
2024-06-21T13:17:55.809516Z  WARN bevy_ecs::schedule::schedule: Schedule PostUpdate has ambiguities.
63 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- bevy_ui::accessibility::image_changed and bevy_ecs::schedule::executor::apply_deferred
--
2024-06-21T13:17:55.816287Z  WARN bevy_ecs::schedule::schedule: Schedule Last has ambiguities.
3 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- bevy_gizmos::update_gizmo_meshes<bevy_gizmos::aabb::AabbGizmoConfigGroup> (in set UpdateGizmoMeshes) and bevy_gizmos::update_gizmo_meshes<bevy_gizmos::light::LightGizmoConfigGroup> (in set UpdateGizmoMeshes)
--
2024-06-21T13:17:55.831074Z  WARN bevy_ecs::schedule::schedule: Schedule ExtractSchedule has ambiguities.
296 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- bevy_render::extract_component::extract_components<bevy_sprite::SpriteSource> and bevy_render::render_asset::extract_render_asset<bevy_sprite::mesh2d::material::PreparedMaterial2d<bevy_sprite::mesh2d::color_material::ColorMaterial>>
```

</p>
</details> 

To try locally: 
```sh
CI_TESTING_CONFIG="./.github/example-run/ambiguity_detection.ron" cargo run --example ambiguity_detection --features "bevy_ci_testing,trace,trace_chrome"
```

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-07-17 21:05:48 +00:00
Sludge
fa855f7974
Derive and reflect Debug for CameraRenderGraph (#14364)
# Objective

- `CameraRenderGraph` is not inspectable via reflection, but should be
(the name of the configured render graph should be visible in editors,
etc.)

## Solution

- Derive and reflect `Debug` for `CameraRenderGraph`
2024-07-17 19:41:31 +00:00
Matty
3484bd916f
Cyclic splines (#14106)
# Objective

Fill a gap in the functionality of our curve constructions by allowing
users to easily build cyclic curves from control data.

## Solution

Here I opted for something lightweight and discoverable. There is a new
`CyclicCubicGenerator` trait with a method `to_curve_cyclic` which uses
splines' control data to create curves that are cyclic. For now, its
signature is exactly like that of `CubicGenerator` — `to_curve_cyclic`
just yields a `CubicCurve`:
```rust
/// Implement this on cubic splines that can generate a cyclic cubic curve from their spline parameters.
///
/// This makes sense only when the control data can be interpreted cyclically.
pub trait CyclicCubicGenerator<P: VectorSpace> {
    /// Build a cyclic [`CubicCurve`] by computing the interpolation coefficients for each curve segment.
    fn to_curve_cyclic(&self) -> CubicCurve<P>;
}
```

This trait has been implemented for `CubicHermite`,
`CubicCardinalSpline`, `CubicBSpline`, and `LinearSpline`:

<img width="753" alt="Screenshot 2024-07-01 at 8 58 27 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/69ae0802-3b78-4fb9-b73a-6f842cf3b33c">
<img width="628" alt="Screenshot 2024-07-01 at 9 00 14 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/2992175a-a96c-40fc-b1a1-5206c3572cde">
<img width="606" alt="Screenshot 2024-07-01 at 8 59 36 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/9e99eb3a-dbe6-42da-886c-3d3e00410d03">
<img width="603" alt="Screenshot 2024-07-01 at 8 59 01 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/d037bc0c-396a-43af-ab5c-fad9a29417ef">

(Each type pictured respectively with the control points rendered as
green spheres; tangents not pictured in the case of the Hermite spline.)

These curves are all parametrized so that the output of `to_curve` and
the output of `to_curve_cyclic` are similar. For instance, in
`CubicCardinalSpline`, the first output segment is a curve segment
joining the first and second control points in each, although it is
constructed differently. In the other cases, the segments from
`to_curve` are a subset of those in `to_curve_cyclic`, with the new
segments appearing at the end.

## Testing

I rendered cyclic splines from control data and made sure they looked
reasonable. Existing tests are intact for splines where previous code
was modified. (Note that the coefficient computation for cyclic spline
segments is almost verbatim identical to that of their non-cyclic
counterparts.)

The Bezier benchmarks also look fine.

---

## Changelog

- Added `CyclicCubicGenerator` trait to `bevy_math::cubic_splines` for
creating cyclic curves from control data.
- Implemented `CyclicCubicGenerator` for `CubicHermite`,
`CubicCardinalSpline`, `CubicBSpline`, and `LinearSpline`.
- `bevy_math` now depends on `itertools`.

---

## Discussion

### Design decisions

The biggest thing here is just the approach taken in the first place:
namely, the cyclic constructions use new methods on the same old
structs. This choice was made to reduce friction and increase
discoverability but also because creating new ones just seemed
unnecessary: the underlying data would have been the same, so creating
something like "`CyclicCubicBSpline`" whose internally-held control data
is regarded as cyclic in nature doesn't really accomplish much — the end
result for the user is basically the same either way.

Similarly, I don't presently see a pressing need for `to_curve_cyclic`
to output something other than a `CubicCurve`, although changing this in
the future may be useful. See below.

A notable omission here is that `CyclicCubicGenerator` is not
implemented for `CubicBezier`. This is not a gap waiting to be filled —
`CubicBezier` just doesn't have enough data to join its start with its
end without just making up the requisite control points wholesale. In
all the cases where `CyclicCubicGenerator` has been implemented here,
the fashion in which the ends are connected is quite natural and follows
the semantics of the associated spline construction.

### Future direction

There are two main things here:
1. We should investigate whether we should do something similar for
NURBS. I just don't know that much about NURBS at the moment, so I
regarded this as out of scope for the PR.
2. We may eventually want to change the output type of
`CyclicCubicGenerator::to_curve_cyclic` to a type which reifies the
cyclic nature of the curve output. This wasn't done in this PR because
I'm unsure how much value a type-level guarantee of cyclicity actually
has, but if some useful features make sense only in the case of cyclic
curves, this might be worth pursuing.
2024-07-17 13:02:31 +00:00
Martín Maita
72e7a4fed2
Update trigger_observers to operate over slices of data (#14354)
# Objective

- Fixes #14333 

## Solution

- Updated `trigger_observers` signature to operate over a slice instead
of an `Iterator`.
- Updated calls to `trigger_observers` to match the new signature.

---

## Migration Guide

- TBD
2024-07-17 13:01:52 +00:00
Patrick Walton
bc34216929
Pack multiple vertex and index arrays together into growable buffers. (#14257)
This commit uses the [`offset-allocator`] crate to combine vertex and
index arrays from different meshes into single buffers. Since the
primary source of `wgpu` overhead is from validation and synchronization
when switching buffers, this significantly improves Bevy's rendering
performance on many scenes.

This patch is a more flexible version of #13218, which also used slabs.
Unlike #13218, which used slabs of a fixed size, this commit implements
slabs that start small and can grow. In addition to reducing memory
usage, supporting slab growth reduces the number of vertex and index
buffer switches that need to happen during rendering, leading to
improved performance. To prevent pathological fragmentation behavior,
slabs are capped to a maximum size, and mesh arrays that are too large
get their own dedicated slabs.

As an additional improvement over #13218, this commit allows the
application to customize all allocator heuristics. The
`MeshAllocatorSettings` resource contains values that adjust the minimum
and maximum slab sizes, the cutoff point at which meshes get their own
dedicated slabs, and the rate at which slabs grow. Hopefully-sensible
defaults have been chosen for each value.

Unfortunately, WebGL 2 doesn't support the *base vertex* feature, which
is necessary to pack vertex arrays from different meshes into the same
buffer. `wgpu` represents this restriction as the downlevel flag
`BASE_VERTEX`. This patch detects that bit and ensures that all vertex
buffers get dedicated slabs on that platform. Even on WebGL 2, though,
we can combine all *index* arrays into single buffers to reduce buffer
changes, and we do so.

The following measurements are on Bistro:

Overall frame time improves from 8.74 ms to 5.53 ms (1.58x speedup):
![Screenshot 2024-07-09
163521](https://github.com/bevyengine/bevy/assets/157897/5d83c824-c0ee-434c-bbaf-218ff7212c48)

Render system time improves from 6.57 ms to 3.54 ms (1.86x speedup):
![Screenshot 2024-07-09
163559](https://github.com/bevyengine/bevy/assets/157897/d94e2273-c3a0-496a-9f88-20d394129610)

Opaque pass time improves from 4.64 ms to 2.33 ms (1.99x speedup):
![Screenshot 2024-07-09
163536](https://github.com/bevyengine/bevy/assets/157897/e4ef6e48-d60e-44ae-9a71-b9a731c99d9a)

## Migration Guide

### Changed

* Vertex and index buffers for meshes may now be packed alongside other
buffers, for performance.
* `GpuMesh` has been renamed to `RenderMesh`, to reflect the fact that
it no longer directly stores handles to GPU objects.
* Because meshes no longer have their own vertex and index buffers, the
responsibility for the buffers has moved from `GpuMesh` (now called
`RenderMesh`) to the `MeshAllocator` resource. To access the vertex data
for a mesh, use `MeshAllocator::mesh_vertex_slice`. To access the index
data for a mesh, use `MeshAllocator::mesh_index_slice`.

[`offset-allocator`]: https://github.com/pcwalton/offset-allocator
2024-07-16 20:33:15 +00:00
Gino Valente
af865e76a3
bevy_reflect: Improve DynamicFunction ergonomics (#14201)
# Objective

Many functions can be converted to `DynamicFunction` using
`IntoFunction`. Unfortunately, we are limited by Rust itself and the
implementations are far from exhaustive. For example, we can't convert
functions with more than 16 arguments. Additionally, we can't handle
returns with lifetimes not tied to the lifetime of the first argument.

In such cases, users will have to create their `DynamicFunction`
manually.

Let's take the following function:

```rust
fn get(index: usize, list: &Vec<String>) -> &String {
    &list[index]
}
```

This function cannot be converted to a `DynamicFunction` via
`IntoFunction` due to the lifetime of the return value being tied to the
second argument. Therefore, we need to construct the `DynamicFunction`
manually:

```rust
DynamicFunction::new(
    |mut args, info| {
        let list = args
            .pop()
            .unwrap()
            .take_ref::<Vec<String>>(&info.args()[1])?;
        let index = args.pop().unwrap().take_owned::<usize>(&info.args()[0])?;
        Ok(Return::Ref(get(index, list)))
    },
    FunctionInfo::new()
        .with_name("get")
        .with_args(vec![
            ArgInfo:🆕:<usize>(0).with_name("index"),
            ArgInfo:🆕:<&Vec<String>>(1).with_name("list"),
        ])
        .with_return_info(ReturnInfo:🆕:<&String>()),
);
```

While still a small and straightforward snippet, there's a decent amount
going on here. There's a lot of room for improvements when it comes to
ergonomics and readability.

The goal of this PR is to address those issues.

## Solution

Improve the ergonomics and readability of manually created
`DynamicFunction`s.

Some of the major changes:
1. Removed the need for `&ArgInfo` when reifying arguments (i.e. the
`&info.args()[1]` calls)
2. Added additional `pop` methods on `ArgList` to handle both popping
and casting
3. Added `take` methods on `ArgList` for taking the arguments out in
order
4. Removed the need for `&FunctionInfo` in the internal closure (Change
1 made it no longer necessary)
5. Added methods to automatically handle generating `ArgInfo` and
`ReturnInfo`

With all these changes in place, we get something a lot nicer to both
write and look at:

```rust
DynamicFunction::new(
    |mut args| {
        let index = args.take::<usize>()?;
        let list = args.take::<&Vec<String>>()?;
        Ok(Return::Ref(get(index, list)))
    },
    FunctionInfo::new()
        .with_name("get")
        .with_arg::<usize>("index")
        .with_arg::<&Vec<String>>("list")
        .with_return::<&String>(),
);
```

Alternatively, to rely on type inference for taking arguments, you could
do:

```rust
DynamicFunction::new(
    |mut args| {
        let index = args.take_owned()?;
        let list = args.take_ref()?;
        Ok(Return::Ref(get(index, list)))
    },
    FunctionInfo::new()
        .with_name("get")
        .with_arg::<usize>("index")
        .with_arg::<&Vec<String>>("list")
        .with_return::<&String>(),
);
```

## Testing

You can test locally by running:

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

---

## Changelog

- Removed `&ArgInfo` argument from `FromArg::from_arg` trait method
- Removed `&ArgInfo` argument from `Arg::take_***` methods
- Added `ArgValue`
- `Arg` is now a struct containing an `ArgValue` and an argument `index`
- `Arg::take_***` methods now require `T` is also `TypePath`
- Added `Arg::new`, `Arg::index`, `Arg::value`, `Arg::take_value`, and
`Arg::take` methods
- Replaced `ArgId` in `ArgError` with just the argument `index`
- Added `ArgError::EmptyArgList`
- Renamed `ArgList::push` to `ArgList::push_arg`
- Added `ArgList::pop_arg`, `ArgList::pop_owned`, `ArgList::pop_ref`,
and `ArgList::pop_mut`
- Added `ArgList::take_arg`, `ArgList::take_owned`, `ArgList::take_ref`,
`ArgList::take_mut`, and `ArgList::take`
- `ArgList::pop` is now generic
- Renamed `FunctionError::InvalidArgCount` to
`FunctionError::ArgCountMismatch`
- The closure given to `DynamicFunction::new` no longer has a
`&FunctionInfo` argument
- Added `FunctionInfo::with_arg`
- Added `FunctionInfo::with_return`

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

* The `FromArg::from_arg` trait method and the `Arg::take_***` methods
no longer take a `&ArgInfo` argument.
* What used to be `Arg` is now `ArgValue`. `Arg` is now a struct which
contains an `ArgValue`.
* `Arg::take_***` methods now require `T` is also `TypePath`
* Instances of `id: ArgId` in `ArgError` have been replaced with `index:
usize`
* `ArgList::push` is now `ArgList::push_arg`. It also takes the new
`ArgValue` type.
* `ArgList::pop` has become `ArgList::pop_arg` and now returns
`ArgValue`. `Arg::pop` now takes a generic type and downcasts to that
type. It's recommended to use `ArgList::take` and friends instead since
they allow removing the arguments from the list in the order they were
pushed (rather than reverse order).
* `FunctionError::InvalidArgCount` is now
`FunctionError::ArgCountMismatch`
* The closure given to `DynamicFunction::new` no longer has a
`&FunctionInfo` argument. This argument can be removed.
2024-07-16 13:01:52 +00:00
Steve Frampton
0e13b1ca5e
Added new method to Cone 3D primitive (#14325)
Reference to #14299.

# Objective
- Ensuring consistent practice of instantiating 3D primitive shapes in
Bevy.

## Solution

- Add `new` method, containing `radius` and `height` arguments, to Cone
3D primitive shape.

## Testing

- Instantiated cone using same values (radius is `2.` and height is
`5.`), using the current method and the added `new` method.
- Basic setup of Bevy Default Plugins and `3DCameraBundle`.


---

## Showcase

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

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

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

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    let new_cone = meshes.add(Cone::new(2., 5.));
    commands.spawn(PbrBundle {
        mesh: new_cone,
        ..default()
    });

    let old_cone = meshes.add(Cone {
        radius: 2.,
        height: 5.,
    });
    commands.spawn(PbrBundle {
        mesh: old_cone,
        material: materials.add(Color::WHITE),
        transform: Transform::from_xyz(10., 0., 0.),
        ..default()
    });

    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(20., 20., 20.).looking_at(Vec3::ZERO, Dir3::Y),
        ..default()
    });
}
```

</details>


![image](https://github.com/user-attachments/assets/267f8124-8734-4c20-8840-fcf35375a778)


- Pink Cone is created using the `new` method.
- Black Cone is created using the existing method.

## Migration Guide
- Addition of `new` method to the 3D primitive Cone struct.
2024-07-16 12:59:26 +00:00
Mike
cfcb56f5b9
Remove need for EventLoopProxy to be NonSend (#14198)
# Objective

- Continue to pare down the uses on NonSend resources in the engine. In
this case, EventLoopProxy used to be `!Sync`, but is now `Sync` in the
latest version of winit.

## Solution

- New type `EventLoopProxy` as `EventLoopProxyWrapper` to make it into a
normal resource.
- Update the `custom_user_event` example as it no longer needs to
indirectly access the `EventLoopProxy` through a static variable
anymore.

## Testing

- Ran the example. The resource exists just for users to use, so there
aren't any in engine uses for it currently.

---

## Changelog

- make EventLoopProxy into a regular resource. 

## Migration Guide

`EventLoopProxy` has been renamed to `EventLoopProxyWrapper` and is now
`Send`, making it an ordinary resource.

Before:
```rust
event_loop_system(event_loop: NonSend<EventLoopProxy<MyEvent>>) {
    event_loop.send_event(MyEvent);
}
```

After:
```rust
event_loop_system(event_loop: Res<EventLoopProxy<MyEvent>>) {
    event_loop.send_event(MyEvent);
}
```
2024-07-16 06:59:01 +00:00
Gino Valente
1042f09c2e
bevy_reflect: Add DynamicClosure and DynamicClosureMut (#14141)
# Objective

As mentioned in
[this](https://github.com/bevyengine/bevy/pull/13152#issuecomment-2198387297)
comment, creating a function registry (see #14098) is a bit difficult
due to the requirements of `DynamicFunction`. Internally, a
`DynamicFunction` contains a `Box<dyn FnMut>` (the function that reifies
reflected arguments and calls the actual function), which requires `&mut
self` in order to be called.

This means that users would require a mutable reference to the function
registry for it to be useful— which isn't great. And they can't clone
the `DynamicFunction` either because cloning an `FnMut` isn't really
feasible (wrapping it in an `Arc` would allow it to be cloned but we
wouldn't be able to call the clone since we need a mutable reference to
the `FnMut`, which we can't get with multiple `Arc`s still alive,
requiring us to also slap in a `Mutex`, which adds additional overhead).

And we don't want to just replace the `dyn FnMut` with `dyn Fn` as that
would prevent reflecting closures that mutate their environment.

Instead, we need to introduce a new type to split the requirements of
`DynamicFunction`.

## Solution

Introduce new types for representing closures.

Specifically, this PR introduces `DynamicClosure` and
`DynamicClosureMut`. Similar to how `IntoFunction` exists for
`DynamicFunction`, two new traits were introduced: `IntoClosure` and
`IntoClosureMut`.

Now `DynamicFunction` stores a `dyn Fn` with a `'static` lifetime.
`DynamicClosure` also uses a `dyn Fn` but has a lifetime, `'env`, tied
to its environment. `DynamicClosureMut` is most like the old
`DynamicFunction`, keeping the `dyn FnMut` and also typing its lifetime,
`'env`, to the environment

Here are some comparison tables:

|   | `DynamicFunction` | `DynamicClosure` | `DynamicClosureMut` |
| - | ----------------- | ---------------- | ------------------- |
| Callable with `&self` |  |  |  |
| Callable with `&mut self` |  |  |  |
| Allows for non-`'static` lifetimes |  |  |  |

|   | `IntoFunction` | `IntoClosure` | `IntoClosureMut` |
| - | -------------- | ------------- | ---------------- |
| Convert `fn` functions |  |  |  |
| Convert `fn` methods |  |  |  |
| Convert anonymous functions |  |  |  |
| Convert closures that capture immutable references |  |  |  |
| Convert closures that capture mutable references |  |  |  |
| Convert closures that capture owned values | [^1] |  |  |

[^1]: Due to limitations in Rust, `IntoFunction` can't be implemented
for just functions (unless we forced users to manually coerce them to
function pointers first). So closures that meet the trait requirements
_can technically_ be converted into a `DynamicFunction` as well. To both
future-proof and reduce confusion, though, we'll just pretend like this
isn't a thing.

```rust
let mut list: Vec<i32> = vec![1, 2, 3];

// `replace` is a closure that captures a mutable reference to `list`
let mut replace = |index: usize, value: i32| -> i32 {
  let old_value = list[index];
  list[index] = value;
  old_value
};

// Convert the closure into a dynamic closure using `IntoClosureMut::into_closure_mut`
let mut func: DynamicClosureMut = replace.into_closure_mut();

// Dynamically call the closure:
let args = ArgList::default().push_owned(1_usize).push_owned(-2_i32);
let value = func.call_once(args).unwrap().unwrap_owned();

// Check the result:
assert_eq!(value.take::<i32>().unwrap(), 2);
assert_eq!(list, vec![1, -2, 3]);
```

### `ReflectFn`/`ReflectFnMut`

To make extending the function reflection system easier (the blanket
impls for `IntoFunction`, `IntoClosure`, and `IntoClosureMut` are all
incredibly short), this PR generalizes callables with two new traits:
`ReflectFn` and `ReflectFnMut`.

These traits mimic `Fn` and `FnMut` but allow for being called via
reflection. In fact, their blanket implementations are identical save
for `ReflectFn` being implemented over `Fn` types and `ReflectFnMut`
being implemented over `FnMut` types.

And just as `Fn` is a subtrait of `FnMut`, `ReflectFn` is a subtrait of
`ReflectFnMut`. So anywhere that expects a `ReflectFnMut` can also be
given a `ReflectFn`.

To reiterate, these traits aren't 100% necessary. They were added in
purely for extensibility. If we decide to split things up differently or
add new traits/types in the future, then those changes should be much
simpler to implement.

### `TypedFunction`

Because of the split into `ReflectFn` and `ReflectFnMut`, we needed a
new way to access the function type information. This PR moves that
concept over into `TypedFunction`.

Much like `Typed`, this provides a way to access a function's
`FunctionInfo`.

By splitting this trait out, it helps to ensure the other traits are
focused on a single responsibility.

### Internal Macros

The original function PR (#13152) implemented `IntoFunction` using a
macro which was passed into an `all_tuples!` macro invocation. Because
we needed the same functionality for these new traits, this PR has
copy+pasted that code for `ReflectFn`, `ReflectFnMut`, and
`TypedFunction`— albeit with some differences between them.

Originally, I was going to try and macro-ify the impls and where clauses
such that we wouldn't have to straight up duplicate a lot of this logic.
However, aside from being more complex in general, autocomplete just
does not play nice with such heavily nested macros (tried in both
RustRover and VSCode). And both of those problems told me that it just
wasn't worth it: we need to ensure the crate is easily maintainable,
even at the cost of duplicating code.

So instead, I made sure to simplify the macro code by removing all
fully-qualified syntax and cutting the where clauses down to the bare
essentials, which helps to clean up a lot of the visual noise. I also
tried my best to document the macro logic in certain areas (I may even
add a bit more) to help with maintainability for future devs.

### Documentation

Documentation for this module was a bit difficult for me. So many of
these traits and types are very interconnected. And each trait/type has
subtle differences that make documenting it in a single place, like at
the module level, difficult to do cleanly. Describing the valid
signatures is also challenging to do well.

Hopefully what I have here is okay. I think I did an okay job, but let
me know if there any thoughts on ways to improve it. We can also move
such a task to a followup PR for more focused discussion.

## Testing

You can test locally by running:

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

---

## Changelog

- Added `DynamicClosure` struct
- Added `DynamicClosureMut` struct
- Added `IntoClosure` trait
- Added `IntoClosureMut` trait
- Added `ReflectFn` trait
- Added `ReflectFnMut` trait
- Added `TypedFunction` trait
- `IntoFunction` now only works for standard Rust functions
- `IntoFunction` no longer takes a lifetime parameter
- `DynamicFunction::call` now only requires `&self`
- Removed `DynamicFunction::call_once`
- Changed the `IntoReturn::into_return` signature to include a where
clause

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

### `IntoClosure`

`IntoFunction` now only works for standard Rust functions. Calling
`IntoFunction::into_function` on a closure that captures references to
its environment (either mutable or immutable), will no longer compile.

Instead, you will need to use either `IntoClosure::into_closure` to
create a `DynamicClosure` or `IntoClosureMut::into_closure_mut` to
create a `DynamicClosureMut`, depending on your needs:

```rust
let punct = String::from("!");
let print = |value: String| {
    println!("{value}{punct}");
};

// BEFORE
let func: DynamicFunction = print.into_function();

// AFTER
let func: DynamicClosure = print.into_closure();
```

### `IntoFunction` lifetime

Additionally, `IntoFunction` no longer takes a lifetime parameter as it
always expects a `'static` lifetime. Usages will need to remove any
lifetime parameters:

```rust
// BEFORE
fn execute<'env, F: IntoFunction<'env, Marker>, Marker>(f: F) {/* ... */}

// AFTER
fn execute<F: IntoFunction<Marker>, Marker>(f: F) {/* ... */}
```

### `IntoReturn`

`IntoReturn::into_return` now has a where clause. Any manual
implementors will need to add this where clause to their implementation.
2024-07-16 03:22:43 +00:00
Patrick Walton
20c6bcdba4
Allow volumetric fog to be localized to specific, optionally voxelized, regions. (#14099)
Currently, volumetric fog is global and affects the entire scene
uniformly. This is inadequate for many use cases, such as local smoke
effects. To address this problem, this commit introduces *fog volumes*,
which are axis-aligned bounding boxes (AABBs) that specify fog
parameters inside their boundaries. Such volumes can also specify a
*density texture*, a 3D texture of voxels that specifies the density of
the fog at each point.

To create a fog volume, add a `FogVolume` component to an entity (which
is included in the new `FogVolumeBundle` convenience bundle). Like light
probes, a fog volume is conceptually a 1×1×1 cube centered on the
origin; a transform can be used to position and resize this region. Many
of the fields on the existing `VolumetricFogSettings` have migrated to
the new `FogVolume` component. `VolumetricFogSettings` on a camera is
still needed to enable volumetric fog. However, by itself
`VolumetricFogSettings` is no longer sufficient to enable volumetric
fog; a `FogVolume` must be present. Applications that wish to retain the
old global fog behavior can simply surround the scene with a large fog
volume.

By way of implementation, this commit converts the volumetric fog shader
from a full-screen shader to one applied to a mesh. The strategy is
different depending on whether the camera is inside or outside the fog
volume. If the camera is inside the fog volume, the mesh is simply a
plane scaled to the viewport, effectively falling back to a full-screen
pass. If the camera is outside the fog volume, the mesh is a cube
transformed to coincide with the boundaries of the fog volume's AABB.
Importantly, in the latter case, only the front faces of the cuboid are
rendered. Instead of treating the boundaries of the fog as a sphere
centered on the camera position, as we did prior to this patch, we
raytrace the far planes of the AABB to determine the portion of each ray
contained within the fog volume. We then raymarch in shadow map space as
usual. If a density texture is present, we modulate the fixed density
value with the trilinearly-interpolated value from that texture.

Furthermore, this patch introduces optional jitter to fog volumes,
intended for use with TAA. This modifies the position of the ray from
frame to frame using interleaved gradient noise, in order to reduce
aliasing artifacts. Many implementations of volumetric fog in games use
this technique. Note that this patch makes no attempt to write a motion
vector; this is because when a view ray intersects multiple voxels
there's no single direction of motion. Consequently, fog volumes can
have ghosting artifacts, but because fog is "ghostly" by its nature,
these artifacts are less objectionable than they would be for opaque
objects.

A new example, `fog_volumes`, has been added. It demonstrates a single
fog volume containing a voxelized representation of the Stanford bunny.
The existing `volumetric_fog` example has been updated to use the new
local volumetrics API.

## Changelog

### Added

* Local `FogVolume`s are now supported, to localize fog to specific
regions. They can optionally have 3D density voxel textures for precise
control over the distribution of the fog.

### Changed

* `VolumetricFogSettings` on a camera no longer enables volumetric fog;
instead, it simply enables the processing of `FogVolume`s within the
scene.

## Migration Guide

* A `FogVolume` is now necessary in order to enable volumetric fog, in
addition to `VolumetricFogSettings` on the camera. Existing uses of
volumetric fog can be migrated by placing a large `FogVolume`
surrounding the scene.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-07-16 03:14:12 +00:00
Joseph
ee15be8549
Make Tasks functional on WASM (#13889)
# Objective

Right not bevy's task pool abstraction is kind of useless on wasm, since
it returns a `FakeTask` which can't be interacted with. This is only
good for fire-and-forget it tasks, and isn't even that useful since it's
just a thin wrapper around `wasm-bindgen-futures::spawn_local`

## Solution

Add a simple `Task<T>` handler type to wasm targets that allow waiting
for a task's output or periodically checking for its completion. This PR
aims to give the wasm version of these tasks feature parity with the
native, multi-threaded version of the task

## Testing

- Did you test these changes? *Not yet*

---------

Co-authored-by: Periwink <charlesbour@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-07-16 01:15:03 +00:00
BD103
c3057d4353
plugin_group! macro (adopted) (#14339)
# Objective

- Adopted from #11460.
- Closes #7332.
- The documentation for `DefaultPlugins` and `MinimalPlugins` frequently
goes out of date because it is not .

## Solution

- Create a macro, `plugin_group!`, to automatically create
`PluginGroup`s and document them.

## Testing

- Run `cargo-expand` on the generated code for `DefaultPlugins` and
`MinimalPlugins`.
- Try creating a custom plugin group with the macro.

---

## Showcase

- You can now define custom `PluginGroup`s using the `plugin_group!`
macro.

```rust
plugin_group! {
    /// My really cool plugic group!
    pub struct MyPluginGroup {
        physics:::PhysicsPlugin,
        rendering:::RenderingPlugin,
        ui:::UiPlugin,
    }
}
```

<details>
  <summary>Expanded output</summary>

```rust
/// My really cool plugic group!
///
/// - [`PhysicsPlugin`](physics::PhysicsPlugin)
/// - [`RenderingPlugin`](rendering::RenderingPlugin)
/// - [`UiPlugin`](ui::UiPlugin)
pub struct MyPluginGroup;
impl ::bevy_app::PluginGroup for MyPluginGroup {
    fn build(self) -> ::bevy_app::PluginGroupBuilder {
        let mut group = ::bevy_app::PluginGroupBuilder::start::<Self>();
        {
            const _: () = {
                const fn check_default<T: Default>() {}
                check_default::<physics::PhysicsPlugin>();
            };
            group = group.add(<physics::PhysicsPlugin>::default());
        }
        {
            const _: () = {
                const fn check_default<T: Default>() {}
                check_default::<rendering::RenderingPlugin>();
            };
            group = group.add(<rendering::RenderingPlugin>::default());
        }
        {
            const _: () = {
                const fn check_default<T: Default>() {}
                check_default::<ui::UiPlugin>();
            };
            group = group.add(<ui::UiPlugin>::default());
        }
        group
    }
}
```

</details>

---------

Co-authored-by: Doonv <58695417+doonv@users.noreply.github.com>
Co-authored-by: Mateusz Wachowiak <mateusz_wachowiak@outlook.com>
2024-07-16 01:14:33 +00:00
Lura
9a1a84dd22
Fix error/typo in SMAA shader (#14338)
# Objective

- Actually use the value assigned to `d_xz`, like in [the original SMAA
implementation](https://github.com/iryoku/smaa/blob/master/SMAA.hlsl#L960).
This not already being the case was likely a mistake when converting
from HLSL to WGSL

## Solution

- Use `d_xz.x` and `d_xz.y` instead of `d.x` and `d.z`

## Testing

- Quickly tested on Windows 11, `x86_64-pc-windows-gnu` `1.79.0` with
the latest NVIDIA drivers. App runs with SMAA enabled and everything
seems to work as intended
- I didn't observe any major visual difference between this and the
previous version, though this should be more correct as it matches the
original SMAA implementation
2024-07-15 23:40:39 +00:00
Jonathan Chan Kwan Yin
e66cd484a7
Add insert_by_id and try_insert_by_id to EntityCommands (#14283)
# Objective

- Allow queuing insertion of dynamic components to an existing entity

## Solution

- Add `insert_by_id<T: Send + 'static>(commands: &mut EntityCommands,
component_id: ComponentId, value: T)` and the `try_insert_by_id`
counterpart

## Testing

TODO

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

## Alternatives

This PR is not feature-complete for dynamic components. In particular,
it
- only supports one component
- only supports adding components with a known, sized type

These were not implemented because doing so would require enhancing
`CommandQueue` to support pushing unsized commands (or equivalently,
pushing commands with a buffer of data). Even so, the cost would not be
transparent compared to the implementation in this PR, which simply
captures the `ComponentId` and `value: T` into the command closure and
can be easily memcpy'ed to the stack during execution. For example, to
efficiently pass `&[ComponentId]` from the caller to the world, we would
need to:

1. Update `CommandQueue.bytes` from `Vec<MaybeUninit<u8>>` to
`Vec<MaybeUninit<usize>>` so that it has the same alignment as
`ComponentId` (which probably needs to be made `#[repr(transparent)]`
too)
2. After pushing the Command metadata, push padding bytes until the vec
len is a multiple of `size_of::<usize>()`
3. Store `components.len()` in the data
4. memcpy the user-provided `&[ComponentId]` to `CommandQueue.bytes`
5. During execution, round up the data pointer behind the `Command` to
skip padding, then cast the pointer and consume it as a `&[ComponentId]`

The effort here seems unnecessarily high, unless someone else has such a
requirement. At least for the use case I am working with, I only need a
single known type, and if we need multiple components, we could always
enhance this function to accept a `[ComponentId; N]`.

I recommend enhancing the `Bundle` API in the long term to achieve this
goal more elegantly.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Felix Rath <felixm.rath@gmail.com>
2024-07-15 23:29:13 +00:00
BD103
5ea88895e9
Remove unused default feature from bevy_window (#14313)
# Objective

- Extracted from #14298.
- `bevy_window` has an empty `default` feature that does not enable
anything, which is equivalent to not having any default features.

## Solution

- Remove it :)
- This is technically a breaking change, but specifying `features =
["default"]` manually in `Cargo.toml` is highly discouraged, so the
impact is low.

---

## Migration Guide

`bevy_window` had an empty default feature flag that did not do
anything, so it was removed. You may have to remove any references to it
if you specified it manually.

```toml
# 0.14
[dependencies]
bevy_window = { version = "0.14", default-features = false, features = ["default"] }

# 0.15
[dependencies]
bevy_window = { version = "0.15", default-features = false }
```
2024-07-15 16:49:00 +00:00
Brezak
6522795889
Specify test group names in github summary for compile fail tests (#14330)
# Objective

The github action summary titles every compile test group as
`compile_fail_utils`.


![image](https://github.com/user-attachments/assets/9d00a113-6772-430c-8da9-bffe6a60a8f8)

## Solution

Manually specify group names for compile fail tests.

## Testing

- Wait for compile fail tests to run.
- Observe the generated summary.
2024-07-15 16:13:03 +00:00
SpecificProtagonist
d276525350
Allow non-static trigger targets (#14327)
# Objective

`TriggerTargets` can not be borrowed for use in `World::trigger_targets`

## Solution

Drop `'static` bound on `TriggerEvent`, keep it for `Command` impl.

## Testing

n/a
2024-07-15 16:10:57 +00:00
Joona Aalto
cf1b7fa4cc
Implement Bounded2d for Annulus (#14326)
# Objective

`Annulus` is missing `Bounded2d` even though the implementation is
trivial.

## Solution

Implement `Bounded2d` for `Annulus`.

## Testing

There is a basic test to verify that the produced bounding volumes are
correct.
2024-07-15 16:08:35 +00:00
Joona Aalto
36b521d069
Improve isometry docs (#14318)
# Objective

Fixes #14308.

#14269 added the `Isometry2d` and `Isometry3d` types, but they don't
have usage examples or much documentation on what the types actually
represent or what they may be useful for.

In addition, their module is public and the types are not re-exported at
the crate root, unlike all the other core math types like Glam's types,
direction types, and `Rot2`.

## Solution

Improve the documentation of `Isometry2d` and `Isometry3d`, explaining
what they represent and can be useful for, along with doc examples on
common high-level usage. I also made the way the types are exported
consistent with other core math types.

This does add some duplication, but I personally think having good docs
for this is valuable, and people are also less likely to look at the
module-level docs than type-level docs.
2024-07-15 16:05:33 +00:00
Torstein Grindvik
ee0a85766d
Clearer spatial bundle pub const docs (#14293)
# Objective

The docs on SpatialBundle's pub const constructors mention that one is
"visible" when it's actually inherited, which afaik means it's
conditional on its parent's visibility.

I feel it's more correct like this.

_Also I'm seeing how making a PR from github.dev works hopefully nothing
weird happens_
2024-07-15 16:03:09 +00:00
BD103
b6f61b3ac6
Fix bevy_window failing with serialize feature (#14298)
# Objective

- [`flag-frenzy`](https://github.com/TheBevyFlock/flag-frenzy) found an
issue where `bevy_window` would fail to build when its `serialize`
feature is enabled.
- See
[here](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/9924187577/job/27415224405)
for the specific log.

## Solution

- Turns out it was failing because the `bevy_ecs/serialize` feature was
not enabled. This error can be fixed by adding the flag as a dependency.

## Testing

```bash
cargo check -p bevy_window -F serialize
# Or if you're very cool...
flag-frenzy --manifest-path path/to/bevy/Cargo.toml --config config -p bevy_window
```
2024-07-15 16:00:49 +00:00
masonk
d2bf052515
Clarify GlobalTransform::transform_point (#14292)
The existing doc comment for GlobalTransform::transform_point is
unclear, or, arguably, incorrect.
https://github.com/bevyengine/bevy/discussions/8501 also mentions this.

Additionally, a user reading the doc for transform_point might be
looking for one of the three other transforms that I mentioned in this
doc comment.

---------

Co-authored-by: Mason Kramer <mason@masonkramer.net>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2024-07-15 15:59:29 +00:00
Ben Frankel
7cb97852a5
Remove second generic from .add_before, .add_after (#14285)
# Objective

```rust
// Currently:
builder.add_after::<FooPlugin, _>(BarPlugin);
// After this PR:
builder.add_after::<FooPlugin>(BarPlugin);
```

This removes some weirdness and better parallels the rest of the
`PluginGroupBuilder` API.

## Solution

Define a helper method `type_id_of_val` to use in `.add_before` and
`.add_after` instead of `TypeId::of::<T>` (which requires the plugin
type to be nameable, preventing `impl Plugin` from being used).

## Testing

Ran `cargo run -p ci lints` successfully.

## Migration Guide

Removed second generic from `PluginGroupBuilder` methods: `add_before`
and `add_after`.

```rust
// Before:
DefaultPlugins
    .build()
    .add_before::<WindowPlugin, _>(FooPlugin)
    .add_after::<WindowPlugin, _>(BarPlugin)

// After:
DefaultPlugins
    .build()
    .add_before::<WindowPlugin>(FooPlugin)
    .add_after::<WindowPlugin>(BarPlugin)
```

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-07-15 15:58:14 +00:00
Sou1gh0st
65aae92127
Add support for skybox transformation (#14267)
# Objective

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

## Solution

- Add a view space transformation for the skybox

## Testing

- I have tested the newly added `transform` field using the `skybox`
example.
```
diff --git a/examples/3d/skybox.rs b/examples/3d/skybox.rs
index beaf5b268..d16cbe988 100644
--- a/examples/3d/skybox.rs
+++ b/examples/3d/skybox.rs
@@ -81,6 +81,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
         Skybox {
             image: skybox_handle.clone(),
             brightness: 1000.0,
+            rotation: Quat::from_rotation_x(PI * -0.5),
         },
     ));
```
<img width="1280" alt="image"
src="https://github.com/bevyengine/bevy/assets/6300263/1230a608-58ea-492d-a811-90c54c3b43ef">


## Migration Guide
- Since we have added a new filed to the Skybox struct, users will need
to include `..Default::default()` or some rotation value in their
initialization code.
2024-07-15 15:53:20 +00:00
Alix Bott
a79df7b124
Fix overflow in RenderLayers::iter_layers (#14264)
# Objective

- Fixes overflow when calling `RenderLayers::iter_layers` on layers of
the form `k * 64 - 1`
- Causes a panic in debug mode, and an infinite iterator in release mode

## Solution

- Use `u64::checked_shr` instead of `>>=`

## Testing

- Added a test case for this: `render_layer_iter_no_overflow`
2024-07-15 15:50:36 +00:00
SpecificProtagonist
ab255aefc6
Implement FromIterator/IntoIterator for dynamic types (#14250)
# Objective

Implement FromIterator/IntoIterator for dynamic types where missing

Note:
- can't impl `IntoIterator` for `&Array` & co because of orphan rules
- `into_iter().collect()` is a no-op for `Vec`s because of
specialization

---

## Migration Guide

- Change `DynamicArray::from_vec` to `DynamicArray::from_iter`
2024-07-15 15:38:11 +00:00
Ben Frankel
18abe2186c
Fix inaccurate docs for Commands::spawn_empty (#14234)
# Objective

`Commands::spawn_empty` docs say that it queues a command to spawn an
entity, but it doesn't. It immediately reserves an `Entity` to be
spawned at the next flush point, which is possible because
`Entities::reserve_entity()` takes `&self` and no components are added
yet.

## Solution

Fix docs.
2024-07-15 15:32:20 +00:00
UkoeHB
c3320627ac
Clean up UiSystem system sets (#14228)
# Objective

- All UI systems should be in system sets that are easy to order around
in user code.

## Solution

- Add `UiSystem::Prepare` and `UiSystem::PostLayout` system sets to
capture floater systems.
- Adjust how UI systems are scheduled to align with the new sets.

This is *mostly* a pure refactor without any behavior/scheduling
changes. See migration guide.

## Testing

- Not tested, correctness by inspection.

---

## Migration Guide

`UiSystem` system set adjustments.
- The `UiSystem::Outline` system set is now strictly ordered after
`UiSystem::Layout`, rather than overlapping it.
2024-07-15 15:27:38 +00:00
Pixelstorm
0f7c548a4a
Component Lifecycle Hook & Observer Trigger for replaced values (#14212)
# Objective

Fixes #14202

## Solution

Add `on_replaced` component hook and `OnReplaced` observer trigger

## Testing

- Did you test these changes? If so, how?
  - Updated & added unit tests

---

## Changelog

- Added new `on_replaced` component hook and `OnReplaced` observer
trigger for performing cleanup on component values when they are
overwritten with `.insert()`
2024-07-15 15:24:15 +00:00
GT
e79f91fc45
Rename bevy_core::name::DebugName to bevy_core::name::NameOrEntity (#14211)
# Objective

- Fixes #14039

## Solution

- Rename.

## Testing

- CI

---

## Migration Guide

- Rename usages of `bevy_core::name::DebugName` to
`bevy_core::name::NameOrEntity`
2024-07-15 15:21:41 +00:00
MiniaczQ
bc72cedfe3
Make initial StateTransition run before PreStartup (#14208)
# Objective

- Fixes #14206 

## Solution

- Run initial `StateTransition` as a startup schedule before
`PreStartup`, instead of running it inside `Startup` as an exclusive
system.

Related discord discussion:

https://discord.com/channels/691052431525675048/692572690833473578/1259543775668207678

## Testing

Reproduction now works correctly:

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

#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
enum AppState {
    #[default]
    Menu,
    InGame,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_state::<AppState>()
        .add_systems(Startup, setup)
        .add_systems(OnEnter(AppState::Menu), enter_menu_state)
        .run();
}

fn setup(mut next_state: ResMut<NextState<AppState>>) {
    next_state.set(AppState::Menu);
}

fn enter_menu_state() {
    println!("Entered menu state");
}
```


![image](https://github.com/bevyengine/bevy/assets/13040204/96d7a533-c439-4c0b-8f15-49f620903ce1)


---

## Changelog

- Initial `StateTransition` runs before `PreStartup` instead of inside
`Startup`.
2024-07-15 15:08:54 +00:00
JMS55
6e8d43a037
Faster MeshletMesh deserialization (#14193)
# Objective
- Using bincode to deserialize binary into a MeshletMesh is expensive
(~77ms for a 5mb file).

## Solution
- Write a custom deserializer using bytemuck's Pod types and slice
casting.
  - Total asset load time has gone from ~102ms to ~12ms.
- Change some types I never meant to be public to private and other misc
cleanup.

## Testing
- Ran the meshlet example and added timing spans to the asset loader.

---

## Changelog
- Improved `MeshletMesh` loading speed
- The `MeshletMesh` disk format has changed, and
`MESHLET_MESH_ASSET_VERSION` has been bumped
- `MeshletMesh` fields are now private
- Renamed `MeshletMeshSaverLoad` to `MeshletMeshSaverLoader`
- The `Meshlet`, `MeshletBoundingSpheres`, and `MeshletBoundingSphere`
types are now private
- Removed `MeshletMeshSaveOrLoadError::SerializationOrDeserialization`
- Added `MeshletMeshSaveOrLoadError::WrongFileType`

## Migration Guide
- Regenerate your `MeshletMesh` assets, as the disk format has changed,
and `MESHLET_MESH_ASSET_VERSION` has been bumped
- `MeshletMesh` fields are now private
- `MeshletMeshSaverLoad` is now named `MeshletMeshSaverLoader`
- The `Meshlet`, `MeshletBoundingSpheres`, and `MeshletBoundingSphere`
types are now private
- `MeshletMeshSaveOrLoadError::SerializationOrDeserialization` has been
removed
- Added `MeshletMeshSaveOrLoadError::WrongFileType`, match on this
variant if you match on `MeshletMeshSaveOrLoadError`
2024-07-15 15:06:02 +00:00
ickk
3dd4953b97
bevy_math: faster sphere sampling (#14168)
Uses fewer transcendental functions than the existing approach
2024-07-15 15:01:18 +00:00
Periwink
da997dd0ea
Allow observer systems to have outputs (#14159)
# Objective

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

## Solution

- Update the ObserverSystem traits to accept an `Out` parameter

## Testing

- Added a test where an observer system has a non-empty output which is
piped into another system

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-15 14:59:12 +00:00
daxpedda
e7271709b2
Expose Winit's KeyEvent::repeat in KeyboardInput (#14161)
# Objective

I would like to know if an event was emitted because of "key repeats" or
not.
Winit already exposes this information, but it isn't sent along by Bevy,
which this PR intends to address.

## Solution

Expose
[`winit::event::KeyEvent::repeat`](https://docs.rs/winit/0.30.3/winit/event/struct.KeyEvent.html#structfield.repeat)
in
[`bevy::input:⌨️:KeyboardInput`](https://docs.rs/bevy/0.14.0/bevy/input/keyboard/struct.KeyboardInput.html).

## Testing

Just hold any regular key down and only the first event should have
`KeyboardInput::repeat` set to `false`. Most OSs have "key repeat"
enabled by default.

---

## Changelog

- Added `KeyboardInput::repeat` signifying if this event was sent in
response to a "key repeat" event or not.
2024-07-15 14:52:33 +00:00
Dmytro Banin
bf53cf30c7
Align Scene::write_to_world_with to match DynamicScene::write_to_world_with (#13855)
# Objective

Fixes a regression in [previously merged but then reverted
pr](https://github.com/bevyengine/bevy/pull/13714) that aligns
lower-level `Scene` API with that in `DynamicScene`. Please look at the
original pr for more details.

The problem was `spawn_sync_internal` is used in `spawn_queued_scenes`.
Since instance creation was moved up a level we need to make sure we add
a specific instance to `SceneSpawner::spawned_instances` when using
`spawn_sync_internal` (just like we do for `DynamicScene`).

Please look at the last commit when reviewing.

## Testing

`alien_cake_addict` and `deferred_rendering` examples look as expected.

## Changelog

Changed `Scene::write_to_world_with` to take `entity_map` as an argument
and no longer return an `InstanceInfo`

## Migration Guide

`Scene::write_to_world_with` no longer returns an `InstanceInfo`. 

Before
```rust
scene.write_to_world_with(world, &registry)
```
After
```rust
let mut entity_map = EntityHashMap::default();
scene.write_to_world_with(world, &mut entity_map, &registry)
```
2024-07-15 14:04:09 +00:00
Jer
4340f7b7c6
add debug logging to ascertain the base path the asset server is using (#13820)
# Objective
Explicitly and exactly know what of the environment variables (if any)
are being used/not-used/found-not-found by the
`bevy_asset::io::file::get_base_path()`.

- Describe the objective or issue this PR addresses:
In a sufficiently complex project, with enough crates and such it _can_
be hard to know what the Asset Server is using as, what in the bevy
parlance is its 'base path', this change seems to be the lowest effort
to discovering that.

## Solution

- Added `debug!` logging to the `FileAssetReader::new()` call.

## Testing
See output by making a project and trying something like
`RUST_LOG=bevy_asset::io::file=debug cargo run`
- Ran Bevy's tests.

- How can other people (reviewers) test your changes?: Intentionally
mess with your `env` variables (BEVY_ASSET_ROOT and CARGO_MANIFEST_DIR,
scatter assets about and attempt to (without this change) locate where
it's going wrong.

- Is there anything specific they need to know?: I encountered this
issue in a rather large workspace with many many crates with multiple
nested asset directories.

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test? Linux.

---
2024-07-15 14:00:43 +00:00
Patrick Walton
fcda67e894
Start a built-in postprocessing stack, and implement chromatic aberration in it. (#13695)
This commit creates a new built-in postprocessing shader that's designed
to hold miscellaneous postprocessing effects, and starts it off with
chromatic aberration. Possible future effects include vignette, film
grain, and lens distortion.

[Chromatic aberration] is a common postprocessing effect that simulates
lenses that fail to focus all colors of light to a single point. It's
often used for impact effects and/or horror games. This patch uses the
technique from *Inside* ([Gjøl & Svendsen 2016]), which allows the
developer to customize the particular color pattern to achieve different
effects. Unity HDRP uses the same technique, while Unreal has a
hard-wired fixed color pattern.

A new example, `post_processing`, has been added, in order to
demonstrate the technique. The existing `post_processing` shader has
been renamed to `custom_post_processing`, for clarity.

[Chromatic aberration]:
https://en.wikipedia.org/wiki/Chromatic_aberration

[Gjøl & Svendsen 2016]:
https://github.com/playdeadgames/publications/blob/master/INSIDE/rendering_inside_gdc2016.pdf

![Screenshot 2024-06-04
180304](https://github.com/bevyengine/bevy/assets/157897/3631c64f-a615-44fe-91ca-7f04df0a54b2)

![Screenshot 2024-06-04
180743](https://github.com/bevyengine/bevy/assets/157897/ee055cbf-4314-49c5-8bfa-8d8a17bd52bb)

## Changelog

### Added

* Chromatic aberration is now available as a built-in postprocessing
effect. To use it, add `ChromaticAberration` to your camera.
2024-07-15 13:59:02 +00:00
Miles Silberling-Cook
ed2b8e0f35
Minimal Bubbling Observers (#13991)
# Objective

Add basic bubbling to observers, modeled off `bevy_eventlistener`.

## Solution

- Introduce a new `Traversal` trait for components which point to other
entities.
- Provide a default `TraverseNone: Traversal` component which cannot be
constructed.
- Implement `Traversal` for `Parent`.
- The `Event` trait now has an associated `Traversal` which defaults to
`TraverseNone`.
- Added a field `bubbling: &mut bool` to `Trigger` which can be used to
instruct the runner to bubble the event to the entity specified by the
event's traversal type.
- Added an associated constant `SHOULD_BUBBLE` to `Event` which
configures the default bubbling state.
- Added logic to wire this all up correctly.

Introducing the new associated information directly on `Event` (instead
of a new `BubblingEvent` trait) lets us dispatch both bubbling and
non-bubbling events through the same api.

## Testing

I have added several unit tests to cover the common bugs I identified
during development. Running the unit tests should be enough to validate
correctness. The changes effect unsafe portions of the code, but should
not change any of the safety assertions.

## Changelog

Observers can now bubble up the entity hierarchy! To create a bubbling
event, change your `Derive(Event)` to something like the following:

```rust
#[derive(Component)]
struct MyEvent;

impl Event for MyEvent {
    type Traverse = Parent; // This event will propagate up from child to parent.
    const AUTO_PROPAGATE: bool = true; // This event will propagate by default.
}
```

You can dispatch a bubbling event using the normal
`world.trigger_targets(MyEvent, entity)`.

Halting an event mid-bubble can be done using
`trigger.propagate(false)`. Events with `AUTO_PROPAGATE = false` will
not propagate by default, but you can enable it using
`trigger.propagate(true)`.

If there are multiple observers attached to a target, they will all be
triggered by bubbling. They all share a bubbling state, which can be
accessed mutably using `trigger.propagation_mut()` (`trigger.propagate`
is just sugar for this).

You can choose to implement `Traversal` for your own types, if you want
to bubble along a different structure than provided by `bevy_hierarchy`.
Implementers must be careful never to produce loops, because this will
cause bevy to hang.

## Migration Guide
+ Manual implementations of `Event` should add associated type `Traverse
= TraverseNone` and associated constant `AUTO_PROPAGATE = false`;
+ `Trigger::new` has new field `propagation: &mut Propagation` which
provides the bubbling state.
+ `ObserverRunner` now takes the same `&mut Propagation` as a final
parameter.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-07-15 13:39:41 +00:00
Gino Valente
aa241672e1
bevy_reflect: Nested TypeInfo getters (#13321)
# Objective

Right now, `TypeInfo` can be accessed directly from a type using either
`Typed::type_info` or `Reflect::get_represented_type_info`.

However, once that `TypeInfo` is accessed, any nested types must be
accessed via the `TypeRegistry`.

```rust
#[derive(Reflect)]
struct Foo {
  bar: usize
}

let registry = TypeRegistry::default();

let TypeInfo::Struct(type_info) = Foo::type_info() else {
  panic!("expected struct info");
};

let field = type_info.field("bar").unwrap();

let field_info = registry.get_type_info(field.type_id()).unwrap();
assert!(field_info.is::<usize>());;
```

## Solution

Enable nested types within a `TypeInfo` to be retrieved directly.

```rust
#[derive(Reflect)]
struct Foo {
  bar: usize
}

let TypeInfo::Struct(type_info) = Foo::type_info() else {
  panic!("expected struct info");
};

let field = type_info.field("bar").unwrap();

let field_info = field.type_info().unwrap();
assert!(field_info.is::<usize>());;
```

The particular implementation was chosen for two reasons.

Firstly, we can't just store `TypeInfo` inside another `TypeInfo`
directly. This is because some types are recursive and would result in a
deadlock when trying to create the `TypeInfo` (i.e. it has to create the
`TypeInfo` before it can use it, but it also needs the `TypeInfo` before
it can create it). Therefore, we must instead store the function so it
can be retrieved lazily.

I had considered also using a `OnceLock` or something to lazily cache
the info, but I figured we can look into optimizations later. The API
should remain the same with or without the `OnceLock`.

Secondly, a new wrapper trait had to be introduced: `MaybeTyped`. Like
`RegisterForReflection`, this trait is `#[doc(hidden)]` and only exists
so that we can properly handle dynamic type fields without requiring
them to implement `Typed`. We don't want dynamic types to implement
`Typed` due to the fact that it would make the return type
`Option<&'static TypeInfo>` for all types even though only the dynamic
types ever need to return `None` (see #6971 for details).

Users should never have to interact with this trait as it has a blanket
impl for all `Typed` types. And `Typed` is automatically implemented
when deriving `Reflect` (as it is required).

The one downside is we do need to return `Option<&'static TypeInfo>`
from all these new methods so that we can handle the dynamic cases. If
we didn't have to, we'd be able to get rid of the `Option` entirely. But
I think that's an okay tradeoff for this one part of the API, and keeps
the other APIs intact.

## Testing

This PR contains tests to verify everything works as expected. You can
test locally by running:

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

---

## Changelog

### Public Changes

- Added `ArrayInfo::item_info` method
- Added `NamedField::type_info` method
- Added `UnnamedField::type_info` method
- Added `ListInfo::item_info` method
- Added `MapInfo::key_info` method
- Added `MapInfo::value_info` method
- All active fields now have a `Typed` bound (remember that this is
automatically satisfied for all types that derive `Reflect`)

### Internal Changes

- Added `MaybeTyped` trait

## Migration Guide

All active fields for reflected types (including lists, maps, tuples,
etc.), must implement `Typed`. For the majority of users this won't have
any visible impact.

However, users implementing `Reflect` manually may need to update their
types to implement `Typed` if they weren't already.

Additionally, custom dynamic types will need to implement the new hidden
`MaybeTyped` trait.
2024-07-15 00:40:07 +00:00
IceSentry
8e67aef96a
Register VisibleMeshEntities (#14320)
# Objective

- A recent PR added this type but never registered it which breaks
loading some gltf

## Solution

- Register the type
2024-07-15 00:06:43 +00:00
Gino Valente
e512cb602c
bevy_reflect: TypeInfo casting methods (#13320)
# Objective

There are times when we might know the type of a `TypeInfo` ahead of
time. Or we may have already checked it one way or another.

In such cases, it's a bit cumbersome to have to pattern match every time
we want to access the nested info:

```rust
if let TypeInfo::List(info) = <Vec<i32>>::type_info() {
  // ...
} else {
  panic!("expected list info");
}
```

Ideally, there would be a way to simply perform the cast down to
`ListInfo` since we already know it will succeed.

Or even if we don't, perhaps we just want a cleaner way of exiting a
function early (i.e. with the `?` operator).

## Solution

Taking a bit from
[`mirror-mirror`](https://docs.rs/mirror-mirror/latest/mirror_mirror/struct.TypeDescriptor.html#implementations),
`TypeInfo` now has methods for attempting a cast into the variant's info
type.

```rust
let info = <Vec<i32>>::type_info().as_list().unwrap();
// ...
```

These new conversion methods return a `Result` where the error type is a
new `TypeInfoError` enum.

A `Result` was chosen as the return type over `Option` because if we do
choose to `unwrap` it, the error message will give us some indication of
what went wrong. In other words, it can truly replace those instances
where we were panicking in the `else` case.

### Open Questions

1. Should the error types instead be a struct? I chose an enum for
future-proofing, but right now it only has one error state.
Alternatively, we could make it a reflect-wide casting error so it could
be used for similar methods on `ReflectRef` and friends.
2. I was going to do it in a separate PR but should I just go ahead and
add similar methods to `ReflectRef`, `ReflectMut`, and `ReflectOwned`? 🤔
3. Should we name these `try_as_***` instead of `as_***` since they
return a `Result`?

## Testing

You can test locally by running:

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

---

## Changelog

### Added

- `TypeInfoError` enum
- `TypeInfo::kind` method
- `TypeInfo::as_struct` method
- `TypeInfo::as_tuple_struct` method
- `TypeInfo::as_tuple` method
- `TypeInfo::as_list` method
- `TypeInfo::as_array` method
- `TypeInfo::as_map` method
- `TypeInfo::as_enum` method
- `TypeInfo::as_value` method
- `VariantInfoError` enum
- `VariantInfo::variant_type` method
- `VariantInfo::as_unit_variant` method
- `VariantInfo::as_tuple_variant` method
- `VariantInfo::as_struct_variant` method
2024-07-14 20:10:31 +00:00
Joona Aalto
9f376df2d5
Add inverse_mul and inverse_transform_point for isometries (#14311)
# Objective

The isometry types added in #14269 support transforming other isometries
and points, as well as computing the inverse of an isometry using
`inverse`.

However, transformations like `iso1.inverse() * iso2` and `iso.inverse()
* point` can be optimized for single-shot cases using custom methods
that avoid an extra rotation operation.

## Solution

Add `inverse_mul` and `inverse_transform_point` for `Isometry2d` and
`Isometry3d`. Note that these methods are only faster when the isometry
can't be reused for multiple transformations.

## Testing

All of the methods have a test, similarly to the existing transformation
operations.
2024-07-14 19:53:40 +00:00
Joona Aalto
22b65b7256
Add Isometry2d::from_xy and Isometry3d::from_xyz (#14312)
# Objective

Creating isometry types with just a translation is a bit more verbose
than it needs to be for cases where you don't have an existing vector to
pass in.

```rust
let iso = Isometry3d::from_translation(Vec3::new(2.0, 1.0, -1.0));
```

This could be made more ergonomic with a method similar to
`Dir2::from_xy`, `Dir3::from_xyz`, and `Transform::from_xyz`:

```rust
let iso = Isometry3d::from_xyz(2.0, 1.0, -1.0);
```

## Solution

Add `Isometry2d::from_xy` and `Isometry3d::from_xyz`.
2024-07-14 19:53:30 +00:00
re0312
3b23aa0864
Fix prepass batch (#13943)
# Objective

- After #11804 , The queue_prepass_material_meshes function is now
executed in parallel with other queue_* systems. This optimization
introduced a potential issue where mesh_instance.should_batch() could
return false in queue_prepass_material_meshes due to an unset
material_bind_group_id.
2024-07-14 19:35:36 +00:00
re0312
36c6f29832
Lighting Should Only hold Vec<Entity> instead of TypeId<Vec<Entity>> (#14073)
# Objective
- After #13894, I noticed the performance of `many_lights `dropped from
120+ to 60+. I reviewed the PR but couldn't identify any mistakes. After
profiling, I discovered that `Hashmap::Clone `was very slow when its not
empty, causing `extract_light` to increase from 3ms to 8ms.
- Lighting only checks visibility for 3D Meshes. We don't need to
maintain a TypeIdMap for this, as it not only impacts performance
negatively but also reduces ergonomics.

## Solution

- use VisibleMeshEntities for lighint visibility checking.


## Performance
cargo run --release --example many_lights  --features bevy/trace_tracy 
name="bevy_pbr::light::check_point_light_mesh_visibility"}

![image](https://github.com/bevyengine/bevy/assets/45868716/8bad061a-f936-45a0-9bb9-4fbdaceec08b)

system{name="bevy_pbr::render::light::extract_lights"}

![image](https://github.com/bevyengine/bevy/assets/45868716/ca75b46c-b4ad-45d3-8c8d-66442447b753)


## Migration Guide

> now `SpotLightBundle` , `CascadesVisibleEntities `and
`CubemapVisibleEntities `use VisibleMeshEntities instead of
`VisibleEntities`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-14 17:00:54 +00:00
Matty
e13c72d8a4
Fix swapped docs for Rot2::rotation_to/from_y (#14307)
# Objective

Fixes #14301 

## Solution

Swap them so that they are no longer swapped.
2024-07-14 17:00:41 +00:00
MiniaczQ
b36b0230e6
Dirty fix for App hanging when windows are invisible on WindowsOS (#14155)
# Objective

- Fixes #14135 

## Solution

- If no windows are visible, app updates will run regardless of redraw
call result.

This a relatively dirty fix, a more robust solution is desired in the
long run:
https://github.com/bevyengine/bevy/issues/1343#issuecomment-770091684

https://discord.com/channels/691052431525675048/1253771396832821270/1258805997011730472
The solution would disconnect rendering from app updates.

## Testing

- `window_settings` now works

## Other platforms

Not a problem on Linux:
https://discord.com/channels/691052431525675048/692572690833473578/1259526650622640160
Not a problem on MacOS:
https://discord.com/channels/691052431525675048/692572690833473578/1259563986148659272
2024-07-14 16:47:28 +00:00
Periwink
17a77445e2
Add error message if states schedule missing (usually because StatesPlugin hasn't been added) (#14160)
# Objective

- Helps improve https://github.com/bevyengine/bevy/issues/14151

## Solution

- At least return an error message from the `Option::unwrap()` call when
we try to access the `StateTransition` schedule

---------

Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
2024-07-14 15:56:16 +00:00
Gino Valente
99c9218b56
bevy_reflect: Feature-gate function reflection (#14174)
# Objective

Function reflection requires a lot of macro code generation in the form
of several `all_tuples!` invocations, as well as impls generated in the
`Reflect` derive macro.

Seeing as function reflection is currently a bit more niche, it makes
sense to gate it all behind a feature.

## Solution

Add a `functions` feature to `bevy_reflect`, which can be enabled in
Bevy using the `reflect_functions` feature.

## Testing

You can test locally by running:

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

That should ensure that everything still works with the feature
disabled.

To test with the feature on, you can run:

```
cargo test --package bevy_reflect --features functions
```

---

## Changelog

- Moved function reflection behind a Cargo feature
(`bevy/reflect_functions` and `bevy_reflect/functions`)
- Add `IntoFunction` export in `bevy_reflect::prelude`

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

Function reflection is now gated behind a feature. To use function
reflection, enable the feature:
- If using `bevy_reflect` directly, enable the `functions` feature
- If using `bevy`, enable the `reflect_functions` feature
2024-07-14 15:55:31 +00:00
Matty
6c9ec88e54
Basic isometry types (#14269)
# Objective

Introduce isometry types for describing relative and absolute position
in mathematical contexts.

## Solution

For the time being, this is a very minimal implementation. This
implements the following faculties for two- and three-dimensional
isometry types:
- Identity transformations
- Creation from translations and/or rotations
- Inverses
- Multiplication (composition) of isometries with each other
- Application of isometries to points (as vectors)
- Conversion of isometries to affine transformations

There is obviously a lot more that could be added, so I erred on the
side of adding things that I knew would be useful, with the idea of
expanding this in the near future as needed.

(I also fixed some random doc problems in `bevy_math`.)

---

## Design

One point of interest here is the matter of if/when to use aligned
types. In the implementation of 3d isometries, I used `Vec3A` rather
than `Vec3` because it has no impact on size/alignment, but I'm still
not sure about that decision (although it is easily changed).

For 2d isometries — which are encoded by four floats — the idea of
shoving them into a single 128-bit buffer (`__m128` or whatever) sounds
kind of enticing, but it's more involved and would involve writing
unsafe code, so I didn't do that for now.

## Future work

- Expand the API to include shortcuts like `inverse_mul` and
`inverse_transform` for efficiency reasons.
- Include more convenience constructors and methods (e.g. `from_xy`,
`from_xyz`).
- Refactor `bevy_math::bounding` to use the isometry types.
- Add conversions to/from isometries for `Transform`/`GlobalTransform`
in `bevy_transform`.
2024-07-14 15:27:42 +00:00
Giacomo Stevanato
d7080369a7
Fix intra-doc links and make CI test them (#14076)
# Objective

- Bevy currently has lot of invalid intra-doc links, let's fix them!
- Also make CI test them, to avoid future regressions.
- Helps with #1983 (but doesn't fix it, as there could still be explicit
links to docs.rs that are broken)

## Solution

- Make `cargo r -p ci -- doc-check` check fail on warnings (could also
be changed to just some specific lints)
- Manually fix all the warnings (note that in some cases it was unclear
to me what the fix should have been, I'll try to highlight them in a
self-review)
2024-07-11 13:08:31 +00:00
Blake Bedford
2414311079
Fixed #14248 and other URL issues (#14276)
# Objective

Fixes #14248 and other URL issues.

## Solution

- Describe the solution used to achieve the objective above.
Removed the random #s in the URL. Led users to the wrong page. For
example, https://bevyengine.org/learn/errors/#b0003 takes users to
https://bevyengine.org/learn/errors/introduction, which is not the right
page. Removing the #s fixes it.

## Testing

- Did you test these changes? If so, how?
I pasted the URL into my address bar and it took me to the right place.

- Are there any parts that need more testing?
No
2024-07-11 12:01:49 +00:00
IQuick 143
291db3e755
fix: Possible NaN due to denormalised quaternions in AABB implementations for round shapes. (#14240)
# Objective

With an unlucky denormalised quaternion (or just a regular very
denormalised quaternion), it's possible to obtain NaN values for AABB's
in shapes which rely on an AABB for a disk.

## Solution

Add an additional `.max(Vec3::ZERO)` clamp to get rid of negative values
arising due to numerical errors.
Fixup some unnecessary calculations and improve variable names in
relevant code, aiming for consistency.

## Discussion

These two (nontrivial) lines of code are repeated at least 5 times,
maybe they could be their own method.
2024-07-10 16:00:19 +00:00
Matty
9af2ef740b
Make bevy_math::common_traits public (#14245)
# Objective

Fixes #14243 

## Solution

`bevy_math::common_traits` is now a public module.
2024-07-09 17:16:47 +00:00
Rob Parrett
3594c4f2f5
Fix doc list indentation (#14225)
# Objective

Fixes #14221

## Solution

Add indentation as suggested.

## Testing

Confirmed that
- This makes Clippy happy with rust beta
- Built docs visually look the same before/after
2024-07-09 01:21:54 +00:00
Bob Gardner
ec1aa48fc6
Created an EventMutator for when you want to mutate an event before reading (#13818)
# Objective

- Often in games you will want to create chains of systems that modify
some event. For example, a chain of damage systems that handle a
DamageEvent and modify the underlying value before the health system
finally consumes the event. Right now this requires either:

* Using a component added to the entity
* Consuming and refiring events

Neither is ideal when really all we want to do is read the events value,
modify it, and write it back.

## Solution

- Create an EventMutator class similar to EventReader but with ResMut<T>
and iterators that return &mut so that events can be mutated.

## Testing

- I replicated all the existing tests for EventReader to make sure
behavior was the same (I believe) and added a number of tests specific
to testing that 1) events can actually be mutated, and that 2)
EventReader sees changes from EventMutator for events it hasn't already
seen.

## Migration Guide

Users currently using `ManualEventReader` should use `EventCursor`
instead. `ManualEventReader` will be removed in Bevy 0.16. Additionally,
`Events::get_reader` has been replaced by `Events::get_cursor`.

Users currently directly accessing the `Events` resource for mutation
should move to `EventMutator` if possible.

---------

Co-authored-by: poopy <gonesbird@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-08 14:53:06 +00:00
github-actions[bot]
8df10d2713
Bump Version after Release (#14219)
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>
2024-07-08 12:54:08 +00:00
François Mockers
1ebabcfe4a
fix typo processed_dir (#14220)
# Objective

- fix typo processed_dir
- unblock #14217 

## Solution

- fix typo processed_dir
2024-07-08 11:29:40 +00:00
SpecificProtagonist
7db5dc03f1
Fix state example urls (#14209)
Doc was still pointing to old location of state examples

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-08 01:19:05 +00:00
Torstein Grindvik
70c0223112
bevy_input: allow use without bevy_reflect (#14167)
# Objective

Allow use of `bevy_input` types without needing `bevy_reflect`.

## Solution

Make `bevy_reflect` within `bevy_input` optional. It's compiled in by
default.
Turn on reflect in dependencies as well when this feature is on.

## Testing

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

I did a `cargo hack -p bevy_input --each-feature build`.

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2024-07-08 01:09:07 +00:00
Torstein Grindvik
faf3c175b8
bevy_core: make bevy_reflect optional (#14179)
# Objective

Allow use of `bevy_core` types without needing `bevy_reflect`.

## Solution

Make `bevy_reflect` within `bevy_core` optional. It's compiled in by
default.
Turn on reflect in dependencies as well when this feature is on.

## Testing

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

I did a `cargo hack -p bevy_core--each-feature build`.


Similar PR: https://github.com/bevyengine/bevy/pull/14167

Discord context starts here:
https://discord.com/channels/691052431525675048/768253008416342076/1258814534651482163

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2024-07-08 01:09:04 +00:00
Litttle_fish
2d34226043
disable gpu preprocessing on android with Adreno 730 GPU and earilier (#14176)
# Objective

Fix #14146 

## Solution

Expansion of #13323 , excluded Adreno 730 and earlier.

## Testing

Tested on android device(Adreno 730) that used to crash
2024-07-08 01:07:03 +00:00
Jan Hohenheim
df80b99e69
Optimize unnecessary normalizations for Transform::local_{xyz} (#14171)
Note that `GlobalTransform` already does it like this for `right`,
`left`, etc. so I didn't have to touch that one
2024-07-08 01:05:09 +00:00
Mike
33ea3b9f7d
use Display for entity id in log_components (#14164)
# Objective

- Cleanup a doubled `Entity` in log components

```
// Before
2024-07-05T19:54:09.082773Z  INFO bevy_ecs::system::commands: Entity Entity { index: 2, generation: 1 }: ["bevy_transform::components::transform::Transform"]

// After
2024-07-05T19:54:09.082773Z  INFO bevy_ecs::system::commands: Entity 2v1: ["bevy_transform::components::transform::Transform"]
```

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-07-08 01:03:27 +00:00
Mike
91dd7e6f0f
add entity to error message (#14163)
# Objective

- There was a new warning added about having an unstyled child in the ui
hierarchy. Debugging the new error is pretty hard without any info about
which entity is.

## Solution

- Add the entity id to the warning.

```text
// Before
2024-07-05T19:40:59.904014Z  WARN bevy_ui::layout::ui_surface: Unstyled child in a UI entity hierarchy. You are using an entity without UI components as a child of an entity with UI components, results may be unexpected.

//After
2024-07-05T19:40:59.904014Z  WARN bevy_ui::layout::ui_surface: Unstyled child `3v1` in a UI entity hierarchy. You are using an entity without UI components as a child of an entity with UI components, results may be unexpected.
```

## Changelog

- add entity id to ui surface warning
2024-07-08 01:01:47 +00:00
Brandon Reinhart
02028d16b3
impl Reflect + Clone for StateScoped (#14156)
# Objective

- Expand the flexibilty of StateScoped by adding Reflect and Clone
- This lets StateScoped be used in Clone Bundles, for example

```rust
#[derive(Component, Reflect, Clone)]
pub struct StateScoped<S: States>(pub S);
```

Notes:
- States are already Clone.
- Type registration is up to the user, but this is commonly the case
with reflected generic types.

## Testing

- Ran the examples.
2024-07-08 01:00:04 +00:00
Brian Reavis
7273ffcd78
Fix crash when an asset load failure event is processed after asset drop (#14123)
# Objective

This PR fixes a crash that happens when an asset failure event is
processed after the asset has already been dropped.

```
2024-07-03T17:12:16.847178Z ERROR bevy_asset::server: Encountered HTTP status 404 when loading asset
thread 'main' panicked at bevy/crates/bevy_asset/src/server/info.rs:593:18:
```

## Solution

- Update `process_asset_fail` to match the graceful behavior in
`process_asset_load` (it does not assume the state still exists).

---

## Changelog

- Fixed a rare crash that happens when an asset failed event is
processed after the asset has been dropped.
2024-07-08 00:58:55 +00:00
Matty
900f50d77d
Uniform mesh sampling (#14071)
# Objective

Allow random sampling from the surfaces of triangle meshes.

## Solution

This has two parts.

Firstly, rendering meshes can now yield their collections of triangles
through a method `Mesh::triangles`. This has signature
```rust
pub fn triangles(&self) -> Result<Vec<Triangle3d>, MeshTrianglesError> { //... }
```

and fails in a variety of cases — the most obvious of these is that the
mesh must have either the `TriangleList` or `TriangleStrip` topology,
and the others correspond to malformed vertex or triangle-index data.

With that in hand, we have the second piece, which is
`UniformMeshSampler`, which is a `Vec3`-valued
[distribution](https://docs.rs/rand/latest/rand/distributions/trait.Distribution.html)
that samples uniformly from collections of triangles. It caches the
triangles' distribution of areas so that after its initial setup,
sampling is allocation-free. It is constructed via
`UniformMeshSampler::try_new`, which looks like this:
```rust
pub fn try_new<T: Into<Vec<Triangle3d>>>(triangles: T) -> Result<Self, ZeroAreaMeshError> { //... }
```

It fails if the collection of triangles has zero area. 

The sum of these parts means that you can sample random points from a
mesh as follows:
```rust
let triangles = my_mesh.triangles().unwrap();
let mut rng = StdRng::seed_from_u64(8765309);
let distribution = UniformMeshSampler::try_new(triangles).unwrap();
// 10000 random points from the surface of my_mesh:
let sample_points: Vec<Vec3> = distribution.sample_iter(&mut rng).take(10000).collect();
```

## Testing

Tested by instantiating meshes and sampling as demonstrated above.

---

## Changelog

- Added `Mesh::triangles` method to get a collection of triangles from a
mesh.
- Added `UniformMeshSampler` to `bevy_math::sampling`. This is a
distribution which allows random sampling over collections of triangles
(such as those provided through meshes).

---

## Discussion

### Design decisions

The main thing here was making sure to have a good separation between
the parts of this in `bevy_render` and in `bevy_math`. Getting the
triangles from a mesh seems like a reasonable step after adding
`Triangle3d` to `bevy_math`, so I decided to make all of the random
sampling operate at that level, with the fallible conversion to
triangles doing most of the work.

Notably, the sampler could be called something else that reflects that
its input is a collection of triangles, but if/when we add other kinds
of meshes to `bevy_math` (e.g. half-edge meshes), the fact that
`try_new` takes an `impl Into<Vec<Triangle3d>>` means that those meshes
just need to satisfy that trait bound in order to work immediately with
this sampling functionality. In that case, the result would just be
something like this:
```rust
let dist = UniformMeshSampler::try_new(mesh).unwrap();
```
I think this highlights that most of the friction is really just from
extracting data from `Mesh`.

It's maybe worth mentioning also that "collection of triangles"
(`Vec<Triangle3d>`) sits downstream of any other kind of triangle mesh,
since the topology connecting the triangles has been effectively erased,
which makes an `Into<Vec<Triangle3d>>` trait bound seem all the more
natural to me.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-08 00:57:08 +00:00
re0312
db19d2ee47
Optimize ui_layout_system (#14064)
# Objective

- Currently bevy's ui layout system could takes a long time.

## Solution

- cache `default_ui_camera `entity to avoid repetitive lookup


## Performance
cargo run --release --example many_buttons --features bevy/trace_tracy  


![image](https://github.com/bevyengine/bevy/assets/45868716/f8eda0b0-343d-4379-847f-f1636c38e5ec)
2024-07-08 00:48:35 +00:00
Jenya705
330911f1bf
Component Hook functions as attributes for Component derive macro (#14005)
# Objective

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

## Solution

Added 3 new attributes to the `Component` macro.

## Testing

Added `component_hook_order_spawn_despawn_with_macro_hooks`, that makes
the same as `component_hook_order_spawn_despawn` but uses a struct, that
defines it's hooks with the `Component` macro.

---

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-08 00:46:00 +00:00
François Mockers
c994c15d5e
EmptyPathStream is only used in android/wasm32 (#14200)
# Objective

- `EmptyPathStream` is only used in android and wasm32
- This now makes rust nightly warn

## Solution

- flag the struct to only be present when needed
- also change how `MorphTargetNames` is used because that makes rust
happier?
2024-07-07 19:54:53 +00:00
daxpedda
ea2a7e5552
Send SceneInstanceReady when spawning any kind of scene (#11741)
# Objective

- Emit an event regardless of scene type (`Scene` and `DynamicScene`).
- Also send the `InstanceId` along.

Follow-up to #11002.
Fixes #2218.

## Solution

- Send `SceneInstanceReady` regardless of scene type.
- Make `SceneInstanceReady::parent` `Option`al.
- Add `SceneInstanceReady::id`.

---

## Changelog

### Changed

- `SceneInstanceReady` is now sent for `Scene` as well.
`SceneInstanceReady::parent` is an `Option` and
`SceneInstanceReady::id`, an `InstanceId`, is added to identify the
corresponding `Scene`.

## Migration Guide

- `SceneInstanceReady { parent: Entity }` is now `SceneInstanceReady {
id: InstanceId, parent: Option<Entity> }`.
2024-07-06 14:00:39 +00:00
BD103
1ceb45540b
Remove unused type parameter in Parallel::drain() (#14178)
# Objective

- `Parallel::drain()` has an unused type parameter `B` than can be
removed.
- Caught [on
Discord](https://discord.com/channels/691052431525675048/692572690833473578/1259004180560085003)
by Andrew, thanks!

## Solution

- Remove it! :)

## Testing

- `Parallel::drain()` should still function exactly the same.

---

## Changelog

- Removed unused type parameter in `Parallel::drain()`.

## Migration Guide

The type parameter of `Parallel::drain()` was unused, so it is now
removed. If you were manually specifying it, you can remove the bounds.

```rust
// 0.14
// Create a `Parallel` and give it a value.
let mut parallel: Parallel<Vec<u8>> = Parallel::default();
*parallel.borrow_local_mut() = vec![1, 2, 3];

for v in parallel.drain::<u8>() {
    // ...
}

// 0.15
let mut parallel: Parallel<Vec<u8>> = Parallel::default();
*parallel.borrow_local_mut() = vec![1, 2, 3];

// Remove the type parameter.
for v in parallel.drain() {
    // ...
}
```
2024-07-06 13:29:29 +00:00
Gino Valente
09d86bfb96
bevy_reflect: Re-enable reflection compile fail tests (#14165)
# Objective

Looks like I accidentally disabled the reflection compile fail tests in
#13152. These should be re-enabled.

## Solution

Re-enable reflection compile fail tests.

## Testing

CI should pass. You can also test locally by navigating to
`crates/bevy_reflect/compile_fail/` and running:

```
cargo test --target-dir ../../../target
```
2024-07-05 20:49:03 +00:00
NWPlayer123
c6a89c2187
impl Debug for ExtendedMaterial (#14140)
# Objective

Both `Material` and `MaterialExtension` (base and extension) can derive
Debug, so there's no reason to not allow `ExtendedMaterial` to derive it

## Solution

- Describe the solution used to achieve the objective above.
Add `Debug` to the list of derived traits

## Testing

- Did you test these changes? If so, how?
I compiled my test project on latest commit, making sure it actually
compiles
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Create an ExtendedMaterial instance, try to `println!("{:?}",
material);`

Co-authored-by: NWPlayer123 <NWPlayer123@users.noreply.github.com>
2024-07-04 23:59:48 +00:00
TotalKrill
5986d5d309
Cosmic text (#10193)
# Replace ab_glyph with the more capable cosmic-text

Fixes #7616.

Cosmic-text is a more mature text-rendering library that handles scripts
and ligatures better than ab_glyph, it can also handle system fonts
which can be implemented in bevy in the future

Rebase of https://github.com/bevyengine/bevy/pull/8808

## Changelog

Replaces text renderer ab_glyph with cosmic-text

The definition of the font size has changed with the migration to cosmic
text. The behavior is now consistent with other platforms (e.g. the
web), where the font size in pixels measures the height of the font (the
distance between the top of the highest ascender and the bottom of the
lowest descender). Font sizes in your app need to be rescaled to
approximately 1.2x smaller; for example, if you were using a font size
of 60.0, you should now use a font size of 50.0.

## Migration guide

- `Text2dBounds` has been replaced with `TextBounds`, and it now accepts
`Option`s to the bounds, instead of using `f32::INFINITY` to inidicate
lack of bounds
- Textsizes should be changed, dividing the current size with 1.2 will
result in the same size as before.
- `TextSettings` struct is removed
- Feature `subpixel_alignment` has been removed since cosmic-text
already does this automatically
- TextBundles and things rendering texts requires the `CosmicBuffer`
Component on them as well

## Suggested followups:

- TextPipeline: reconstruct byte indices for keeping track of eventual
cursors in text input
- TextPipeline: (future work) split text entities into section entities
- TextPipeline: (future work) text editing
- Support line height as an option. Unitless `1.2` is the default used
in browsers (1.2x font size).
- Support System Fonts and font families
- Example showing of animated text styles. Eg. throbbing hyperlinks

---------

Co-authored-by: tigregalis <anak.harimau@gmail.com>
Co-authored-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: sam edelsten <samedelsten1@gmail.com>
Co-authored-by: Dimchikkk <velo.app1@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2024-07-04 20:41:08 +00:00
re0312
1c2f687202
Skip extract UiImage When its texture is default (#14122)
# Objective

- After #14017 , I noticed that the drawcall increased 10x in the
`many_buttons`, causing the `UIPassNode `to increase from 1.5ms to 6ms.
This is because our UI batching is very fragile.

## Solution

- skip extract UiImage when its texture is default


## Performance 
many_buttons UiPassNode

![image](https://github.com/bevyengine/bevy/assets/45868716/9295d958-8c3f-469c-a7e0-d1e90db4dfb7)
2024-07-03 20:54:11 +00:00
re0312
2893fc3e8b
Using simple approx round up in ui_layout_system (#14079)
# Objective

- built-in `f32::round `is slow 
- splits from #14064 
## Solution

- using a simple floor instead of round

## Testing

- I am not an expert on floating-point values, but I enumerated all f32
values to test for potential errors compared to the previous function.
[rust
playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=0d8ed5604499e7bd9c61ce57d47e8c06)

three cases where the behavior differs between the new and previous
functions:
| value  |  previous | new  |  
|---|---|---|
|  [-0.5,0) |  -0 | +0  |   
|  0.49999997  | 0  |  1 |   
| +-8388609 |  8388609   | 8388610  |   

## Performance


![image](https://github.com/bevyengine/bevy/assets/45868716/1910f342-e55b-4f5c-851c-24a142d5c72e)
2024-07-03 12:48:34 +00:00
Gagnus
a47b91cccc
Added feature switch to default Standard Material's new anisotropy texture to off (#14048)
# Objective

- Standard Material is starting to run out of samplers (currently uses
13 with no additional features off, I think in 0.13 it was 12).
- This change adds a new feature switch, modelled on the other ones
which add features to Standard Material, to turn off the new anisotropy
feature by default.

## Solution

- feature + texture define

## Testing

- Anisotropy example still works fine
- Other samples work fine
- Standard Material now takes 12 samplers by default on my Mac instead
of 13

## Migration Guide

- Add feature pbr_anisotropy_texture if you are using that texture in
any standard materials.

---------

Co-authored-by: John Payne <20407779+johngpayne@users.noreply.github.com>
2024-07-02 18:02:05 +00:00
Vic
7e0d262d77
use associated type bounds in QueryManyIter and QueryIter::sort() (#14107)
# Objective

The bounds for query iterators are quite intimidating.

## Solution

With Rust 1.79, [associated type
bounds](https://github.com/rust-lang/rust/pull/122055/) stabilized,
which can simplify the bounds slightly.
2024-07-02 13:39:22 +00:00
Mincong Lu
ce5254e3ec
Added get_main_animation for AnimationTransitions (#14104)
# Objective

Added a getter for the main animation of `AnimationTransitions`.

## Solution

Added `get_main_animation` for `AnimationTransitions`.
2024-07-02 13:28:42 +00:00
Vic
1d907c5668
add missing mention of sort_unstable_by_key in QuerySortedIter docs (#14108)
# Objective

There is a missing mention of `sort_unstable_by_key` in the
`QuerySortedIter` docs.

## Solution

Add it.
2024-07-02 13:27:21 +00:00
Jan Hohenheim
7aaf440fbf
Fix push_children inserting a Children component even when no children are supplied (#14109)
# Objective

The Bevy API around manipulating hierarchies removes `Children` if the
operation results in an entity having no children. This means that
`Children` is guaranteed to hold actual children. However, the following
code unexpectedly inserts empty `Children`:

```rust
commands.entity(entity).with_children(|_| {});
```

This was discovered by @Jondolf:
https://discord.com/channels/691052431525675048/1124043933886976171/1257660865625325800

## Solution

- `with_children` is now a noop when no children were passed

## Testing

- Added a regression test
2024-07-02 13:27:02 +00:00
Joseph
5876352206
Optimize common usages of AssetReader (#14082)
# Objective

The `AssetReader` trait allows customizing the behavior of fetching
bytes for an `AssetPath`, and expects implementors to return `dyn
AsyncRead + AsyncSeek`. This gives implementors of `AssetLoader` great
flexibility to tightly integrate their asset loading behavior with the
asynchronous task system.

However, almost all implementors of `AssetLoader` don't use the async
functionality at all, and just call `AsyncReadExt::read_to_end(&mut
Vec<u8>)`. This is incredibly inefficient, as this method repeatedly
calls `poll_read` on the trait object, filling the vector 32 bytes at a
time. At my work we have assets that are hundreds of megabytes which
makes this a meaningful overhead.

## Solution

Turn the `Reader` type alias into an actual trait, with a provided
method `read_to_end`. This provided method should be more efficient than
the existing extension method, as the compiler will know the underlying
type of `Reader` when generating this function, which removes the
repeated dynamic dispatches and allows the compiler to make further
optimizations after inlining. Individual implementors are able to
override the provided implementation -- for simple asset readers that
just copy bytes from one buffer to another, this allows removing a large
amount of overhead from the provided implementation.

Now that `Reader` is an actual trait, I also improved the ergonomics for
implementing `AssetReader`. Currently, implementors are expected to box
their reader and return it as a trait object, which adds unnecessary
boilerplate to implementations. This PR changes that trait method to
return a pseudo trait alias, which allows implementors to return `impl
Reader` instead of `Box<dyn Reader>`. Now, the boilerplate for boxing
occurs in `ErasedAssetReader`.

## Testing

I made identical changes to my company's fork of bevy. Our app, which
makes heavy use of `read_to_end` for asset loading, still worked
properly after this. I am not aware if we have a more systematic way of
testing asset loading for correctness.

---

## Migration Guide

The trait method `bevy_asset::io::AssetReader::read` (and `read_meta`)
now return an opaque type instead of a boxed trait object. Implementors
of these methods should change the type signatures appropriately

```rust
impl AssetReader for MyReader {
    // Before
    async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
        let reader = // construct a reader
        Box::new(reader) as Box<Reader<'a>>
    }

    // After
    async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
        // create a reader
    }
}
```

`bevy::asset::io::Reader` is now a trait, rather than a type alias for a
trait object. Implementors of `AssetLoader::load` will need to adjust
the method signature accordingly

```rust
impl AssetLoader for MyLoader {
    async fn load<'a>(
        &'a self,
        // Before:
        reader: &'a mut bevy::asset::io::Reader,
        // After:
        reader: &'a mut dyn bevy::asset::io::Reader,
        _: &'a Self::Settings,
        load_context: &'a mut LoadContext<'_>,
    ) -> Result<Self::Asset, Self::Error> {
}
```

Additionally, implementors of `AssetReader` that return a type
implementing `futures_io::AsyncRead` and `AsyncSeek` might need to
explicitly implement `bevy::asset::io::Reader` for that type.

```rust
impl bevy::asset::io::Reader for MyAsyncReadAndSeek {}
```
2024-07-01 19:59:42 +00:00
Lee-Orr
bd7dcd3f6d
deregister events (#14083)
# Objective

Add ability to de-register events from the EventRegistry (and the
associated World).

The initial reasoning relates to retaining support for Event hot
reloading in `dexterous_developer`.

## Solution

Add a `deregister_events<T: Event>(&mut world)` method to the
`EventRegistry` struct.

## Testing

Added an automated test that verifies the event registry adds and
removes `Events<T>` from the world.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-07-01 16:18:14 +00:00
Lura
856b39d821
Apply Clippy lints regarding lazy evaluation and closures (#14015)
# Objective

- Lazily evaluate
[default](https://rust-lang.github.io/rust-clippy/master/index.html#/unwrap_or_default)~~/[or](https://rust-lang.github.io/rust-clippy/master/index.html#/or_fun_call)~~
values where it makes sense
  - ~~`unwrap_or(foo())` -> `unwrap_or_else(|| foo())`~~
  - `unwrap_or(Default::default())` -> `unwrap_or_default()`
  - etc.
- Avoid creating [redundant
closures](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure),
even for [method
calls](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure_for_method_calls)
  - `map(|something| something.into())` -> `map(Into:into)`

## Solution

- Apply Clippy lints:
-
~~[or_fun_call](https://rust-lang.github.io/rust-clippy/master/index.html#/or_fun_call)~~
-
[unwrap_or_default](https://rust-lang.github.io/rust-clippy/master/index.html#/unwrap_or_default)
-
[redundant_closure_for_method_calls](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure_for_method_calls)
([redundant
closures](https://rust-lang.github.io/rust-clippy/master/index.html#/redundant_closure)
is already enabled)

## Testing

- Tested on Windows 11 (`stable-x86_64-pc-windows-gnu`, 1.79.0)
- Bevy compiles without errors or warnings and examples seem to work as
intended
  - `cargo clippy` 
  - `cargo run -p ci -- compile` 

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-01 15:54:40 +00:00
Joseph
9055fc1d68
Clarify the difference between default render layers and none render layers (#14075)
# Objective

It's not always obvious what the default value for `RenderLayers`
represents. It is documented, but since it's an implementation of a
trait method the documentation may or may not be shown depending on the
IDE.

## Solution

Add documentation to the `none` method that explicitly calls out the
difference.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-01 14:47:13 +00:00
BD103
f7bc0a01dd
Bump accesskit to 0.16 (#14091)
Also bumps `accesskit_winit` to 0.22 and fixes one breaking change.

# Objective

- `accesskit` has been updated recently to 0.16!

## Solution

- Update `accesskit`, as well as `accesskit_winit`.
- [`accesskit`
changelog](552032c839/common/CHANGELOG.md (0160-2024-06-29))
- [`accesskit_winit`
changelog](552032c839/platforms/winit/CHANGELOG.md (0220-2024-06-29))
- Fix one breaking change where `Role::StaticText` has been renamed to
`Role::Label`.

## Testing

- The test suite should cover most things.
- It would be good to test this with an example, but I don't know how.

---

## Changelog

- Update `accesskit` to 0.16 and `accesskit_winit` to 0.22.

## Migration Guide

`accesskit`'s `Role::StaticText` variant has been renamed to
`Role::Label`.
2024-07-01 14:42:40 +00:00
BD103
b389e7baba
Bump rodio to 0.19 (#14090)
# Objective

- Though Rodio will eventually be replaced with Kira for `bevy_audio`,
we should not let it languish.

## Solution

- Bump Rodio to 0.19.
- This is [the
changelog](27f2b42406/CHANGELOG.md (version-0190-2024-06-29)).
No apparent breaking changes, only 1 feature and 1 fix.

## Testing

- Run an example that uses audio, on both native and WASM.

---

## Changelog

- Bumped Rodio to 0.19.
2024-07-01 14:41:49 +00:00
Al M
ace4eaaf0e
Merge BuildWorldChildren and BuildChildren traits. (#14052)
# Objective

The `BuildChildren` and `BuildWorldChildren` traits are mostly
identical, so I decided to try and merge them. I'm not sure of the
history, maybe they were added before GATs existed.

## Solution

- Add an associated type to `BuildChildren` which reflects the prior
differences between the `BuildChildren` and `BuildWorldChildren` traits.
- Add `ChildBuild` trait that is the bounds for
`BuildChildren::Builder`, with impls for `ChildBuilder` and
`WorldChildBuilder`.
- Remove `BuildWorldChildren` trait and replace it with an impl of
`BuildChildren` for `EntityWorldMut`.

## Testing

I ran several of the examples that use entity hierarchies, mainly UI.

---

## Changelog

n/a

## Migration Guide

n/a
2024-07-01 14:29:39 +00:00
Aztro
6dcff2bfe8
Mouse input accumulation (#14044)
# Objective

- Add the `AccumulatedMouseMotion` and `AccumulatedMouseScroll`
resources to make it simpler to track mouse motion/scroll changes
- Closes #13915

## Solution

- Created two resources, `AccumulatedMouseMotion` and
`AccumulatedMouseScroll`, and a method that tracks the `MouseMotion` and
`MouseWheel` events and accumulates their deltas every frame.
- Also modified the mouse input example to show how to use the
resources.

## Testing

- Tested the changes by modifying an existing example to use the newly
added resources, and moving/scrolling my trackpad around a ton.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-01 14:27:21 +00:00
Sarthak Singh
f607be8777
Handle Ctrl+C in the terminal properly (#14001)
# Objective

Fixes #13995.

## Solution

Override the default `Ctrl+C` handler with one that sends `AppExit`
event to every app with `TerminalCtrlCHandlerPlugin`.

## Testing

Tested by running the `3d_scene` example and hitting `Ctrl+C` in the
terminal.

---

## Changelog

Handles `Ctrl+C` in the terminal gracefully.

## Migration Guide

If you are overriding the `Ctrl+C` handler then you should call
`TerminalCtrlCHandlerPlugin::gracefully_exit` from your handler. It will
tell the app to exit.
2024-07-01 14:08:42 +00:00
Mikhail Novikov
cb4fe4ea9e
Make gLTF node children Handle instead of objects (#13707)
Part of #13681 

# Objective

gLTF Assets shouldn't be duplicated between Assets resource and node
children.

Also changed `asset_label` to be a method as [per previous PR
comment](https://github.com/bevyengine/bevy/pull/13558).

## Solution

- Made GltfNode children be Handles instead of asset copies.

## Testing

- Added tests that actually test loading and hierarchy as previous ones
unit tested only one function and that makes little sense.
- Made circular nodes an actual loading failure instead of a warning
no-op. You [_MUST NOT_ have cycles in
gLTF](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#nodes-and-hierarchy)
according to the spec.
- IMO this is a bugfix, not a breaking change. But in an extremely
unlikely event in which you relied on invalid behavior for loading gLTF
with cyclic children, you will not be able to do that anymore. You
should fix your gLTF file as it's not valid according to gLTF spec. For
it to for work someone, it had to be bevy with bevy_animation flag off.

---

## Changelog

### Changed

- `GltfNode.children` are now `Vec<Handle<GltfNode>>` instead of
`Vec<GltfNode>`
- Having children cycles between gLTF nodes in a gLTF document is now an
explicit asset loading failure.

## Migration Guide

If accessing children, use `Assets<GltfNode>` resource to get the actual
child object.

#### Before

```rs
fn gltf_print_first_node_children_system(gltf_component_query: Query<Handle<Gltf>>, gltf_assets: Res<Assets<Gltf>>, gltf_nodes: Res<Assets<GltfNode>>) {
    for gltf_handle in gltf_component_query.iter() {
        let gltf_root = gltf_assets.get(gltf_handle).unwrap();
        let first_node_handle = gltf_root.nodes.get(0).unwrap();
        let first_node = gltf_nodes.get(first_node_handle).unwrap();
        let first_child = first_node.children.get(0).unwrap();
        println!("First nodes child node name is {:?)", first_child.name);
    }
}
```

#### After

```rs
fn gltf_print_first_node_children_system(gltf_component_query: Query<Handle<Gltf>>, gltf_assets: Res<Assets<Gltf>>, gltf_nodes: Res<Assets<GltfNode>>) {
    for gltf_handle in gltf_component_query.iter() {
        let gltf_root = gltf_assets.get(gltf_handle).unwrap();
        let first_node_handle = gltf_root.nodes.get(0).unwrap();
        let first_node = gltf_nodes.get(first_node_handle).unwrap();
        let first_child_handle = first_node.children.get(0).unwrap();
        let first_child = gltf_nodes.get(first_child_handle).unwrap();
        println!("First nodes child node name is {:?)", first_child.name);
    }
}
```
2024-07-01 14:05:16 +00:00
Joseph
64bc811815
Support operations for render layers and fix equality comparisons (#13310)
# Objective

Allow combining render layers with a more-ergonomic syntax than
`RenderLayers::from_iter(a.iter().chain(b.iter()))`.

## Solution

Add the `or` operation (and corresponding `const` method) to allow
computing the union of a set of render layers. While we're here, also
added `and` and `xor` operations. Someone might find them useful

## Testing

Added a simple unit test.
2024-07-01 13:55:25 +00:00
Gino Valente
276dd04001
bevy_reflect: Function reflection (#13152)
# Objective

We're able to reflect types sooooooo... why not functions?

The goal of this PR is to make functions callable within a dynamic
context, where type information is not readily available at compile
time.

For example, if we have a function:

```rust
fn add(left: i32, right: i32) -> i32 {
  left + right
}
```

And two `Reflect` values we've already validated are `i32` types:

```rust
let left: Box<dyn Reflect> = Box::new(2_i32);
let right: Box<dyn Reflect> = Box::new(2_i32);
```

We should be able to call `add` with these values:

```rust
// ?????
let result: Box<dyn Reflect> = add.call_dynamic(left, right);
```

And ideally this wouldn't just work for functions, but methods and
closures too!

Right now, users have two options:

1. Manually parse the reflected data and call the function themselves
2. Rely on registered type data to handle the conversions for them

For a small function like `add`, this isn't too bad. But what about for
more complex functions? What about for many functions?

At worst, this process is error-prone. At best, it's simply tedious.

And this is assuming we know the function at compile time. What if we
want to accept a function dynamically and call it with our own
arguments?

It would be much nicer if `bevy_reflect` could alleviate some of the
problems here.

## Solution

Added function reflection!

This adds a `DynamicFunction` type to wrap a function dynamically. This
can be called with an `ArgList`, which is a dynamic list of
`Reflect`-containing `Arg` arguments. It returns a `FunctionResult`
which indicates whether or not the function call succeeded, returning a
`Reflect`-containing `Return` type if it did succeed.

Many functions can be converted into this `DynamicFunction` type thanks
to the `IntoFunction` trait.

Taking our previous `add` example, this might look something like
(explicit types added for readability):

```rust
fn add(left: i32, right: i32) -> i32 {
  left + right
}

let mut function: DynamicFunction = add.into_function();
let args: ArgList = ArgList::new().push_owned(2_i32).push_owned(2_i32);
let result: Return = function.call(args).unwrap();
let value: Box<dyn Reflect> = result.unwrap_owned();
assert_eq!(value.take::<i32>().unwrap(), 4);
```

And it also works on closures:

```rust
let add = |left: i32, right: i32| left + right;

let mut function: DynamicFunction = add.into_function();
let args: ArgList = ArgList::new().push_owned(2_i32).push_owned(2_i32);
let result: Return = function.call(args).unwrap();
let value: Box<dyn Reflect> = result.unwrap_owned();
assert_eq!(value.take::<i32>().unwrap(), 4);
```

As well as methods:

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

impl Foo {
  fn add(&mut self, value: i32) {
    self.0 += value;
  }
}

let mut foo = Foo(2);

let mut function: DynamicFunction = Foo::add.into_function();
let args: ArgList = ArgList::new().push_mut(&mut foo).push_owned(2_i32);
function.call(args).unwrap();
assert_eq!(foo.0, 4);
```

### Limitations

While this does cover many functions, it is far from a perfect system
and has quite a few limitations. Here are a few of the limitations when
using `IntoFunction`:

1. The lifetime of the return value is only tied to the lifetime of the
first argument (useful for methods). This means you can't have a
function like `(a: i32, b: &i32) -> &i32` without creating the
`DynamicFunction` manually.
2. Only 15 arguments are currently supported. If the first argument is a
(mutable) reference, this number increases to 16.
3. Manual implementations of `Reflect` will need to implement the new
`FromArg`, `GetOwnership`, and `IntoReturn` traits in order to be used
as arguments/return types.

And some limitations of `DynamicFunction` itself:

1. All arguments share the same lifetime, or rather, they will shrink to
the shortest lifetime.
2. Closures that capture their environment may need to have their
`DynamicFunction` dropped before accessing those variables again (there
is a `DynamicFunction::call_once` to make this a bit easier)
3. All arguments and return types must implement `Reflect`. While not a
big surprise coming from `bevy_reflect`, this implementation could
actually still work by swapping `Reflect` out with `Any`. Of course,
that makes working with the arguments and return values a bit harder.
4. Generic functions are not supported (unless they have been manually
monomorphized)

And general, reflection gotchas:

1. `&str` does not implement `Reflect`. Rather, `&'static str`
implements `Reflect` (the same is true for `&Path` and similar types).
This means that `&'static str` is considered an "owned" value for the
sake of generating arguments. Additionally, arguments and return types
containing `&str` will assume it's `&'static str`, which is almost never
the desired behavior. In these cases, the only solution (I believe) is
to use `&String` instead.

### Followup Work

This PR is the first of two PRs I intend to work on. The second PR will
aim to integrate this new function reflection system into the existing
reflection traits and `TypeInfo`. The goal would be to register and call
a reflected type's methods dynamically.

I chose not to do that in this PR since the diff is already quite large.
I also want the discussion for both PRs to be focused on their own
implementation.

Another followup I'd like to do is investigate allowing common container
types as a return type, such as `Option<&[mut] T>` and `Result<&[mut] T,
E>`. This would allow even more functions to opt into this system. I
chose to not include it in this one, though, for the same reasoning as
previously mentioned.

### Alternatives

One alternative I had considered was adding a macro to convert any
function into a reflection-based counterpart. The idea would be that a
struct that wraps the function would be created and users could specify
which arguments and return values should be `Reflect`. It could then be
called via a new `Function` trait.

I think that could still work, but it will be a fair bit more involved,
requiring some slightly more complex parsing. And it of course is a bit
more work for the user, since they need to create the type via macro
invocation.

It also makes registering these functions onto a type a bit more
complicated (depending on how it's implemented).

For now, I think this is a fairly simple, yet powerful solution that
provides the least amount of friction for users.

---

## Showcase

Bevy now adds support for storing and calling functions dynamically
using reflection!

```rust
// 1. Take a standard Rust function
fn add(left: i32, right: i32) -> i32 {
  left + right
}

// 2. Convert it into a type-erased `DynamicFunction` using the `IntoFunction` trait
let mut function: DynamicFunction = add.into_function();
// 3. Define your arguments from reflected values
let args: ArgList = ArgList::new().push_owned(2_i32).push_owned(2_i32);
// 4. Call the function with your arguments
let result: Return = function.call(args).unwrap();
// 5. Extract the return value
let value: Box<dyn Reflect> = result.unwrap_owned();
assert_eq!(value.take::<i32>().unwrap(), 4);
```

## Changelog

#### TL;DR

- Added support for function reflection
- Added a new `Function Reflection` example:
ba727898f2/examples/reflection/function_reflection.rs (L1-L157)

#### Details

Added the following items:

- `ArgError` enum
- `ArgId` enum
- `ArgInfo` struct
- `ArgList` struct
- `Arg` enum
- `DynamicFunction` struct
- `FromArg` trait (derived with `derive(Reflect)`)
- `FunctionError` enum
- `FunctionInfo` struct
- `FunctionResult` alias
- `GetOwnership` trait (derived with `derive(Reflect)`)
- `IntoFunction` trait (with blanket implementation)
- `IntoReturn` trait (derived with `derive(Reflect)`)
- `Ownership` enum
- `ReturnInfo` struct
- `Return` enum

---------

Co-authored-by: Periwink <charlesbour@gmail.com>
2024-07-01 13:49:08 +00:00
Aevyrie
a1545dd3a6
Fix compile failure in WASM without wgpu backend (#14081)
# Objective

- When no wgpu backend is selected, there should be a clear explanation.
- Fix a regression in 0.14 when not using default features. I hit this
compile failure when trying to build bevy_framepace for 0.14.0-rc.4
```
error[E0432]: unresolved import `crate::core_3d::DEPTH_TEXTURE_SAMPLING_SUPPORTED`
  --> /Users/aevyrie/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_core_pipeline-0.14.0-rc.4/src/dof/mod.rs:59:19
   |
59 |         Camera3d, DEPTH_TEXTURE_SAMPLING_SUPPORTED,
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `DEPTH_TEXTURE_SAMPLING_SUPPORTED` in `core_3d`
   |
note: found an item that was configured out
  --> /Users/aevyrie/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_core_pipeline-0.14.0-rc.4/src/core_3d/mod.rs:53:11
   |
53 | pub const DEPTH_TEXTURE_SAMPLING_SUPPORTED: bool = false;
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: found an item that was configured out
  --> /Users/aevyrie/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_core_pipeline-0.14.0-rc.4/src/core_3d/mod.rs:63:11
   |
63 | pub const DEPTH_TEXTURE_SAMPLING_SUPPORTED: bool = true;
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

## Solution

- Ensure that `DEPTH_TEXTURE_SAMPLING_SUPPORTED` is either `true` or
`false`, it shouldn't be completely missing.

## Testing

- Building on WASM without default features, which now seemingly no
longer includes webgl, will panic on startup with a message saying that
no wgpu backend was selected. This is much more helpful than the compile
time failure:
```
No wgpu backend feature that is implemented for the target platform was enabled
```
- I can see an argument for making this a compile time failure, however
the current failure mode is very confusing for novice users, and
provides no clues for how to fix it. If we want this to fail at compile
time, we should do it in a way that fails with a helpful message,
similar to what this PR acheives.
2024-06-30 22:58:43 +00:00
François Mockers
8a7d3ce461
don't put previous skin/morph in the morphed_skinned_mesh_layout (#14065)
# Objective

- Fixes #14059
- `morphed_skinned_mesh_layout` is the same as
`morphed_skinned_motion_mesh_layout` but shouldn't have the skin / morph
from previous frame, as they're used for motion

## Solution

- Remove the extra entries

## Testing

- Run with the glTF file reproducing #14059, it works
2024-06-29 01:03:51 +00:00
Brian Reavis
e69e28fe74
Made Material2dBindGroupId instantiable (#14053)
# Objective / Solution

Make it possible to construct `Material2dBindGroupId` for custom 2D
material pipelines by making the inner field public.

---

The 3D variant (`MaterialBindGroupId`) had this done in
e79b9b62ce
2024-06-29 00:41:15 +00:00
Periwink
6573887d5c
Fix error in AnyOf (#14027)
# Objective

- Fixes a correctness error introduced in
https://github.com/bevyengine/bevy/pull/14013 ...

## Solution

I've been playing around a lot of with the access code and I realized
that I introduced a soundness error when trying to simplify the code.
When we have a `Or<(With<A>, With<B>)>` filter, we cannot call
```
  let mut intermediate = FilteredAccess::default();
  $name::update_component_access($name, &mut intermediate);
  _new_access.append_or(&intermediate);
```
because that's just equivalent to adding the new components as `Or`
clauses.
For example if the existing `filter_sets` was `vec![With<C>]`, we would
then get `vec![With<C>, With<A>, With<B>]` which translates to `A or B
or C`.
Instead what we want is `(A and B) or (A and C)`, so we need to have
each new OR clause compose with the existing access like so:
```
let mut intermediate = _access.clone();
// if we previously had a With<C> in the filter_set, this will become `With<C> AND With<A>`
$name::update_component_access($name, &mut intermediate);
_new_access.append_or(&intermediate);
```

## Testing

- Added a unit test that is broken in main, but passes in this PR
2024-06-27 20:20:50 +00:00
Tamás Kiss
edca8707c8
add PartialEq to Outline (#14055)
# Objective

`sickle_ui` needs `PartialEq` on components to turn them into animatable
style attributes.

## Solution

All properties of Outline is already `PartialEq`, add derive on
`Outline` as well.

## Testing

- used `sickle_ui` to test if it can be made animatable
2024-06-27 20:03:07 +00:00
Patrick Walton
44db8b7fac
Allow phase items not associated with meshes to be binned. (#14029)
As reported in #14004, many third-party plugins, such as Hanabi, enqueue
entities that don't have meshes into render phases. However, the
introduction of indirect mode added a dependency on mesh-specific data,
breaking this workflow. This is because GPU preprocessing requires that
the render phases manage indirect draw parameters, which don't apply to
objects that aren't meshes. The existing code skips over binned entities
that don't have indirect draw parameters, which causes the rendering to
be skipped for such objects.

To support this workflow, this commit adds a new field,
`non_mesh_items`, to `BinnedRenderPhase`. This field contains a simple
list of (bin key, entity) pairs. After drawing batchable and unbatchable
objects, the non-mesh items are drawn one after another. Bevy itself
doesn't enqueue any items into this list; it exists solely for the
application and/or plugins to use.

Additionally, this commit switches the asset ID in the standard bin keys
to be an untyped asset ID rather than that of a mesh. This allows more
flexibility, allowing bins to be keyed off any type of asset.

This patch adds a new example, `custom_phase_item`, which simultaneously
serves to demonstrate how to use this new feature and to act as a
regression test so this doesn't break again.

Fixes #14004.

## Changelog

### Added

* `BinnedRenderPhase` now contains a `non_mesh_items` field for plugins
to add custom items to.
2024-06-27 16:13:03 +00:00
Chris Russell
1baa1a11b7
Add missing StaticSystemParam::queue implementation. (#14051)
# Objective

`StaticSystemParam` should delegate all `SystemParam` methods to the
inner param, but it looks like it was missed when the new `queue()`
method was added in #10839.

## Solution

Implement `StaticSystemParam::queue()` to delegate to the inner param.
2024-06-27 15:47:22 +00:00
Vic
e813326c87
add missing sort_unstable_by_key to QueryIter (#14040)
# Objective

`QueryIter::sort_unstable_by_key` is missing.

## Solution

Add `QueryIter::sort_unstable_by_key`.

## Testing

Added the new method to existing test.

## Changelog

Added `QueryIter::sort_unstable_by_key`.
2024-06-27 15:46:19 +00:00
Arseny Kapoulkine
9148847589
Fix incorrect computation of mips for cluster occlusion lookup (#14042)
The comment was incorrect - we are already looking at the pyramid
texture so we do not need to transform the size in any way. Doing that
resulted in a mip that was too fine to be selected in certain cases,
which resulted in a 2x2 pixel footprint not actually fully covering the
cluster sphere - sometimes this could lead to a non-conservative depth
value being computed which resulted in the cluster being marked as
invisible incorrectly.
2024-06-27 05:57:01 +00:00
Arseny Kapoulkine
4cd188568a
Improve MeshletMesh::from_mesh performance further (#14038)
This change updates meshopt-rs to 0.3 to take advantage of the newly
added sparse simplification mode: by default, simplifier assumes that
the entire mesh is simplified and runs a set of calculations that are
O(vertex count), but in our case we simplify many small mesh subsets
which is inefficient.

Sparse mode instead assumes that the simplified subset is only using a
portion of the vertex buffer, and optimizes accordingly. This changes
the meaning of the error (as it becomes relative to the subset, in our
case a meshlet group); to ensure consistent error selection, we also use
the ErrorAbsolute mode which allows us to operate in mesh coordinate
space.

Additionally, meshopt 0.3 runs optimizeMeshlet automatically as part of
`build_meshlets` so we no longer need to call it ourselves.

This reduces the time to build meshlet representation for Stanford Bunny
mesh from ~1.65s to ~0.45s (3.7x) in optimized builds.
2024-06-27 00:06:22 +00:00
François Mockers
3a04d38832
only run one update per frame drawn (#14023)
# Objective

- Fixes #13965 

## Solution

- Don't run multiple updates for a single frame
2024-06-26 20:23:17 +00:00
Martin Svanberg
0ee9827ba2
Fix typo in CPU adapter warning (#14037)
An annoying typo slipped through in #13780
2024-06-26 18:37:34 +00:00
Al M
57ac8f5211
impl BuildChildrenTransformExt for EntityWorldMut (#14022)
# Objective

Implement `BuildChildrenTransformExt` for `EntityWorldMut`, which is
useful when working directly with a mutable `World` ref.

## Solution

I realize this isn't the most optimal implementation in that it doesn't
reuse the existing entity location for the child, but it is terse and
reuses the existing code. I can address that if needed.

## Testing

I only tested locally. There are no tests for `set_parent_in_place` and
`remove_parent_in_place` currently, but I can add some.

---

## Changelog

`BuildChildrenTransformExt` implemented for `EntityWorldMut`.
2024-06-26 14:59:20 +00:00
Joseph
2b7d54b300
Emit a warning if the result of EntityCommand::with_entity is not used (#14028)
# Objective

When using combinators such as `EntityCommand::with_entity` to build
commands, it can be easy to forget to apply that command, leading to
dead code. In many cases this doesn't even lead to an unused variable
warning, which can make these mistakes difficult to track down

## Solution

Annotate the method with `#[must_use]`

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-26 13:54:55 +00:00
re0312
a3f91a28fc
Refactor check_light_mesh_visibility for performance #2 (#13906)
# Objective

- Second part of #13900 
- based on #13905 

## Solution

- check_dir_light_mesh_visibility defers setting the entity's
`ViewVisibility `so that Bevy can schedule it to run in parallel with
`check_point_light_mesh_visibility`.

- Reduce HashMap lookups for directional light checking as much as
possible

- Use `par_iter `to parallelize the checking process within each system.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-06-26 12:48:15 +00:00
Joseph
a4c621a127
Use an opaque type for EntityCommand::with_entity (#11210)
# Objective

The trait method `with_entity` is used to add an `EntityCommand` to the
command queue. Currently this method returns `WithEntity<C>` which pairs
a command with an `Entity`. By replacing this explicit type with an
opaque type, implementors can override this default implementation by
returning a custom command or closure that does the same thing with a
lower memory footprint.

# Solution

Return an opaque type from the method. As a bonus this file is now
cleaner without the `WithEntity` boilerplate
2024-06-26 12:47:46 +00:00
Martin Svanberg
0ae7afbcad
Print warning when using llvmpipe (#13780)
# Objective

Numerous people have been confused that Bevy runs slowly, when the
reason is that the `llvmpipe` software rendered is being used.

## Solution

Printing a warning could reduce the confusion.
2024-06-26 12:44:48 +00:00
François Mockers
19d078c609
don't crash without features bevy_pbr, ktx2, zstd (#14020)
# Objective

- Fixes #13728 

## Solution

- add a new feature `smaa_luts`. if enables, it also enables `ktx2` and
`zstd`. if not, it doesn't load the files but use placeholders instead
- adds all the resources needed in the same places that system that uses
them are added.
2024-06-26 03:08:23 +00:00
Periwink
8308ad08a2
AnyOf soundness fix (#14013)
# Objective
Fixes https://github.com/bevyengine/bevy/issues/13993 
PR inspired by https://github.com/bevyengine/bevy/pull/14007 to
accomplish the same thing, but maybe in a clearer fashion.

@Gingeh feel free to take my changes and add them to your PR, I don't
want to steal any credit

---------

Co-authored-by: Gingeh <39150378+Gingeh@users.noreply.github.com>
Co-authored-by: Bob Gardner <rgardner@inworld.ai>
Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
2024-06-25 23:54:50 +00:00
Alice Cecile
336fddb101
Make default behavior for BackgroundColor and BorderColor more intuitive (#14017)
# Objective

In Bevy 0.13, `BackgroundColor` simply tinted the image of any
`UiImage`. This was confusing: in every other case (e.g. Text), this
added a solid square behind the element. #11165 changed this, but
removed `BackgroundColor` from `ImageBundle` to avoid confusion, since
the semantic meaning had changed.

However, this resulted in a serious UX downgrade / inconsistency, as
this behavior was no longer part of the bundle (unlike for `TextBundle`
or `NodeBundle`), leaving users with a relatively frustrating upgrade
path.

Additionally, adding both `BackgroundColor` and `UiImage` resulted in a
bizarre effect, where the background color was seemingly ignored as it
was covered by a solid white placeholder image.

Fixes #13969.

## Solution

Per @viridia's design:

> - if you don't specify a background color, it's transparent.
> - if you don't specify an image color, it's white (because it's a
multiplier).
> - if you don't specify an image, no image is drawn.
> - if you specify both a background color and an image color, they are
independent.
> - the background color is drawn behind the image (in whatever pixels
are transparent)

As laid out by @benfrankel, this involves:

1. Changing the default `UiImage` to use a transparent texture but a
pure white tint.
2. Adding `UiImage::solid_color` to quickly set placeholder images.
3. Changing the default `BorderColor` and `BackgroundColor` to
transparent.
4. Removing the default overrides for these values in the other assorted
UI bundles.
5. Adding `BackgroundColor` back to `ImageBundle` and `ButtonBundle`.
6. Adding a 1x1 `Image::transparent`, which can be accessed from
`Assets<Image>` via the `TRANSPARENT_IMAGE_HANDLE` constant.

Huge thanks to everyone who helped out with the design in the linked
issue and [the Discord
thread](https://discord.com/channels/691052431525675048/1255209923890118697/1255209999278280844):
this was very much a joint design.

@cart helped me figure out how to set the UiImage's default texture to a
transparent 1x1 image, which is a much nicer fix.

## Testing

I've checked the examples modified by this PR, and the `ui` example as
well just to be sure.

## Migration Guide

- `BackgroundColor` no longer tints the color of images in `ImageBundle`
or `ButtonBundle`. Set `UiImage::color` to tint images instead.
- The default texture for `UiImage` is now a transparent white square.
Use `UiImage::solid_color` to quickly draw debug images.
- The default value for `BackgroundColor` and `BorderColor` is now
transparent. Set the color to white manually to return to previous
behavior.
2024-06-25 21:50:41 +00:00
re0312
dbffb41e50
Remove unnecessary compute for rotation interpolation (#14019)
# Objective

- `slerp` has a built-in short path check. And quaternions are ensured
to be normalized during loading .

## Solution
- remove it 

## Testing
`many_foxes ` in single thread

![image](https://github.com/bevyengine/bevy/assets/45868716/a7e74050-e202-4adb-9179-82a87263c300)
2024-06-25 21:14:37 +00:00
JMS55
d8b45ca136
Fix MeshletMesh material system ordering (#14016)
# Objective
- Fixes #13811 (probably, I lost my test code...)

## Solution
- Turns out that Queue and PrepareAssets are _not_ ordered. We should
probably either rethink our system sets (again), or improve the
documentation here. For reference, I've included the current ordering
below.
- The `prepare_meshlet_meshes_X` systems need to run after
`prepare_assets::<PreparedMaterial<M>>`, and have also been moved to
QueueMeshes.

```rust
schedule.configure_sets(
    (
        ExtractCommands,
        ManageViews,
        Queue,
        PhaseSort,
        Prepare,
        Render,
        Cleanup,
    )
        .chain(),
);

schedule.configure_sets((ExtractCommands, PrepareAssets, Prepare).chain());
schedule.configure_sets(QueueMeshes.in_set(Queue).after(prepare_assets::<GpuMesh>));
schedule.configure_sets(
    (PrepareResources, PrepareResourcesFlush, PrepareBindGroups)
        .chain()
        .in_set(Prepare),
);
```

## Testing
- Ambiguity checker to make sure I don't have ambiguous system ordering
2024-06-25 18:17:52 +00:00
Alice Cecile
52e5ad5da7
Don't show .to_bits in Display impl for Entity (#14011)
# Objective

#12469 changed the `Debug` impl for `Entity`, making sure it's actually
accurate for debugging. To ensure that its can still be readily logged
in error messages and inspectors, this PR added a more concise and
human-friendly `Display` impl.

However, users found this form too verbose: the `to_bits` information
was unhelpful and too long. Fixes #13980.

## Solution

- Don't include `Entity::to_bits` in the `Display` implementation for
`Entity`. This information can readily be accessed and logged for users
who need it.
- Also clean up the implementation of `Display` for `DebugName`,
introduced in https://github.com/bevyengine/bevy/pull/13760, to simply
use the new `Display` impl (since this was the desired format there).

## Testing

I've updated an existing test to verify the output of `Entity::display`.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-06-25 17:08:24 +00:00
Bob Gardner
4c3b4a445d
Mark events as read during EventReader::par_read (#13836)
# Objective

- Fix issue #13821  

## Solution

- Rewrote the test to ensure that it actually tests the functionality
correctly. Then made the par_read function correctly change the values
of self.reader.last_event_count.

## Testing

- Rewrote the test for par_read to run the system schedule twice,
checking the output each time

---------

Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
2024-06-25 15:36:06 +00:00
Sou1gh0st
f51a306b30
feat(bevy_app): expose an API to perform updates for a specific sub-app. (#14009)
# Objective

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

## Solution

- Expose an API to perform updates for a specific sub-app, so we can
avoid mutable borrow the app twice.

## Testing

- I have tested the API by modifying the code in the `many_lights`
example with the following changes:
```rust
impl Plugin for LogVisibleLights {
    fn build(&self, app: &mut App) {
        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
            return;
        };

        render_app.add_systems(Render, print_visible_light_count.in_set(RenderSet::Prepare));
    }

    fn finish(&self, app: &mut App) {
        app.update_sub_app_by_label(RenderApp);
    }
}
```

---

## Changelog
- add the `update_sub_app_by_label` API to `App` and `SubApps`.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2024-06-25 14:04:31 +00:00
Gagnus
1df811e6a5
Add Display implementation to DebugName. (#13760)
# Objective

- When writing "in game" debugging tools, quite often you need the name
of an entity (for example an entity tree). DebugName is the usual way of
doing that.
- A recent change to Entity's Debug implementation meant it was no
longer a minimal {index}v{generation} but instead a more verbose auto
generated Debug.
- This made DebugName's Debug implementation also verbose

## Solution

- I changed DebugName to derive Debug automatically and added a new
(preferred) Display implementation for it which is the preferred name
for an entity. If the entity has a Name component its the contents of
that, otherwise it is {index}v{generation} (though this does not use
Display of the Entity as that is more verbose than this).

## Testing

- I've added a new test in name.rs which tests the Display
implementation for DebugName by using to_string.

---

## Migration Guide

- In code which uses DebugName you should now use the Display
implementation rather than the Debug implementation (ie {} instead of
{:?} if you were printing it out).

---------

Co-authored-by: John Payne <20407779+johngpayne@users.noreply.github.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Andres O. Vela <andresovela@users.noreply.github.com>
2024-06-25 12:58:53 +00:00
Wuketuke
2d30ae437c
improved error message when forgetting to call system apply function … (#13975)
fixes #13944
I literally just added `Did you forget to call SystemState::apply?` to
the error message. I tested it with the code snipped from the Issue and
yeah it works
2024-06-25 12:27:15 +00:00
Caleb Yates
82fd3df719
Document use of NO_COLOR in LogPlugin (#13984)
# Objective
Fixes #13982

## Solution
~~Adds a new field to `bevy_log::LogPlugin`: `ansi: bool`~~
Documents the use of `std::env::set_var("NO_COLOR", "1");` to disable
colour output in terminals.

## Testing
Yes, all tests passed when I ran `cargo run -p ci -- test` and `cargo
run -p ci -- lints`

I have only tested the code on my Mac, though I doubt this change would
have any affect on other platforms.

---
2024-06-24 21:04:55 +00:00
Michael "Scott" McBee
d48ebdf641
Have WindowPosition::Centered take scale_factor_override into account (#13949)
# Objective

Fixes #8916 

My game has a low resolution pixel art style, and I use
`.with_scale_factor_override()` to make the window larger.
`WindowPosition::Centered` doesn't work for me.

## Solution

If `scale_factor_override` is set, use that over `monitor.scale_factor`

## Testing

Tested on Windows 11 with an Nvidia GPU:

### Main

![image](https://github.com/bevyengine/bevy/assets/3324533/5f9ae90e-b65a-48d9-b601-117df8f08a28)

### This PR

![image](https://github.com/bevyengine/bevy/assets/3324533/cd860611-7b6a-4ae5-b690-28d9ba8ea6ad)
2024-06-24 20:56:46 +00:00
Christian Hughes
3a82d6784b
Add a test asserting that reflected cloning a Handle increments strong count (#13961)
# Objective

Closes #5943. Seems like Assets v2 solved this one.

## Solution

Added a test to confirm that using `Reflect::clone_value` and then
`FromReflect::from_reflect` on a `Handle<T>` both increment the strong
count.

## Testing

A new test was added to confirm behavior.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-06-24 20:54:54 +00:00
Tamás Kiss
87fa69bd7e
fix panic: invalid SlotMap key used (#13990)
# Objective

Tight, in-frame generation, re-parenting, despawning, etc., UI
operations could sometime lead taffy to panic (invalid SlotMap key used)
when an entity with an invalid state later despawned.

Fixes #12403 

## Solution

Move the `remove_entities` call after children updates.

## Testing

`sickle_ui` had a case that always caused the panic. Tested before this
change, after this change, and before the change again to make sure the
error is there without the fix. The fix worked. Test steps and used
commit described in issue #12403.

I have also ran every bevy UI example, though none of them deal with
entity re-parenting or removal. No regression detected on them.

Tested on Windows only.
2024-06-24 20:47:44 +00:00
JMS55
158ccc6d6a
Fix meshlet interactions with regular shading passes (#13816)
* Fixes https://github.com/bevyengine/bevy/issues/13813
* Fixes https://github.com/bevyengine/bevy/issues/13810

Tested a combined scene with both regular meshes and meshlet meshes
with:
* Regular forward setup
* Forward + normal/motion vector prepasses
* Deferred (with depth prepass since that's required) 
* Deferred + depth/normal/motion vector prepasses

Still broken:
* Using meshlet meshes rendering in deferred and regular meshes
rendering in forward + depth/normal prepass. I don't know how to fix
this at the moment, so for now I've just add instructions to not mix
them.
2024-06-21 19:06:08 +00:00
Carter Anderson
0daa6c510b
Make Observer::with_event (and other variants) unsafe (#13954)
# Objective

`with_event` will result in unsafe casting of event data of the given
type to the type expected by the Observer system. This is inherently
unsafe.

## Solution

Flag `Observer::with_event` and `ObserverDescriptor::with_events` as
unsafe. This will not affect normal workflows as `with_event` is
intended for very specific (largely internal) use cases.

This _should_ be backported to 0.14 before release.

---

## Changelog

- `Observer::with_event` is now unsafe.
- Rename `ObserverDescriptor::with_triggers` to
`ObserverDescriptor::with_events` and make it unsafe.
2024-06-21 18:31:01 +00:00
François Mockers
841df150cc
apply window scale to window size when creating it (#13967)
# Objective

- Fixes #13702
- When creating a new window, its scale was changed to match the one
returned by winit, but its size was not which resulted in an incorrect
size until the event with the correct size was received, at least 1
frame later

## Solution

- Apply the window scale to its size when creating it
2024-06-21 18:04:57 +00:00
Shane Celis
e72f4ef9e9
bug: Don't panic. Warn on missing file_watcher path. (new branch) (#13902)
I updated my 'main' branch, which accidentally closed the original PR
#13747. I'm reopening the this from an actual branch on my repo like I
should have done in the first place. Here's the original info from the
first PR:

* * *

# Problem

The `file_watcher` feature panics if the file_watcher's path "assets" is
not present. I stumbled upon this behavior when I was actually testing
against `embedded_watcher`. I had no "assets" directory and didn't need
one for [my project](https://github.com/shanecelis/bevy_plane_cut).

```text
$ cargo run --example simple; # Runs fine.
$ cargo run --example simple --feature embedded_watcher; # Panics
thread 'main' panicked at /Users/shane/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_asset-0.14.0-rc.2/src/io/source.rs:503:21:
Failed to create file watcher from path "assets", Error { kind: PathNotFound, paths: ["/Users/shane/Projects/bevy_plane_cut/assets"] }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

# Opinion

If a project runs without panicing, then adding the `file_watcher`
feature shouldn't cause it to panic.

# Suggested Solution

This PR suggests if the "assets" path does not exist, emit a warning
stating that the file watcher could not be created and why. All other
errors will be treated as before with a panic and a message.

```text
$ cargo run --example simple --feature embedded_watcher; # Panics
2024-06-08T08:55:11.385249Z  WARN bevy_asset::io::source: Skip creating file watcher because path "assets" does not exist.
2024-06-08T08:55:11.385291Z  WARN bevy_asset::io::source: AssetSourceId::Default does not have an AssetWatcher configured. Consider enabling the `file_watcher` feature.
```

The second warning is new and I'd prefer it didn't emit under this
condition, but I'll wait to see whether this is actually regarded as a
bug.

# Testing

No tests added. Compiled against my project and it demonstrated the
suggested behavior.

* * *

I changed the second warning to the following when the `file_watcher`
feature is present. When it's not present, it uses the same warning as
before.

```
024-06-09T01:22:16.880619Z  WARN bevy_asset::io::source: Skip creating file watcher because path "assets" does not exist.
2024-06-09T01:22:16.880660Z  WARN bevy_asset::io::source: AssetSourceId::Default does not have an AssetWatcher configured. Consider adding an "assets" directory.
```
2024-06-21 13:10:57 +00:00
Rob Parrett
e46e246581
Fix a few "repeated word" typos (#13955)
# Objective

Stumbled on one of these and went digging for more

## Solution

```diff
- word word
+ word
```
2024-06-20 21:35:20 +00:00
Octorine
dcb191bb18
Updated descriptions for some geometric primitives to include more detail (#13937)
This is an attempt to address issue #13725, which was about the
geometric primitives in the bevy_math crate lacking some detail in the
docs.

# Objective

Fixes #13725

## Solution

Added details to the docstrings. Mostly this consisted of specifying
that the primitives are centered on the origin, or describing how
they're defined (e.g., a circle is the set of all points some distance
from the origin).

## Testing

No testing, since the only changes were to docs.
2024-06-20 12:16:27 +00:00
charlotte
8635a0f916
Correctly check physical size when updating winit (#13942)
Fixes #13701

After `winit` upgrade to `0.31`, windows were no longer correctly
resizing. This appears to just have been a simple mistake, where the new
physical size was being sourced from the `winit` window rather than on
the incoming `Window` component.

## Testing

Tested on macOS, but I'm curious whether this was also broken on other
platforms.
2024-06-20 11:22:47 +00:00
Alessio Marchi
2f9c42bb33
feat: add insert_after and insert_startup_before (#13941)
# Objective

Fixes #13866 

## Solution

Add `insert_before` in **FixedMainScheduleOrder** and
**MainScheduleOrder**, add `insert_startup_before` in
**MainScheduleOrder**, applying the same logic as `insert_after`, except
for parameters naming and insertion index.
2024-06-20 01:02:16 +00:00
Arseny Kapoulkine
6eec73a9a5
Make meshlet processing deterministic (#13913)
This is a followup to https://github.com/bevyengine/bevy/pull/13904
based on the discussion there, and switches two HashMaps that used
meshlet ids as keys to Vec.

In addition to a small further performance boost for `from_mesh` (1.66s
=> 1.60s), this makes processing deterministic modulo threading issues
wrt CRT rand described in the linked PR. This is valuable for debugging,
as you can visually or programmatically inspect the meshlet distribution
before/after making changes that should not change the output, whereas
previously every asset rebuild would change the meshlet structure.

Tested with https://github.com/bevyengine/bevy/pull/13431; after this
change, the visual output of meshlets is consistent between asset
rebuilds, and the MD5 of the output GLB file does not change either,
which was not the case before.
2024-06-20 00:58:43 +00:00
NiseVoid
38c8dc27c7
Use u32 for resolution/subdivision in primitive meshing (#13930)
# Objective

- Make primitive meshing behavior consisten across platforms
- Avoid using sizes bigger than `u32` since these aren't even supported
for meshes

## Solution

- Use `u32` instead of `usize` for resolution/subdivisions/segments/etc
fields

---

## Changelog

- Change resolutions in primitive mesh builders from `usize` to `u32`

## Migration Guide

- All primitive mesh builders now take `u32` instead of `usize` for
their resolution/subdivision/segment counts
2024-06-20 00:58:21 +00:00
MiniaczQ
31af724944
Move StateTransitionSteps registration to states plugin (#13939)
# Objective

Fixes #13920

## Solution

As described in the issue.

## Testing

Moved a custom transition plugin in example before any of the app-state
methods.
2024-06-20 00:57:40 +00:00
Christian Hughes
ee2487a6e2
Change World::inspect_entity to return an Iterator instead of Vec (#13934)
# Objective

Fixes #13933.

## Solution

Changed the return type.

## Testing

Fixed and reused the pre-existing tests for `inspect_entity`.

---

## Migration Guide

- `World::inspect_entity` now returns an `Iterator` instead of a `Vec`.
If you need a `Vec`, immediately collect the iterator:
`world.inspect_entity(entity).collect<Vec<_>>()`
2024-06-19 21:06:35 +00:00
Ben Frankel
e34ecf2f86
Fix typo in ComponentId docs: of -> or (#13932)
# Objective

Fix a typo. Single-character PR :)
2024-06-19 18:51:47 +00:00
Alessio Marchi
5bab161386
docs(bevy_state): fix broken links in init_state and insert_state (#13929)
# Objective

Fixes #13845 

## Solution

Fix inline docs links inside `init_state` and `insert_state`. 

## Testing

- Did you test these changes? If so, how?
Manually checked on `cargo doc` and  `rust-analyzer lsp`.
2024-06-19 17:38:00 +00:00
Shane Celis
6df0e9b37d
bug: Fix 9-slice textures with asymmetric borders. (#13921)
# Objective

Fix a 9-slice asymmetric border issue that
[QueenOfSquiggles](https://blobfox.coffee/@queenofsquiggles/112639035165575222)
found. Here's the behavior before:

<img width="340" alt="the-bug"
src="https://github.com/bevyengine/bevy/assets/54390/81ff1847-b2ea-4578-9fd0-af6ee96c5438">

## Solution

Here's the behavior with the fix.

<img width="327" alt="the-fix"
src="https://github.com/bevyengine/bevy/assets/54390/33a4e3f0-b6a8-448e-9654-1197218ea11d">


## Testing

I used QueenOfSquiggles
[repo](https://github.com/QueenOfSquiggles/my-bevy-learning-project) to
exercise the code. I manually went through a number of variations of the
border and caught a few other issues after the first pass. I added some
code to create random borders and though they often looked funny there
weren't any gaps like before.

### Unit Tests

I did add some tests to `slicer.rs` mostly as an exploratory programming
exercise. So they currently act as a limited, incomplete,
"golden-file"-ish approach. Perhaps they're not worth keeping.

In order to write the tests, I did add a `PartialEq` derive for
`TextureSlice`.

I only tested these changes on macOS.

---

## Changelog

Make 9-slice textures work with asymmetric borders.
2024-06-19 17:30:18 +00:00
NiseVoid
eddb006a8a
Use u32 for all resolution/subdivision fields in bevy_gizmos (#13927)
# Objective

- Make gizmos behavior consistent across platforms

## Solution

- Use `u32` instead of `usize` for resolution/subdivisions/segments/etc
fields

---

## Changelog

- Change resolutions in gizmos from `usize` to  `u32`

## Migration Guide

- All gizmos now take `u32` instead of `usize` for their
resolution/subdivision/segment counts
2024-06-19 17:28:10 +00:00
NiseVoid
524dce7505
Use a well defined type for sides in RegularPolygon (#13837)
# Objective

- Primitives should not use poorly defined types like `usize`,
especially since they are serializable

## Solution

- Use `u32` instead of `usize`
- The generic array types do not need to be changed because this size is
not actually stored or serialized anywhere

---

## Migration Guide

- `RegularPolygon` now uses `u32` instead of `usize` for the number of
sides
2024-06-19 15:43:40 +00:00
Luc
45a5f66c9d
Improve error handling for log filter (#13897)
# Objective
This PR aims to improve error handling for log filters.

Closes #13850

## Solution
I changed the parsing of LogPlugin its filter to lossy, so that it
prints the directives with an error but does not skip them. I decided on
letting it gracefully handle the error instead of panicking to be
consistent with the parsing from an environment variable that it tries
to do before parsing it from the LogPlugin filter.

If the user decides to specify the filter by an environment variable, it
would silently fail and default to the LogPlugin filter value. It now
prints an error before defaulting to the LogPlugin filter value.

Unfortunately, I could not try and loosely set the filter from the
environment variable because the `tracing-subscriber` module does not
expose the function it uses to get the environment variable, and I would
rather not copy its code. We may want to check if the maintainers are
open to exposing the method.


## Testing
Consider the following bevy app, where the second of the 3 filters is
invalid:
```
use bevy::{log::LogPlugin, prelude::*};

fn main() {
    App::new().add_plugins(DefaultPlugins
        .set(LogPlugin {
            filter: "wgpu=error,my_package=invalid_log_level,naga=warn".into(),
            ..default()
        })
    ).run();
}
```
In the previous situation, it would panic with a non-descriptive error:
"called `Result::unwrap()` on an `Err` value: ParseError { kind:
Other(None) }", while only 1 of the 3 filters is invalid. When running
`cargo run`, it will now use the two valid filters and print an error on
the invalid filter.
> ignoring `my_package=invalid_log_level`: invalid filter directive

This error comes from `tracing-subscriber` and cannot be altered as far
as I can see.

To test setting the log filter through an environment variable, you can
use `RUST_LOG="wgpu=error,my_package=invalid_log_level,naga=warn" cargo
run` to run your app. In the previous situation it would silently fail
and use the LogPlugin filter. It will now print an error before using
the LogPlugin filter.
> LogPlugin failed to parse filter from env: invalid filter directive


## Changelog
- Added warning when using invalid filter in the RUST_LOG environment
variable
- Prevent the app from panicking when setting an invalid LogPlugin
filter

---------

Co-authored-by: Luc Drenth <luc.drenth@ing.com>
2024-06-19 13:46:03 +00:00
Yoh Deadfall
0a003eaa98
Fixed a link to Blender's mikktspace docs (#13924)
# Objective

- The old link doesn't work since the page was moved to the archive.
2024-06-19 12:37:10 +00:00
Jenya705
6b2d4834e9
IntoSystemConfigs::chain_ignore_deferred's return type fix (#13919)
# Objective

Fixes #13917 

## Solution

Changed `IntoSystemSetConfigs::chain_ignore_deferred`'s return type from
`SystemConfigs` to `SystemSetConfigs`

## Testing

Tried to run the `ecs_guide` example, where `chain` method is replaced
by `chain_ignore_deferred` method

---
2024-06-18 22:21:58 +00:00
dav-wolff
1b0475f234
Fix typo in Query::single_mut docs (#13916)
# Objective

- Fix a typo in documentation for `Query::single_mut`

## Solution

- Change `item` to `items`

## Testing

- I built the documentation and it looked fine.
- Since this only affects a doc comment, no further testing should be
necessary.

---

## Changelog

> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.

- Fixed a typo in the documentation for Query.
2024-06-18 19:55:37 +00:00
BD103
c37e81b34a
Specify units in AmbientLight::brightness docs (#13297)
# Objective

- Fixes #11933.
- Related: #12280.

## Solution

- Specify that, after applying `AmbientLight`, the resulting units are
in cd/m^2.
- This is based on [@fintelia's
comment](https://github.com/bevyengine/bevy/issues/11933#issuecomment-1995427587),
and will need to be verified.

---

## Changelog

- Specified units for `AmbientLight`'s `brightness` field.
2024-06-18 11:20:10 +00:00
Arseny Kapoulkine
001cc147c6
Improve MeshletMesh::from_mesh performance (#13904)
This change reworks `find_connected_meshlets` to scale more linearly
with the mesh size, which significantly reduces the cost of building
meshlet representations. As a small extra complexity reduction, it moves
`simplify_scale` call out of the loop so that it's called once (it only
depends on the vertex data => is safe to cache).

The new implementation of connectivity analysis builds edge=>meshlet
list data structure, which allows us to only iterate through
`tuple_combinations` of a (usually) small list. There is still some
redundancy as if two meshlets share two edges, they will be represented
in the meshlet lists twice, but it's overall much faster.

Since the hash traversal is non-deterministic, to keep this part of the
algorithm deterministic for reproducible results we sort the output
adjacency lists.

Overall this reduces the time to process bunny mesh from ~4.2s to ~1.7s
when using release; in unoptimized builds the delta is even more
significant.

This was tested by using https://github.com/bevyengine/bevy/pull/13431
and:

a) comparing the result of `find_connected_meshlets` using old and new
code; they are equal in all steps of the clustering process
b) comparing the rendered result of the old code vs new code *after*
making the rest of the algorithm deterministic: right now the loop that
iterates through the result of `group_meshlets()` call executes in
different order between program runs. This is orthogonal to this change
and can be fixed separately.

Note: a future change can shrink the processing time further from ~1.7s
to ~0.4s with a small diff but that requires an update to meshopt crate
which is pending in https://github.com/gwihlidal/meshopt-rs/pull/42.
This change is independent.
2024-06-18 08:29:17 +00:00
re0312
91cd84fea7
Refactor check_light_mesh_visibility for performance #1 (#13905)
# Objective

- first part of #13900 

## Solution

- split `check_light_mesh_visibility `into
`check_dir_light_mesh_visibility `and
`check_point_light_mesh_visibility` for better review
2024-06-18 03:22:54 +00:00
re0312
41ad4e98de
Reuse VisibleEntities in check_light_mesh_visibilty (#13894)
# Objective

- After #12582 , Bevy split visibleEntities into a TypeIdMap for
different types of entities, but the behavior in
`check_light_mesh_visibility `simply calls HashMap::clear(), which will
reallocate memory every frame.


## Testing
cargo run --release --example many_cubes --features bevy/trace_tracy --
--shadows
~10% win in `check_light_mesh_visibilty`

![image](https://github.com/bevyengine/bevy/assets/45868716/1bf4deef-bab2-4e5f-9f60-bea8b7e33e3e)
2024-06-17 22:37:50 +00:00
Gino Valente
53910e07ae
bevy_reflect: Improve reflection serialization error messages (#13867)
# Objective

The error messages that appear when a value cannot be serialized or
deserialized via reflection could be slightly improved.

When one of these operations fails, some users are confused about how to
resolve the issue. I've spoken with a few who didn't know they could
register `ReflectSerialize` themselves. We should try to clarify this to
some degree in the error messages.

## Solution

Add some more detail to the error messages.

For example, replacing this:

```
Type 'core::ops::RangeInclusive<f32>' did not register ReflectSerialize
```

with this:

```
Type `core::ops::RangeInclusive<f32>` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`
```

I also added a separate error message if the type was not registered in
the type registry at all:

```
Type `core::ops::RangeInclusive<f32>` is not registered in the type registry
```

## Testing

You can test locally by running:

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

---

## Changelog

- Added error message for missing type registration when serializing
reflect data
- Changed error message for missing `ReflectSerialize` registration when
serializing reflect data
- Changed error message for missing `ReflectDeserialize` registration
when deserializing reflect data
2024-06-17 18:13:46 +00:00
Jan Hohenheim
6273227e09
Fix lints introduced in Rust beta 1.80 (#13899)
Resolves #13895

Mostly just involves being more explicit about which parts of the docs
belong to a list and which begin a new paragraph.
- found a few docs that were malformed because of exactly this, so I
fixed that by introducing a paragraph
- added indentation to nearly all multiline lists
- fixed a few minor typos
- added `#[allow(dead_code)]` to types that are needed to test
annotations but are never constructed
([here](https://github.com/bevyengine/bevy/pull/13899/files#diff-b02b63604e569c8577c491e7a2030d456886d8f6716eeccd46b11df8aac75dafR1514)
and
[here](https://github.com/bevyengine/bevy/pull/13899/files#diff-b02b63604e569c8577c491e7a2030d456886d8f6716eeccd46b11df8aac75dafR1523))
- verified that  `cargo +beta run -p ci -- lints` passes
- verified that `cargo +beta run -p ci -- test` passes
2024-06-17 17:22:01 +00:00
Ľubomír Kurčák
4b3246af40
Add cross gizmos (#13883)
# Objective

Add `cross` and `cross_2d` gizmos in accordance with #13868.

## Solution

Extend `Gizmos` to provide these functions.

## Testing

Tested in `2d_gizmos` and `3d_gizmos` examples, and external projects.


![image](https://github.com/bevyengine/bevy/assets/29227697/d13067e1-d7eb-46c5-9b73-6c2d70417889)


![image](https://github.com/bevyengine/bevy/assets/29227697/0a8eba48-fbb3-4b3e-abe1-4e250222f94b)
2024-06-17 15:45:32 +00:00
long_long_float
47f58ac6c5
Fix parameter name of all_tuples's document (#13896)
# Objective

I got little confused by the document of `all_tuples!` because type
names of the parameter `T` and extracted names `Pn` are difference.

## Solution

I fixed type names of the document.
2024-06-17 15:17:24 +00:00
James O'Brien
335dcf96a2
Update observer archetype flags for sparse components (#13886)
# Objective

- Fixes #13885 

## Solution

- Update the flags correctly on archetype creation

## Testing

- Added `observer_order_insert_remove_sparse` to catch regressions.
2024-06-17 15:15:30 +00:00
Josh Matthews
8626ad05bc
Update accesskit and accesskit_winit (#13841)
Updates the requirements on
[accesskit](https://github.com/AccessKit/accesskit) to permit the latest
version.
- [Release notes](https://github.com/AccessKit/accesskit/releases)
-
[Changelog](https://github.com/AccessKit/accesskit/blob/main/release-please-config.json)
-
[Commits](https://github.com/AccessKit/accesskit/compare/accesskit-v0.14.0...accesskit-v0.15.0)

---
updated-dependencies:
- dependency-name: accesskit dependency-type: direct:production ...

Adopted from #13787.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-17 15:08:53 +00:00
Mincong Lu
c75610e2b2
Made some things in bevy_render Debug. (#13830)
# Objective

Some items in `bevy_render` do not implement `Debug`.

## Solution

Made them derive `Debug`.
2024-06-17 15:04:20 +00:00
Brezak
16e02e1889
Use a unstable sort to sort component ids in bevy_ecs (#13789)
# Objective

While writing code for the `bevy_ecs` I noticed we were using a
unnecessarily stable sort to sort component ids

## Solution

- Sort component ids with a unstable sort
- Comb the bevy_ecs crate for any other obvious inefficiencies.
- Don't clone component vectors when inserting an archetype.

## Testing

I ran `cargo test -p bevy_ecs`. Everything else I leave to CI.

## Profiling

I measured about a 1% speed increase when spawning entities directly
into a world. Since the difference is so small (and might just be noise)
I didn't bother to figure out which of change if any made the biggest
difference.
<details>
<summary> Tracy data </summary>
Yellow is this PR. Red is the commit I branched from.


![image](https://github.com/bevyengine/bevy/assets/59848927/f1a5c95d-a882-4dfb-ac07-dd2922273b91)

</details>

<details>
<summary>Methodology</summary>
I created a system that spawn a 1000 entities each with the same 30
components each frame, and then I measured it's run time. The unusually
high number of components was chosen because the standard library [will
use a insertion sort for slices under 20
elements](0de24a5177/library/core/src/slice/sort.rs (L1048-L1049)).
This holds for both stable and unstable sorts.
</details>
2024-06-17 14:56:19 +00:00
hut
92ac77867d
Fix phantom key presses in winit on focus change (#13299) (#13696)
# Objective

Fixes #13299

On Linux/X11, changing focus into a winit window will produce winit
KeyboardInput events with a "is_synthetic=true" flag that are not
intended to be used. Bevy erroneously passes them on to the user,
resulting in phantom key presses.

## Solution

This patch properly filters out winit KeyboardInput events with
"is_synthetic=true".

For example, pressing Alt+Tab to focus a bevy winit window results in a
permanently stuck Tab key until the user presses Tab once again to
produce a winit KeyboardInput release event. The Tab key press event
that causes this problem is "synthetic", should not be used according to
the winit devs, and simply ignoring it fixes this problem.

Synthetic key **releases** are still evaluated though, as they are
essential for correct release key handling. For example, if the user
binds the key combination Alt+1 to the action "move the window to
workspace 1", places the bevy game in workspace 2, focuses the game and
presses Alt+1, then the key release event for the "1" key will be
synthetic. If we would filter out all synthetic keys, the bevy game
would think that the 1 key remains pressed forever, until the user
manually presses+releases the key again inside bevy.

Reference:
https://docs.rs/winit/0.30.0/winit/event/enum.WindowEvent.html#variant.KeyboardInput.field.is_synthetic
Relevant discussion: https://github.com/rust-windowing/winit/issues/3543

## Testing

Tested with the "keyboard_input_events" example. Entering/exiting the
window with various keys, as well as changing its workspace, produces
the correct press/release events.
2024-06-17 14:49:16 +00:00
amy universe
836b6c4409
fix typo (#13880)
# Objective

"wtate" an off-by-one typo in the winit_config.rs file

## Solution

"state"
2024-06-16 18:59:51 +00:00
Kristoffer Søholm
cde610577d
Make time_system public (#13879)
# Objective

If `time_system` isn't public you cannot order systems relative to it in
the `TimeSystem` set.

## Solution

Make it public
2024-06-16 18:07:41 +00:00
MiniaczQ
90894a1910
Warn about missing StatesPlugin when installing states (#13877)
# Objective

- Fixes #13874

## Solution

- Confirm that the `StatesPlugin` is installed when trying to add
states.
- Skipped for state scoped entities, since those will warn about missing
states.
2024-06-16 17:36:24 +00:00
Lee-Orr
f69117331b
remove inaccurate warning from in_state (#13862)
# Objective
Fixes #13854

## Solution
Removed the inaccurate warning. This was done for a few reasons:

- States not existing is now a valid "state" (for lack of a better term)
- Other run conditions don't provide an equivalent warning
2024-06-16 16:06:45 +00:00
Torstein Grindvik
8b25ef3328
Allow bevy_color use without bevy_reflect support (#13870)
# Objective

Allow the use of color definitions from Bevy in other contexts than pure
Bevy apps, e.g. outside ECS use.
In those cases it's nice to not have more dependencies than you need.

## Solution

Hide use of reflection behind a feature flag.
Defaults to on.

## Points to consider

1. This was straightforward _except_ for the
`crates/bevy_color/src/lib.rs` change where I removed `Reflect` as a
bound. That is awkward to have feature gated since features should be
additive. If the bound was added as part of the feature flag, the result
would be _more_ restrictive, and _disable_ impls which did not have the
impl. On the other hand having the reflect bound there unconditionally
would defeat the purpose of the PR. I opted to remove the bound since it
seems overly restrictive anyway.
2. It's possible to hide `encase` and `bytemuck` behind the new feature
flag too (or a separate one). I'm thinking if `bevy-support` is not
desired then it's unlikely that the user has need of those.

---------

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
2024-06-16 15:47:30 +00:00
François Mockers
d8f42608f9
text position: use size instead of bounds (#13858)
# Objective

- #13846 introduced a bug where text not bound was not displayed

## Solution

- bounds are infinite
- use computed size instead, that already should be using the available
bounds
2024-06-16 15:07:31 +00:00
Miles Silberling-Cook
aaccbe88aa
Upstream CorePlugin from bevy_mod_picking (#13677)
# Objective

This is the first of a series of PRs intended to begin the upstreaming
process for `bevy_mod_picking`. The purpose of this PR is to:
+ Create the new `bevy_picking` crate
+ Upstream `CorePlugin` as `PickingPlugin`
+ Upstream the core pointer and backend abstractions.

This code has been ported verbatim from the corresponding files in
[bevy_picking_core](https://github.com/aevyrie/bevy_mod_picking/tree/main/crates/bevy_picking_core/src)
with a few tiny naming and docs tweaks.

The work here is only an initial foothold to get the up-streaming
process started in earnest. We can do refactoring and improvements once
this is in-tree.

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-15 11:59:57 +00:00
James O'Brien
eb3c81374a
Generalised ECS reactivity with Observers (#10839)
# Objective

- Provide an expressive way to register dynamic behavior in response to
ECS changes that is consistent with existing bevy types and traits as to
provide a smooth user experience.
- Provide a mechanism for immediate changes in response to events during
command application in order to facilitate improved query caching on the
path to relations.

## Solution

- A new fundamental ECS construct, the `Observer`; inspired by flec's
observers but adapted to better fit bevy's access patterns and rust's
type system.

---

## Examples
There are 3 main ways to register observers. The first is a "component
observer" that looks like this:
```rust
world.observe(|trigger: Trigger<OnAdd, Transform>, query: Query<&Transform>| {
    let transform = query.get(trigger.entity()).unwrap();
});
```
The above code will spawn a new entity representing the observer that
will run it's callback whenever the `Transform` component is added to an
entity. This is a system-like function that supports dependency
injection for all the standard bevy types: `Query`, `Res`, `Commands`
etc. It also has a `Trigger` parameter that provides information about
the trigger such as the target entity, and the event being triggered.
Importantly these systems run during command application which is key
for their future use to keep ECS internals up to date. There are similar
events for `OnInsert` and `OnRemove`, and this will be expanded with
things such as `ArchetypeCreated`, `TableEmpty` etc. in follow up PRs.

Another way to register an observer is an "entity observer" that looks
like this:
```rust
world.entity_mut(entity).observe(|trigger: Trigger<Resize>| {
    // ...
});
```
Entity observers run whenever an event of their type is triggered
targeting that specific entity. This type of observer will de-spawn
itself if the entity (or entities) it is observing is ever de-spawned so
as to not leave dangling observers.

Entity observers can also be spawned from deferred contexts such as
other observers, systems, or hooks using commands:
```rust
commands.entity(entity).observe(|trigger: Trigger<Resize>| {
    // ...
});
```

Observers are not limited to in built event types, they can be used with
any type that implements `Event` (which has been extended to implement
Component). This means events can also carry data:

```rust
#[derive(Event)]
struct Resize { x: u32, y: u32 }

commands.entity(entity).observe(|trigger: Trigger<Resize>, query: Query<&mut Size>| {
    let event = trigger.event();
    // ...
});

// Will trigger the observer when commands are applied.
commands.trigger_targets(Resize { x: 10, y: 10 }, entity);
```

You can also trigger events that target more than one entity at a time:

```rust
commands.trigger_targets(Resize { x: 10, y: 10 }, [e1, e2]);
```

Additionally, Observers don't _need_ entity targets:

```rust
app.observe(|trigger: Trigger<Quit>| {
})

commands.trigger(Quit);
```

In these cases, `trigger.entity()` will be a placeholder.

Observers are actually just normal entities with an `ObserverState` and
`Observer` component! The `observe()` functions above are just shorthand
for:

```rust
world.spawn(Observer::new(|trigger: Trigger<Resize>| {});
```

This will spawn the `Observer` system and use an `on_add` hook to add
the `ObserverState` component.

Dynamic components and trigger types are also fully supported allowing
for runtime defined trigger types.

## Possible Follow-ups
1. Deprecate `RemovedComponents`, observers should fulfill all use cases
while being more flexible and performant.
2. Queries as entities: Swap queries to entities and begin using
observers listening to archetype creation triggers to keep their caches
in sync, this allows unification of `ObserverState` and `QueryState` as
well as unlocking several API improvements for `Query` and the
management of `QueryState`.
3. Trigger bubbling: For some UI use cases in particular users are
likely to want some form of bubbling for entity observers, this is
trivial to implement naively but ideally this includes an acceleration
structure to cache hierarchy traversals.
4. All kinds of other in-built trigger types.
5. Optimization; in order to not bloat the complexity of the PR I have
kept the implementation straightforward, there are several areas where
performance can be improved. The focus for this PR is to get the
behavior implemented and not incur a performance cost for users who
don't use observers.

I am leaving each of these to follow up PR's in order to keep each of
them reviewable as this already includes significant changes.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-06-15 01:33:26 +00:00
MiniaczQ
1a1b22ede8
Restore overwrite capabilities of insert_state (#13848)
# Objective

- Fixes #13844
- Warn user when initializing state multiple times

## Solution

- `insert_state` will overwrite previously initialized state value,
reset transition events and re-insert it's own transition event.
- `init_state`, `add_sub_state`, `add_computed_state` are idempotent, so
calling them multiple times will emit a warning.

## Testing

- 2 tests confirming overwrite works.
- Given the example from #13844
```rs
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .insert_state(AppState::A)
        .insert_state(AppState::B)
        .add_systems(OnEnter(AppState::A), setup_a)
        .add_systems(OnEnter(AppState::B), setup_b)
        .add_systems(OnExit(AppState::A), cleanup_a)
        .add_systems(OnExit(AppState::B), cleanup_b)
        .run();
}

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]
enum AppState {
    A,
    B,
}

fn setup_a() {
    info!("setting up A");
}

fn setup_b() {
    info!("setting up B");
}

fn cleanup_a() {
    info!("cleaning up A");
}

fn cleanup_b() {
    info!("cleaning up B");
}
```

We get the following result:
```
INFO states: setting up B
```
which matches our expectations.
2024-06-14 22:22:59 +00:00
Kristoffer Søholm
1395e3672c
Fix is_plugin_added::<Self>() being true during build (#13817)
# Objective

Fixes #13815 

## Solution

Move insertion of the plugin name to after build is called.

## Testing

I added a regression test

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-06-14 19:37:03 +00:00
robtfm
01971f210e
fix non-exact text h-alignment (#13846)
# Objective

when a parent container is auto-sized, text alignments `Center` and
`Right` don't align to the center and right properly. fix it

## Solution

ab_glyph positions return +/- values from an anchor point. we currently
transform them to positive values from the min-x of the glyphs, and then
offset from the left of the bounds. instead, we can keep the negative
values as ab_glyph intended and offset from the left/middle/right of the
bounds as appropriate.

## Testing

texts with align left, center, right, all contained in the purple boxes:
before (0.14.0-rc.2):
![Screenshot 2024-06-14
165456](https://github.com/bevyengine/bevy/assets/50659922/90fb73b0-d8bd-4ae8-abf3-7106eafc93ba)

after:

![Screenshot 2024-06-14
164449](https://github.com/bevyengine/bevy/assets/50659922/0a75ff09-b51d-4fbe-a491-b655a145c08b)

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

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

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

    for (left, justify) in [
        (100.0, JustifyText::Left),
        (500.0, JustifyText::Center),
        (900.0, JustifyText::Right),
    ] {
        commands
        // container
        .spawn(NodeBundle {
            style: Style {
                flex_direction: FlexDirection::Column,
                position_type: PositionType::Absolute,
                left: Val::Px(left),
                top: Val::Px(100.0),
                width: Val::Px(300.0),
                ..Default::default()
            },
            ..Default::default()
        })
        .with_children(|commands| {
            commands.spawn(NodeBundle{
                style: Style {
                    flex_direction: FlexDirection::Row,
                    height: Val::Px(75.0),
                    ..Default::default()
                },
                background_color: Color::srgb(1.0, 0.0, 1.0).into(),
                ..Default::default()
            }).with_children(|commands| {
                // a div that reduces the available size
                commands.spawn(NodeBundle {
                    style: Style {
                        width: Val::Px(75.0),
                        ..Default::default()
                    },
                    background_color: Color::srgb(0.0, 1.0, 0.0).into(),
                    ..Default::default()
                });

                // text with width=auto, but actual size will not be what it expcets due to the sibling div above
                commands.spawn(TextBundle {
                    text: Text::from_section("Some text that wraps onto a second line", Default::default()).with_justify(justify),
                    style: Style {
                        align_self: AlignSelf::Center,
                        ..Default::default()
                    },
                    ..Default::default()
                });
            });
        });
    }
}
```
2024-06-14 19:14:42 +00:00
Elabajaba
2825ac8a8e
Wgpu 0.20 (#13186)
Currently blocked on https://github.com/gfx-rs/wgpu/issues/5774

# Objective

Update to wgpu 0.20

## Solution

Update to wgpu 0.20 and naga_oil 0.14.

## Testing

Tested a few different examples on linux (vulkan, webgl2, webgpu) and
windows (dx12 + vulkan) and they worked.

---

## Changelog

- Updated to wgpu 0.20. Note that we don't currently support wgpu's new
pipeline overridable constants, as they don't work on web currently and
need some more changes to naga_oil (and are somewhat redundant with
naga_oil's shader defs). See wgpu's changelog for more
https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v0200-2024-04-28

## Migration Guide

TODO

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-06-14 18:39:31 +00:00
Mike
004ba585b2
reduce the antialias strength (#13814)
# Objective

- Fixes #13807

## Solution

- Before this pr we antialiased between 0.5 and -0.5. This pr changes
things to antialias between 0.25 and -0.25. I tried slightly larger
ranges, but the edge between the boxes still showed. I'm not 100% sure
this is the correct solution, but from what I could find the range you
use is more art than science.

## Testing

- Ran rounded_borders example, the code in the linked issue, and the
testing example from #12702.

---

## Changelog

- reduce antialiasing in ui shader.
2024-06-14 18:36:15 +00:00
Nionidh
ba198151a4
Add missing plugins to doc of DefaultPlugins (#13833)
StatesPlugin and GizmoPlugin were missing from the doc comment of
DefaultPlugins. I am not sure whether this was for a reason, but i just
stumbled over it and it seemed off...

## Testing

I'm not sure how to test these changes?
2024-06-14 18:03:04 +00:00
Alice Cecile
2cffd14923
Ensure that events are updated even when using a bare-bones Bevy App (#13808)
# Objective

As discovered in
https://github.com/Leafwing-Studios/leafwing-input-manager/issues/538,
there appears to be some real weirdness going on in how event updates
are processed between Bevy 0.13 and Bevy 0.14.

To identify the cause and prevent regression, I've added tests to
validate the intended behavior.
My initial suspicion was that this would be fixed by
https://github.com/bevyengine/bevy/pull/13762, but that doesn't seem to
be the case.

Instead, events appear to never be updated at all when using `bevy_app`
by itself. This is part of the problem resolved by
https://github.com/bevyengine/bevy/pull/11528, and introduced by
https://github.com/bevyengine/bevy/pull/10077.

After some investigation, it appears that `signal_event_update_system`
is never added using a bare-bones `App`, and so event updates are always
skipped.

This can be worked around by adding your own copy to a
later-in-the-frame schedule, but that's not a very good fix.

## Solution

Ensure that if we're not using a `FixedUpdate` schedule, events are
always updated every frame.

To do this, I've modified the logic of `event_update_condition` and
`event_update_system` to clearly and correctly differentiate between the
two cases: where we're waiting for a "you should update now" signal and
where we simply don't care.

To encode this, I've added the `ShouldUpdateEvents` enum, replacing a
simple `bool` in `EventRegistry`'s `needs_update` field.

Now, both tests pass as expected, without having to manually add a
system!

## Testing

I've written two parallel unit tests to cover the intended behavior:

1. Test that `iter_current_update_events` works as expected in
`bevy_ecs`.
2. Test that `iter_current_update_events` works as expected in
`bevy_app`

I've also added a test to verify that event updating works correctly in
the presence of a fixed main schedule, and a second test to verify that
fixed updating works at all to help future authors narrow down failures.

## Outstanding

- [x] figure out why the `bevy_app` version of this test fails but the
`bevy_ecs` version does not
- [x] figure out why `EventRegistry::run_updates` isn't working properly
- [x] figure out why `EventRegistry::run_updates` is never getting
called
- [x] figure out why `event_update_condition` is always returning false
- [x] figure out why `EventRegistry::needs_update` is always false
- [x] verify that the problem is a missing `signal_events_update_system`

---------

Co-authored-by: Mike <mike.hsu@gmail.com>
2024-06-12 14:28:51 +00:00
CatThingy
f23c686fcf
Fix minor typos in query join docs (#13812)
# Objective

- Correct typos in docs for `Query::join`'s docs

## Solution

- Fix them

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-06-11 23:24:53 +00:00
Mike
07a85676b3
Revert "constrain WorldQuery::init_state argument to ComponentInitial… (#13804)
…izer (#13442)"

This reverts commit 5cfb063d4a.

- This PR broke bevy-trait-query, which needs to be able to write a
resource in init_state. See #13798 for more details.
- Note this doesn't fix everything as transmutes for bevy-trait-query
will still be broken,. But the current usage in that crate is UB, so we
need to find another solution.
2024-06-11 22:54:42 +00:00
Alice Cecile
d659a1f7d5
Revert "Make FOG_ENABLED a shader_def instead of material flag (#13783)" (#13803)
This reverts commit 3ced49f672.

Relevant to https://github.com/bevyengine/bevy/issues/13802. This wasn't
done quite right and partially broke fog.

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-06-10 23:25:16 +00:00
Bob Gardner
2ccdae7489
Split event.rs into a full module. (#13801)
# Objective

- Split the bevy_ecs::events module so it's easier to work with

## Solution

- Split the event.rs file across multiple files, made sure all tests
passed, and exports from the module were the same as previous

## Testing

- All automated tests pass.
2024-06-10 21:45:01 +00:00
Brezak
d803adff09
Add from_color to StandardMaterial and ColorMaterial (#13791)
# Objective

Closes #13738

## Solution

Added `from_color` to materials that would support it. Didn't add
`from_color` to `WireframeMaterial` as it doesn't seem we expect users
to be constructing them themselves.

## Testing

None

---

## Changelog

### Added

- `from_color` to `StandardMaterial` so you can construct this material
from any color type.
- `from_color` to `ColorMaterial` so you can construct this material
from any color type.
2024-06-10 21:25:31 +00:00
Alice Cecile
54010cc07e
Revert Align Scene::write_to_world_with to match DynamicScene::write_to_world_with (#13800)
# Objective

- https://github.com/bevyengine/bevy/pull/13714 broke scenes pretty
seriously
- Fixes https://github.com/bevyengine/bevy/issues/13796

## Solution

Revert it. We can redo this PR once the behavior is fixed.

Co-authored-by: Dmytro Banin <dima_banin@hotmail.com>
2024-06-10 21:14:11 +00:00
JMS55
fd30e0c67d
Fix meshlet vertex attribute interpolation (#13775)
# Objective

- Mikktspace requires that we normalize world normals/tangents _before_
interpolation across vertices, and then do _not_ normalize after. I had
it backwards.
- We do not (am not supposed to?) need a second set of barycentrics for
motion vectors. If you think about the typical raster pipeline, in the
vertex shader we calculate previous_world_position, and then it gets
interpolated using the current triangle's barycentrics.

## Solution

- Fix normal/tangent processing 
- Reuse barycentrics for motion vector calculations
- Not implementing this for 0.14, but long term I aim to remove explicit
vertex tangents and calculate them in the shader on the fly.

## Testing

- I tested out some of the normal maps we have in repo. Didn't seem to
make a difference, but mikktspace is all about correctness across
various baking tools. I probably just didn't have any of the ones that
would cause it to break.
- Didn't test motion vectors as there's a known bug with the depth
buffer and meshlets that I'm waiting on the render graph rewrite to fix.
2024-06-10 20:18:43 +00:00
Brezak
f187d9c5fc
Poll system information in separate tasks (#13693)
# Objective

Reading system information severely slows down the update loop.
Fixes #12848.

## Solution

Read system info in a separate thread.

## Testing

- Open the scene 3d example
- Add `FrameTimeDiagnosticsPlugin`, `SystemInformationDiagnosticsPlugin`
and `LogDiagnosticsPlugin` to the app.
- Add this system to the update schedule to disable Vsync on the main
window
```rust
fn change_window_mode(mut windows: Query<&mut Window, Added<Window>>) {
    for mut window in &mut windows {
        window.present_mode = PresentMode::AutoNoVsync;
    }
}
```
- Read the fps values in the console before and after this PR.

On my PC I went from around 50 fps to around 1150 fps.

---

## Changelog

### Changed

- The `SystemInformationDiagnosticsPlugin` now reads system data
separate of the update cycle.

### Added 

- The `EXPECTED_SYSTEM_INFORMATION_INTERVAL` constant which defines how
often we read system diagnostic data.

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-06-10 19:06:22 +00:00
Chris Juchem
49661b99fe
Remove extra call to clear_trackers (#13762)
Fixes #13758.

# Objective

Calling `update` on the main app already calls `clear_trackers`. Calling
it again in `SubApps::update` caused RemovedCompenet Events to be
cleared earlier than they should be.

## Solution

- Don't call clear_trackers an extra time.

## Testing

I manually tested the fix with this unit test: 
```
#[cfg(test)]
mod test {
    use crate::core::{FrameCount, FrameCountPlugin};
    use crate::prelude::*;

    #[test]
    fn test_next_frame_removal() {
        #[derive(Component)]
        struct Foo;

        #[derive(Resource)]
        struct RemovedCount(usize);

        let mut app = App::new();
        app.add_plugins(FrameCountPlugin);
        app.add_systems(Startup, |mut commands: Commands| {
            for _ in 0..100 {
                commands.spawn(Foo);
            }
            commands.insert_resource(RemovedCount(0));
        });

        app.add_systems(First, |counter: Res<FrameCount>| {
            println!("Frame {}:", counter.0)
        });

        fn detector_system(
            mut removals: RemovedComponents<Foo>,
            foos: Query<Entity, With<Foo>>,
            mut removed_c: ResMut<RemovedCount>,
        ) {
            for e in removals.read() {
                println!("  Detected removed Foo component for {e:?}");
                removed_c.0 += 1;
            }
            let c = foos.iter().count();
            println!("  Total Foos: {}", c);
            assert_eq!(c + removed_c.0, 100);
        }
        fn deleter_system(foos: Query<Entity, With<Foo>>, mut commands: Commands) {
            foos.iter().next().map(|e| {
                commands.entity(e).remove::<Foo>();
            });
        }
        app.add_systems(Update, (detector_system, deleter_system).chain());

        app.update();
        app.update();
        app.update();
        app.update();
    }
}
```
2024-06-10 18:06:05 +00:00
Wuketuke
2c5959a29d
Added an illustration to the compass direction docs (issue 13664) (#13788)
i based the design on @mgi388 in the discussion about the issue.
i added the illustration in such a way that it shows up when you hover
your mouse over the type, i hope this is what was meant by the issue
no unit tests were added bc obviously

Fixes #13664
2024-06-10 17:31:11 +00:00
Periwink
93f3432400
Update serialize flag for bevy_ecs (#13740)
# Objective

There were some issues with the `serialize` feature:
- `bevy_app` had a `serialize` feature and a dependency on `serde` even
there is no usage of serde at all inside `bevy_app`
- the `bevy_app/serialize` feature enabled `bevy_ecs/serde`, which is
strange
- `bevy_internal/serialize` did not enable `bevy_app/serialize` so there
was no way of serializing an Entity in bevy 0.14

## Solution

- Remove `serde` and `bevy_app/serialize` 
- Add a `serialize` flag on `bevy_ecs` that enables `serde`
- ` bevy_internal/serialize` now enables `bevy_ecs/serialize`
2024-06-10 16:37:59 +00:00
T.J. Given
70a38ab1f6
Re-name and Extend Run Conditions API (#13784)
# Objective

- My attempt at fulfilling #13629.

## Solution

Renames the `and_then` / `or_else` run condition methods to `and` /
`or`, respectively.

Extends the run conditions API to include a suite of binary logical
operators:
- `and`
- `or`
- `nand`
- `nor`
- `xor`
- `xnor`

## Testing

- Did you test these changes? If so, how?
- The test **run_condition_combinators** was extended to include the
added run condition combinators. A **double_counter** system was added
to test for combinators running on even count cycles.

- Are there any parts that need more testing?
- I'm not too sure how I feel about the "counter" style of testing but I
wanted to keep it consistent. If it's just a unit test I would prefer
simply to just assert `true` == _combinator output_ or `false` ==
_combinator output_ .

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Nothing too specific. The added methods should be equivalent to the
logical operators they are analogous to (`&&` , `||`, `^`, `!`).

- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
    - Should not be relevant, I'm using Windows.

## Changelog

- What changed as a result of this PR?
    - The run conditions API.

- If applicable, organize changes under "Added", "Changed", or "Fixed"
sub-headings
    - Changed:
        - `and_then` run condition combinator renamed to simply `and`
        - `or_else` run condition combinator renamed to simply `or`
    - Added:
        - `nand` run condition combinator.
        - `nor` run condition combinator.
        - `xor` run condition combinator.
        - `xnor` run condition combinator.

## Migration Guide

- The `and_then` run condition method has been replaced with the `and`
run condition method.
- The `or_else` run condition method has been replaced with the `or` run
condition method.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Andres O. Vela <andresovela@users.noreply.github.com>
2024-06-10 13:41:56 +00:00
IceSentry
5134272dc9
Make FOG_ENABLED a shader_def instead of material flag (#13783)
# Objective

- If the fog is disabled it still generates a useless branch which can
hurt performance

## Solution

- Make the flag a shader_def instead

## Testing

- I tested enabling/disabling fog works as expected per-material in the
fog example
- I also tested that scenes that don't add the FogSettings resource
still work correctly

## Review notes

I'm not sure how to handle the removed material flag. Right now I just
commented it out and added a not to reuse it instead of creating a new
one.
2024-06-10 13:26:43 +00:00
Lee-Orr
7ec301c48d
fix docs around StateTransition and remove references to `apply_sta… (#13772)
The documentation for the `State` resource still referenced the use of
`apply_state_transition` to manually force a state transition to occur,
and the question around how to force transitions had come up a few times
on discord.

This is a docs-only change, that does the following:
- Properly references `StateTransition` in the `MainSchedule` docs
- replace the explanations for applying `NextState` with ones that
explain the `StateTransition` schedule, and mentions the possibility of
calling it manually
- Add an example of calling `StateTransition` manually in the docs for
the state transition schedule itself.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-10 13:23:14 +00:00
Isaïe
2356276afd
Clarify error message due to missing shader file (#13766)
# Objective

The error printed-out due to a missing shader file was confusing; This
PR changes the error message.

Fixes #13644 

## Solution

I replaced the confusing wording (`... shader is not loaded yet`) with a
clear explanation (`... shader could not be loaded`)

## Testing

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

removing `assets/shaders/game_of_life.wgsl` & running its associated
example now produces the following error:

```
thread '<unnamed>' panicked at examples/shader/compute_shader_game_of_life.rs:233:25:
Initializing assets/shaders/game_of_life.wgsl:
Pipeline could not be compiled because the following shader could not be loaded: AssetId<bevy_render::render_resource::shader::Shader>{ index: 0, generation: 0}
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_render::renderer::render_system`!
```

I don't think there are any tests expecting the previous error message,
so this change should not break anything.

> Are there any parts that need more testing?

If there was an intent behind the original message, this might need more
attention.

> How can other people (reviewers) test your changes? Is there anything
specific they need to know?

One should be able to preview the changes by running any example after
deleting/renaming their associated shader(s).

> If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

N/A
2024-06-10 13:15:54 +00:00
MiniaczQ
6d0b7504a2
Add more granular system sets for state transition schedule ordering (#13763)
# Objective

Fixes #13711 

## Solution

Introduce smaller, generic system sets for each schedule variant, which
are ordered against other generic variants:
- `ExitSchedules<S>` - For `OnExit` schedules, runs from leaf states to
root states.
- `TransitionSchedules<S>` - For `OnTransition` schedules, runs in
arbitrary order.
- `EnterSchedules<S>` - For `OnEnter` schedules, runs from root states
to leaf states.

Also unified `ApplyStateTransition<S>` schedule which works in basically
the same way, just for internals.

## Testing

- One test that tests schedule execution order

---------

Co-authored-by: Lee-Orr <lee-orr@users.noreply.github.com>
2024-06-10 13:13:58 +00:00
JMS55
50ee483665
Meshlet misc (#13761)
- Copy module docs so that they show up in the re-export
- Change meshlet_id to cluster_id in the debug visualization
- Small doc tweaks
2024-06-10 13:06:08 +00:00
Gagnus
298b01f10d
Adds back in way to convert color to u8 array, implemented for the two RGB color types, also renames Color::linear to Color::to_linear. (#13759)
# Objective

One thing missing from the new Color implementation in 0.14 is the
ability to easily convert to a u8 representation of the rgb color.

(note this is a redo of PR https://github.com/bevyengine/bevy/pull/13739
as I needed to move the source branch

## Solution

I have added to_u8_array and to_u8_array_no_alpha to a new trait called
ColorToPacked to mirror the f32 conversions in ColorToComponents and
implemented the new trait for Srgba and LinearRgba.
To go with those I also added matching from_u8... functions and
converted a couple of cases that used ad-hoc implementations of that
conversion to use these.
After discussion on Discord of the experience of using the API I renamed
Color::linear to Color::to_linear, as without that it looks like a
constructor (like Color::rgb).
I also added to_srgba which is the other commonly converted to type of
color (for UI and 2D) to match to_linear.
Removed a redundant extra implementation of to_f32_array for LinearColor
as it is also supplied in ColorToComponents (I'm surprised that's
allowed?)

## Testing

Ran all tests and manually tested.
Added to_and_from_u8 to linear_rgba::tests

## Changelog

visible change is Color::linear becomes Color::to_linear.

---------

Co-authored-by: John Payne <20407779+johngpayne@users.noreply.github.com>
2024-06-10 13:03:46 +00:00
JMS55
c50a4d8821
Remove unused mip_bias parameter from apply_normal_mapping (#13752)
Mip bias is no longer used here
2024-06-10 13:00:34 +00:00
Joseph
0dfdd87248
Improve error handling for AssetServer::add_async (#13745)
# Objective

The method `AssetServer::add_async` (added in
https://github.com/bevyengine/bevy/pull/13700) requires a future that
returns an `AssetLoadError` error, which was a bit of an oversight on my
part, as that type of error only really makes sense in the context of
bevy's own asset loader -- returning it from user-defined futures isn't
very useful.

## Solution

Allow passing custom error types to `add_async`, which get cast into a
trait object matching the form of `AssetLoader::load`. If merged before
the next release this will not be a breaking change
2024-06-10 12:56:21 +00:00
Matty
a569b35c18
Stable interpolation and smooth following (#13741)
# Objective

Partially address #13408 

Rework of #13613

Unify the very nice forms of interpolation specifically present in
`bevy_math` under a shared trait upon which further behavior can be
based.

The ideas in this PR were prompted by [Lerp smoothing is broken by Freya
Holmer](https://www.youtube.com/watch?v=LSNQuFEDOyQ).

## Solution

There is a new trait `StableInterpolate` in `bevy_math::common_traits`
which enshrines a quite-specific notion of interpolation with a lot of
guarantees:
```rust
/// A type with a natural interpolation that provides strong subdivision guarantees.
///
/// Although the only required method is `interpolate_stable`, many things are expected of it:
///
/// 1. The notion of interpolation should follow naturally from the semantics of the type, so
///    that inferring the interpolation mode from the type alone is sensible.
///
/// 2. The interpolation recovers something equivalent to the starting value at `t = 0.0`
///    and likewise with the ending value at `t = 1.0`.
///
/// 3. Importantly, the interpolation must be *subdivision-stable*: for any interpolation curve
///    between two (unnamed) values and any parameter-value pairs `(t0, p)` and `(t1, q)`, the
///    interpolation curve between `p` and `q` must be the *linear* reparametrization of the original
///    interpolation curve restricted to the interval `[t0, t1]`.
///
/// The last of these conditions is very strong and indicates something like constant speed. It
/// is called "subdivision stability" because it guarantees that breaking up the interpolation
/// into segments and joining them back together has no effect.
///
/// Here is a diagram depicting it:
/// ```text
/// top curve = u.interpolate_stable(v, t)
///
///              t0 => p   t1 => q    
///   |-------------|---------|-------------|
/// 0 => u         /           \          1 => v
///              /               \
///            /                   \
///          /        linear         \
///        /     reparametrization     \
///      /   t = t0 * (1 - s) + t1 * s   \
///    /                                   \
///   |-------------------------------------|
/// 0 => p                                1 => q
///
/// bottom curve = p.interpolate_stable(q, s)
/// ```
///
/// Note that some common forms of interpolation do not satisfy this criterion. For example,
/// [`Quat::lerp`] and [`Rot2::nlerp`] are not subdivision-stable.
///
/// Furthermore, this is not to be used as a general trait for abstract interpolation.
/// Consumers rely on the strong guarantees in order for behavior based on this trait to be
/// well-behaved.
///
/// [`Quat::lerp`]: crate::Quat::lerp
/// [`Rot2::nlerp`]: crate::Rot2::nlerp
pub trait StableInterpolate: Clone {
    /// Interpolate between this value and the `other` given value using the parameter `t`.
    /// Note that the parameter `t` is not necessarily clamped to lie between `0` and `1`.
    /// When `t = 0.0`, `self` is recovered, while `other` is recovered at `t = 1.0`,
    /// with intermediate values lying between the two.
    fn interpolate_stable(&self, other: &Self, t: f32) -> Self;
}
```

This trait has a blanket implementation over `NormedVectorSpace`, where
`lerp` is used, along with implementations for `Rot2`, `Quat`, and the
direction types using variants of `slerp`. Other areas may choose to
implement this trait in order to hook into its functionality, but the
stringent requirements must actually be met.

This trait bears no direct relationship with `bevy_animation`'s
`Animatable` trait, although they may choose to use `interpolate_stable`
in their trait implementations if they wish, as both traits involve
type-inferred interpolations of the same kind. `StableInterpolate` is
not a supertrait of `Animatable` for a couple reasons:
1. Notions of interpolation in animation are generally going to be much
more general than those allowed under these constraints.
2. Laying out these generalized interpolation notions is the domain of
`bevy_animation` rather than of `bevy_math`. (Consider also that
inferring interpolation from types is not universally desirable.)

Similarly, this is not implemented on `bevy_color`'s color types,
although their current mixing behavior does meet the conditions of the
trait.

As an aside, the subdivision-stability condition is of interest
specifically for the [Curve
RFC](https://github.com/bevyengine/rfcs/pull/80), where it also ensures
a kind of stability for subsampling.

Importantly, this trait ensures that the "smooth following" behavior
defined in this PR behaves predictably:
```rust
    /// Smoothly nudge this value towards the `target` at a given decay rate. The `decay_rate`
    /// parameter controls how fast the distance between `self` and `target` decays relative to
    /// the units of `delta`; the intended usage is for `decay_rate` to generally remain fixed,
    /// while `delta` is something like `delta_time` from an updating system. This produces a
    /// smooth following of the target that is independent of framerate.
    ///
    /// More specifically, when this is called repeatedly, the result is that the distance between
    /// `self` and a fixed `target` attenuates exponentially, with the rate of this exponential
    /// decay given by `decay_rate`.
    ///
    /// For example, at `decay_rate = 0.0`, this has no effect.
    /// At `decay_rate = f32::INFINITY`, `self` immediately snaps to `target`.
    /// In general, higher rates mean that `self` moves more quickly towards `target`.
    ///
    /// # Example
    /// ```
    /// # use bevy_math::{Vec3, StableInterpolate};
    /// # let delta_time: f32 = 1.0 / 60.0;
    /// let mut object_position: Vec3 = Vec3::ZERO;
    /// let target_position: Vec3 = Vec3::new(2.0, 3.0, 5.0);
    /// // Decay rate of ln(10) => after 1 second, remaining distance is 1/10th
    /// let decay_rate = f32::ln(10.0);
    /// // Calling this repeatedly will move `object_position` towards `target_position`:
    /// object_position.smooth_nudge(&target_position, decay_rate, delta_time);
    /// ```
    fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32) {
        self.interpolate_stable_assign(target, 1.0 - f32::exp(-decay_rate * delta));
    }
```

As the documentation indicates, the intention is for this to be called
in game update systems, and `delta` would be something like
`Time::delta_seconds` in Bevy, allowing positions, orientations, and so
on to smoothly follow a target. A new example, `smooth_follow`,
demonstrates a basic implementation of this, with a sphere smoothly
following a sharply moving target:


https://github.com/bevyengine/bevy/assets/2975848/7124b28b-6361-47e3-acf7-d1578ebd0347


## Testing

Tested by running the example with various parameters.
2024-06-10 12:50:59 +00:00
Lynn
1196186257
Add segments to ExtrusionBuilder (#13719)
# Objective

- Add support for `segments` for extrusion-meshes, akin to what is
possible with cylinders

## Solution

- Added a `.segments(segments: usize)` function to `ExtrusionBuilder`.
- Implemented support for segments in the meshing algorithm.
- If you set `.segments(0)`, the meshing will fail, just like it does
with cylinders.

## Additional information

Here is a wireframe of some extrusions with 1, 2, 3, etc. segments:

![image_2024-06-06_233205114](https://github.com/bevyengine/bevy/assets/62256001/358081e2-172d-407b-8bdb-9cda88eb4664)

---------

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
2024-06-10 12:50:29 +00:00
Dmytro Banin
1f61c26d2e
Align Scene::write_to_world_with to match DynamicScene::write_to_world_with (#13714)
# Objective

`Scene` and `DynamicScene` work with `InstanceInfo` at different levels
of abstraction
- `Scene::write_to_world_with` returns an `InstanceInfo` whereas
`DynamicScene::write_to_world_with` returns `()`. Instances are created
one level higher at the `SceneSpawner` API level.
- `DynamicScene::write_to_world_with` takes the `entity_map` as an
argument whereas the `Scene` version is less flexible and creates a new
one for you. No reason this needs to be the case.

## Solution

I propose changing `Scene::write_to_world_with` to match the API we have
for `DynamicScene`. Returning the `InstanceInfo` as we do today just
seems like a leaky abstraction - it's only used in
`spawn_sync_internal`. Being able to pass in an entity_map gives you
more flexibility with how you write entities to a world.

This also moves `InstanceInfo` out of `Scene` which is cleaner
conceptually. If someone wants to work with instances then they should
work with `SceneSpawner` - I see `write_to_world_with` as a lower-level
API to be used with exclusive world access.

## Testing

Code is just shifting things around.

## Changelog

Changed `Scene::write_to_world_with` to take `entity_map` as an argument
and no longer return an `InstanceInfo`

## Migration Guide

`Scene::write_to_world_with` no longer returns an `InstanceInfo`. 

Before
```rust
scene.write_to_world_with(world, &registry)
```
After
```rust
let mut entity_map = EntityHashMap::default();
scene.write_to_world_with(world, &mut entity_map, &registry)
```
2024-06-10 12:39:35 +00:00
Jan Hohenheim
1b9edd0e5b
Fix minor doc typo (#13776)
Don't think any description is needed, just happened to stumble on this
while reading up on how to use `Stopwatch` :)
2024-06-10 07:15:38 +00:00
Niklas Eicker
69d7da9b37
Let init_non_send_resource require FromWorld instead of Default (#13779)
# Objective

- Let `init_non_send_resource` take `FromWorld` values again, not only
`Default`
- This reverts an unintended breaking change introduced in #9202

## Solution

- The resource initialized with `init_non_send_resource` requires
`FromWorld` again
2024-06-10 07:10:52 +00:00
thebluefish
7c9c6ff27f
Fix EntityCommands::despawn docs (#13774)
# Objective

The `EntityCommands::despawn` method was previously changed from
panicking behavior to a warning, but the docs continue to state that it
panics.

## Solution

- Removed panic section, copied warning blurb from `World::despawn`
- Adds a similar warning blurb to
`DespawnRecursiveExt::despawn_recursive` and
`DespawnRecursiveExt::despawn_descendants`
2024-06-09 17:59:19 +00:00
Chris Biscardi
b9e67bc3c3
view.inverse_clip_from_world should be world_from_clip (#13756)
As per the other changes in
https://github.com/bevyengine/bevy/pull/13489
`view.inverse_clip_from_world` should be `world_from_clip`.



# Objective

fixes #13749

## Solution

Modified lines.wgsl to use the right name as the current name does not
exist.

## Testing

I ran the 3d_gizmos example and pressed "p".

![screenshot-2024-06-08-at-13 21
22@2x](https://github.com/bevyengine/bevy/assets/551247/b8bfd3db-8273-4606-9dae-040764339883)

![screenshot-2024-06-08-at-13 21
26@2x](https://github.com/bevyengine/bevy/assets/551247/2619f1ae-ce83-44d7-a9fc-07e686950887)
2024-06-09 14:40:14 +00:00
Vitaliy Sapronenko
e9a3a0d694
Clear messed up feature flag on AppExitStates impl (#13737)
# Objective

- In #13649 additional method had been added to AppExitStates, but there
feature gate left for method in implementation for App at refactoring
stage.
- Fixes #13733 .

## Solution

- Removed the feature gate.

## Testing

- Ran reproducing example from #13733 with no compilation errors
2024-06-09 13:49:03 +00:00
charlotte
7b14b8c015
13743 app exit hang (#13744)
Fixes #13743.

---------

Co-authored-by: Brezak <bezak.adam@proton.me>
2024-06-08 21:42:01 +00:00
Zachary Harrold
3bfc427666
Add mappings to EntityMapper (#13727)
# Objective

- Fixes #13703

## Solution

- Added `mappings` to the `EntityMapper` trait, which returns an
iterator over currently tracked `Entity` to `Entity` mappings.
- Added `DynEntityMapper` as an [object
safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety)
alternative to `EntityMapper`.
- Added `assert_object_safe` as a helper for ensuring traits are object
safe.

## Testing

- Added new unit test `entity_mapper_iteration` which tests the
`SceneEntityMapper` implementation of `EntityMapper::mappings`.
- Added unit tests to ensure `DynEntityMapper`, `DynEq` and `DynHash`
are object safe.
- Passed CI on my Windows 10 development environment

---

## Changelog

- Added `mappings` to `EntityMapper` trait.

## Migration Guide

- If you are implementing `EntityMapper` yourself, you can use the below
as a stub implementation:

```rust
fn mappings(&self) -> impl Iterator<Item = (Entity, Entity)> {
    unimplemented!()
}
```

- If you were using `EntityMapper` as a trait object (`dyn
EntityMapper`), instead use `dyn DynEntityMapper` and its associated
methods.

## Notes

- The original issue proposed returning a `Vec` from `EntityMapper`
instead of an `impl Iterator` to preserve its object safety. This is a
simpler option, but also forces an allocation where it isn't strictly
needed. I've opted for this split into `DynEntityMapper` and
`EntityMapper` as it's been done several times across Bevy already, and
provides maximum flexibility to users.
- `assert_object_safe` is an empty function, since the assertion
actually happens once you try to use a `dyn T` for some trait `T`. I
have still added this function to clearly document what object safety is
within Bevy, and to create a standard way to communicate that a given
trait must be object safe.
- Other traits should have tests added to ensure object safety, but I've
left those off to avoid cluttering this PR further.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-08 12:52:23 +00:00
Jerome Humbert
d38d8a148a
Uncouple DynamicTextureAtlasBuilder from assets (#13717)
# Objective

Remove some unnecessary coupling between `DynamicTextureAtlasBuilder`
and `bevy_asset`.

## Solution

Remove the dependency of `DynamicTextureAtlasBuilder::add_texture` to
`bevy_asset`, by directly passing the `Image` of the atlas to mutate,
instead of passing separate `Assets<Image>` and `Handle<Image>` for the
function to do the lookup by itself. The lookup can be done from the
caller, and this allows using the builder in contexts where the `Image`
is not stored inside `Assets`.

Clean-up a bit the font atlas files by introducing a `PlacedGlyph` type
storing the `GlyphId` and its `SubpixelOffset`, which were otherwise
always both passed as function parameters and the pair used as key in
hash maps.

## Testing

There's no change in behavior.

---

## Changelog

- Added a `PlacedGlyph` type aggregating a `GlyphId` and a
`SubpixelOffset`. That type is now used as parameter in a few text atlas
APIs, instead of passing individual values.

## Migration Guide

- Replace the `glyph_id` and `subpixel_offset` of a few text atlas APIs
by a single `place_glyph: PlacedGlyph` parameter trivially combining the
two.
2024-06-08 12:38:03 +00:00
Mincong Lu
651f3d08d7
Make the component types of the new animation players clonable. (#13736)
# Objective

Some use cases might require holding onto the previous state of the
animation player for change detection.

## Solution

Added `clone` and `copy` implementation to most animation types. 
Added optimized `clone_from` implementations for the specific use case
of holding a `PreviousAnimationPlayer` component.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-07 21:51:24 +00:00
Wuketuke
d45bcfd043
improved the error message by insert_boxed (issue #13646) (again) (#13706)
previously I worked on fixing issue #13646, back when the error message
did not include the type at all.
But that error message had room for improvement, so I included the
feedback of @alice-i-cecile and @MrGVSV.
The error message will now read `the given key (of type
bevy_reflect::tests::Foo) does not support hashing` or 'the given key
(of type bevy_reflect::DynamicStruct) does not support hashing' in case
of a dynamic struct that represents a hashable struct

i also added a new unit test for this new behaviour
(`reflect_map_no_hash_dynamic`).
Fixes #13646 (again)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-06-07 20:56:16 +00:00
François Mockers
b17292f9d1
rename the crate bevy_state_macros_official back to its original name (#13732)
# Objective

- Thanks to the original author we can now use the original name

## Solution

- Use it
2024-06-07 12:49:21 +00:00
François Mockers
98bc5ff8c4
Update crate metadata for bevy state (#13722)
# Objective

- crate metadata for bevy_state has been copied from bevy_ecs

## Solution

- Update it
2024-06-07 01:54:53 +00:00
François Mockers
401234a5fb
rename bevy_state_macros to bevy_state_macros_official (#13721)
# Objective

- `bevy_state_macros` is a new crate added in the 0.14
- it already exists outside of the bevy org:
https://crates.io/crates/bevy_state_macros

## Solution

- Rename the crate
2024-06-06 22:18:05 +00:00
charlotte
027f8e21ec
Allow mix of hdr and non-hdr cameras to same render target (#13419)
Changes:
- Track whether an output texture has been written to yet and only clear
it on the first write.
- Use `ClearColorConfig` on `CameraOutputMode` instead of a raw
`LoadOp`.
- Track whether a output texture has been seen when specializing the
upscaling pipeline and use alpha blending for extra cameras rendering to
that texture that do not specify an explicit blend mode.

Fixes #6754

## Testing

Tested against provided test case in issue:

![image](https://github.com/bevyengine/bevy/assets/10366310/d066f069-87fb-4249-a4d9-b6cb1751971b)

---

## Changelog

- Allow cameras rendering to the same output texture with mixed hdr to
work correctly.

## Migration Guide

- - Change `CameraOutputMode` to use `ClearColorConfig` instead of
`LoadOp`.
2024-06-06 20:55:05 +00:00
Rob Parrett
cca0f79022
Fix links to Transform in Transform and GlobalTransform docs (#13704)
# Objective

All the links that should go to the `Transform` type in the `Transform`
and `GlobalTransform` docs currently go to the `transform` example
instead.

## Solution

Fix collision of link labels in `Transform` and `GlobalTransform` docs.
2024-06-06 20:06:54 +00:00
Brandon Reinhart
3122c87702
Provide more information when a filewatcher failure is hit. (#13715)
A naked unwrap led to an opaque error that can be hit when using the
embedded filewatcher.

I've changed this an unwrap_or_else panic! with the error message
providing more details about the failed operation.

A better solution would be to print an error! and not panic...

This was tested with the asset_processing example.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-06 19:20:07 +00:00
IceSentry
f7ae277025
Use TBN in apply_normal_mapping in pbr_prepass (#13716)
# Objective

- apply_normal_mapping was changed to use TBN but the pbr_prepass was
not updated for that change

## Solution

- Update the pbr_prepass to correctly apply normal mapping
2024-06-06 19:04:30 +00:00
JMS55
175e146228
Misc meshlet changes (#13705)
* Rename cull_meshlets -> cull_clusters
* Rename meshlet_visible -> cluster_visible
* Add an if statement around meshlet_second_pass_candidates writes,
maybe a small bit of performance.
2024-06-06 17:10:07 +00:00
Mincong Lu
31be32ff10
Made Mesh::merge take a reference of Mesh. (#13710)
# Objective

`Mesh::merge` does not need ownership of the right hand side mesh.

## Solution

Made `Mesh::merge` take a reference.

## Testing

Modified existing tests.

---

## Changelog

Made `Mesh::merge` take a reference.


## Migration Guide

* `Mesh::merge` now take a reference of a mesh instead of an owned mesh.
2024-06-06 11:57:10 +00:00
Joseph
9389de5c71
Allow loading assets with custom async behavior (#13700)
# Objective

Currently, bevy supports custom asset loading via `AssetServer:;add`,
which allows you to add arbitrary assets to the asset system and returns
a handle to it. However this only works for assets that have already
been fully loaded. If your loading logic involves any async, you need to
wait until the asset is done loading before adding it to the server.
This is problematic, as the `Handle` does not get allocated until the
very end, which makes it very difficult to use and defeats the value of
having handles for asynchronously-loaded assets.

## Solution

Add the method `AssetServer::add_async`. This has the same behavior as
`AssetServer::add`, only it accepts a future instead of a fully loaded
asset.

## Testing

I added an identical method to my company's fork of bevy, which works in
our app. I'm not quite sure how to go about adding an actual unit test
for asset loading behvior, but I will note that `AssetServer::add` also
does not appear to have any tests.

---

## Changelog

+ Added `AssetServer::add_async`, which allows adding assets with custom
asynchronous loading behavior to the `AssetServer`
2024-06-06 00:21:59 +00:00
François Mockers
3d9b1e4025
make UI text rendering camera driven (#13697)
# Objective

- Fixes #13687 

## Solution

- Text rendering in UI is still dependent on the `PrimaryWIndow`
- implements #10559 for text rendering

There are other parts of UI that are still `PrimaryWindow` dependent, if
the changes here are OK I'll apply them everywhere.
I'm not a fan of the `EntityHashMap` here to hold the scale factors, but
it seems the quick and easy fix

## Testing

- Run example `multiple_windows` on a screen with a scale factor
different than 1, close the primary window
2024-06-06 00:20:50 +00:00
Mikhail Novikov
52215ce072
Add labels to Gltf Node and Mesh assets (#13558)
# Objective

Add labels to GltfNode and GltfMesh - they are missing from the assets
even though they are need if one wants to write a custom Gltf spawning
logic.

Eg AnimationPlayer relies on Name component of the node entities to
control the animation. There is no way to actually get names of the gltf
nodes, thus you can't manually spawn subtree from the scene and animate
it.

## Solution

- Add label field and make use of existing label creation logic to store
it there.

## Testing

- Ran all tests
- Fixed tests for node_hierarchy to use lable now

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-06-05 23:10:33 +00:00
Ricky Taylor
9a123cd3a7
Avoid a panic when loading labelled assets (#13506)
# Objective

- Fixes #10820.

## Solution

- Check that the asset ID to be inserted is still being managed.
- Since this route is only used by `AssetServer`-tracked handles, if the
`infos` map no longer contains the asset ID, all handles must have been
dropped. In this case, since nobody can be watching for the result,
we're safe to bail out. This avoids the panic when inserting the asset,
because when the handles are dropped, its slot in `Assets<A>` is
poisoned.
- Someone may be waiting for a labelled asset rather than the main
asset, these are handled with separate calls to `process_asset_load`, so
shouldn't cause any issues.
- Removed the workaround keeping asset info alive after the handle has
died, since we should no longer be trying to operate on any assets once
their handles have been dropped.

## Testing

- I added a `break` in `handle_internal_asset_events`
(`crates/bevy_asset/src/server/mod.rs` on line 1152). I don't believe
this should affect correctness, only efficiency, since it is effectively
only allowing one asset event to be handled per frame. This causes
examples like `animated_fox` to produce the issue fairly frequently.
- I wrote a small program which called `AssetServer::reload` and could
trigger it too.

---

## Changelog
- Fixed an issue which could cause a panic when loading an asset which
was no longer referenced.

---

## Remaining Work

~This needs more testing. I don't yet have a complete project that
reliably crashes without changes to bevy.~ We have at least one vote of
confidence so far from @Testare who had a project broken by this bug.

@cart, (sorry for the ping), I believe you added the code which delays
`remove_dropped`. Was there any other reason `track_assets` needed to
keep the dropped assets alive?
2024-06-05 23:04:52 +00:00
Alice Cecile
2165f2218f
Rename Rotation2d to Rot2 (#13694)
# Objective

- `Rotation2d` is a very long name for a commonly used type.

## Solution

- Rename it to `Rot2` to match `glam`'s naming convention (e.g. `Vec2`)

I ran a poll, and `Rot2` was the favorite of the candidate names.

This is not actually a breaking change, since `Rotation2d` has not been
shipped yet.

---------

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-06-05 21:51:13 +00:00
Wuketuke
2eb9d5cc38
hashing error in bevy_reflect now includes the type (bevyengine#13646) (#13691)
# Objective
If you try to add an object to the hashmap that is not capable of
hashing, the program panics. For easier debugging, the type for that
object should be included in the error message.

Fixes #13646.

## Solution
initially i tried calling std::any::type_name_of_val. this had the
problem that it would print something like dyn Box<dyn Reflect>, not
helpful. But since these objects all implement Reflect, i used
Reflect::type_path() instead. Previously, the error message was part of
a constant called HASH_ERROR. i changed that to a macro called
hash_error to print the type of that object more easily

## Testing
i adapted the unit test reflect_map_no_hash to expect the type in that
panic aswell

since this is my first contribution, please let me know if i have done
everything properly
2024-06-05 19:41:23 +00:00
Lynn
fb3a560a1c
Allow Bounded3d implementations for custom primitives (#13688)
# Objective

- Due to coherency, it was previously not possible to implement
`Bounded3d` for `Extrusion<MyCustomPrimitive>`. This PR fixes that.

## Solution

- Added a new trait `BoundedExtrusion: Primitive2d + Bounded2d` which
provides functions for bounding boxes and spheres of extrusions of 2D
primitives.
- Changed all implementations of `Bounded3d for Extrusion<T>` to
`BoundedExtrusion for T`
- Implemented `Bounded3d for Extrusion<T: BoundedExtrusion>`
- Removed the `extrusion_bounding_box` and `extrusion_bounding_sphere`
functions and used them as default implementations in `BoundedExtrusion`

## Testing

- This PR does not change any implementations

---------

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-06-05 19:40:02 +00:00
François Mockers
519abbca11
make sure windows are dropped on main thread (#13686)
# Objective

- On macOS, closing a window by respawning its entity freezes

## Solution

- `WindowWrapper` is keeping an `Arc` of the window, to be able to
access it from the rendering thread. Winit windows are closed when they
are dropped. This need to happen on the main thread on macOS
- Dropping it as soon as the window is closed means the last remaining
`Arc` will be in the rendering thread
- This PR keeps the `Arc` for one frame in the rendering thread before
actually dropping it
2024-06-05 18:13:59 +00:00
Matty
38d3833c83
Allow creation of random Rotation2d (#13684)
# Objective

Fill the gap in this functionality by implementing it for `Rotation2d`.
We have this already for `Quat` in addition to the direction types.

## Solution

`bevy_math::sampling` now contains an implementation of
`Distribution<Rotation2d>` for `Standard`, along with the associated
convenience implementation `Rotation2d: FromRng`, which allows syntax
like this for creating a random rotation:
```rust
// With `FromRng`:
let rotation = Rotation2d::from_rng(rng);
// With `rand::random`:
let another_rotation: Rotation2d = random();
// With `Rng::gen`:
let yet_another_rotation: Rotation2d = rng.gen();
```

I also cleaned up the documentation a little bit, seeding the `Rng`s
instead of building them from entropy, along with adding a handful of
inline directives.
2024-06-05 17:16:51 +00:00
Lukas Chodosevičius
2b20af6b79
Skip tonemapping in case it is none (#13679)
# Objective
Skip unnecessary blit then tonemapping is set to none.

## Testing
Only tested locally on our app.

## Changelog

Changed tonemapping not to execute in case it is set to none.

Co-authored-by: Lukas Chodosevicius <lukaschodosevicius@Lukass-MacBook-Pro.local>
2024-06-05 11:32:46 +00:00
mike
bd6acc6119
flush key_input cache when Bevy loses focus (Adopted) (#13678)
This was adopted from #12878. I rebased the changes resolved the
following merge conflicts:

- moved over the changes originally done in bevy_winit/src/lib.rs's
`handle_winit_event` into bevy_winit/src/state.rs's `window_event`
function
- moved WinitEvent::KeyboardFocusLost event forwarding originally done
in bevy_winit/src/winit_event.rs to the equivalent in
bevy_winit/src/state.rs

Tested this by following the modified keyboard_input example from the
original PR.

First, I verified I could reproduce the issue without the changes. Then,
after applying the changes, I verified that when I Alt+Tabbed away from
the running example that the log showed I released Alt and when I tabbed
back it didn't behave like Alt was stuck.

 
 The following is from the original pull request by @gavlig 
 
 # Objective
 
This helps avoiding stuck key presses after switching from and back to
Bevy window. Key press event gets stuck because window loses focus
before receiving a key release event thus we end up with false positive
in ButtonInput.
 ## Solution
 
 I saw two ways to fix this:
 
     1. add bevy_window as dependency and read WindowFocus events
 
     2. add a KeyboardFocusLost event specifically for this.
 
 
I chose the latter because adding another dependency felt wrong, but if
that is more preferable changing this pr won't be a problem. Also if
someone sees another way please let me know.
 
To test the bug use this small modification over
examples/keyboard_input.rs: (it will work only if you have Alt-Tab
combination for switching between windows in your OS, otherwise change
AltLeft accordingly)
 
 ```
 //! Demonstrates handling a key press/release.
 
 use bevy::{prelude::*, input:⌨️:KeyboardInput};
 
 fn main() {
     App::new()
         .add_plugins(DefaultPlugins)
         .add_systems(Update, keyboard_input_system)
         .run();
 }
 
 /// This system prints 'Alt' key state
fn keyboard_input_system(keyboard_input: Res<ButtonInput<KeyCode>>, mut
keyboard_input_events: EventReader<KeyboardInput>) {
     for event in keyboard_input_events.read() {
         info!("{:?}", event);
     }
 
     if keyboard_input.pressed(KeyCode::AltLeft) {
         info!("'Alt' currently pressed");
     }
 
     if keyboard_input.just_pressed(KeyCode::AltLeft) {
         info!("'Alt' just pressed");
     }
     if keyboard_input.just_released(KeyCode::AltLeft) {
         info!("'Alt' just released");
     }
 }
 ```
 
Here i made a quick video with demo of the fix:
https://youtu.be/qTvUCk4IHvo In first part i press Alt and Alt+Tab to
switch back and forth from example app, logs will indicate that too. In
second part I applied fix and you'll see that Alt will no longer be
pressed when window gets unfocused
 ## Migration Guide
 
 `WinitEvent` has a new enum variant: `WinitEvent::KeyboardFocusLost`.

Co-authored-by: gavlig <gavlig@gmail.com>
2024-06-05 02:06:47 +00:00
Lynn
8e4e840a19
Meshable extrusions - Part 2 (#13676)
# Objective

- Implement `Extrudable` for all meshbuilders of shapes that have been
added after #13478 was created

## Solution

- Implemented meshing for extrusions of `CircularSector`,
`CircularSegment` and `Rhombus`

## Testing

- The correctness of these was confirmed visually.

## Additional information

Here is an image of what they look like :)

![Screenshot 2024-06-04
230633](https://github.com/bevyengine/bevy/assets/62256001/d9cca0ba-30ea-4c48-8ae2-007b469739d7)

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
2024-06-04 21:53:06 +00:00
Brezak
1fdddf8992
Forward exit codes in default app runner (#13674)
# Objective

The default app runner fabricates exit codes loosing useful info in the
process.

## Solution

- Make run_once extract the correct exit code from app.
- Add a test to confirm it works.

## Testing

- Run the `runner_returns_correct_exit_code` test.
- Rejoice when it succeeds.
2024-06-04 21:40:40 +00:00
Lynn
fd82ef8956
Meshable extrusions (#13478)
# Objective

- Implement `Meshable` for `Extrusion<T>`

## Solution

- `Meshable` requires `Meshable::Output: MeshBuilder` now. This means
that all `some_primitive.mesh()` calls now return a `MeshBuilder`. These
were added for primitives that did not have one prior to this.
- A new trait `Extrudable: MeshBuilder` has been added. This trait
allows you to specify the indices of the perimeter of the mesh created
by this `MeshBuilder` and whether they are to be shaded smooth or flat.
- `Extrusion<P: Primitive2d + Meshable>` is now `Meshable` aswell. The
associated `MeshBuilder` is `ExtrusionMeshBuilder` which is generic over
`P` and uses the `MeshBuilder` of its baseshape internally.
- `ExtrusionMeshBuilder` exposes the configuration functions of its
base-shapes builder.
- Updated the `3d_shapes` example to include `Extrusion`s

## Migration Guide

- Depending on the context, you may need to explicitly call
`.mesh().build()` on primitives where you have previously called
`.mesh()`
- The `Output` type of custom `Meshable` implementations must now derive
`MeshBuilder`.

## Additional information
- The extrusions UVs are done so that 
- the front face (`+Z`) is in the area between `(0, 0)` and `(0.5,
0.5)`,
- the back face (`-Z`) is in the area between `(0.5, 0)` and `(1, 0.5)`
- the mantle is in the area between `(0, 0.5)` and `(1, 1)`. Each
`PerimeterSegment` you specified in the `Extrudable` implementation will
be allocated an equal portion of this area.
- The UVs of the base shape are scaled to be in the front/back area so
whatever method of filling the full UV-space the base shape used is how
these areas will be filled.

Here is an example of what that looks like on a capsule:


https://github.com/bevyengine/bevy/assets/62256001/425ad288-fbbc-4634-9d3f-5e846cdce85f

This is the texture used:

![extrusion
uvs](https://github.com/bevyengine/bevy/assets/62256001/4e54e421-bfda-44b9-8571-412525cebddf)

The `3d_shapes` example now looks like this:


![image_2024-05-22_235915753](https://github.com/bevyengine/bevy/assets/62256001/3d8bc86d-9ed1-47f2-899a-27aac0a265dd)

---------

Co-authored-by: Lynn Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
Co-authored-by: Matty <2975848+mweatherley@users.noreply.github.com>
2024-06-04 17:27:32 +00:00
Lynn
5e1c841f4e
Extrusion bounded (#13346)
# Objective

- Implement `Bounded3d` for some `Extrusion<T>`
- Provide methods to calculate `Aabb3d`s and `BoundingSphere`s for any
extrusion with a `Bounded2d` base shape

## Solution

- Implemented `Bounded3d` for all 2D `bevy_math` primitives with the
exception of `Plane2d`. As far as I can see, `Plane2d` is pretty much a
line? and I think it is very unintuitive to extrude a plane and get a
plane as a result.
- Add `extrusion_bounding_box` and `extrusion_bounding_sphere`. These
are not always used internally since there are faster methods for
specific extrusions. Both of them produce the optimal result within
precision limits though.

## Testing

- Bounds for extrusions are tested within the same module. All unique
implementations are tested.
- The correctness was validated visually aswell.

---------

Co-authored-by: Raphael Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
2024-06-04 17:25:12 +00:00
Patrick Walton
ace4c6023b
Implement subpixel morphological antialiasing, or SMAA. (#13423)
This commit implements a large subset of [*subpixel morphological
antialiasing*], better known as SMAA. SMAA is a 2011 antialiasing
technique that detects jaggies in an aliased image and smooths them out.
Despite its age, it's been a continual staple of games for over a
decade. Four quality presets are available: *low*, *medium*, *high*, and
*ultra*. I set the default to *high*, on account of modern GPUs being
significantly faster than they were in 2011.

Like the already-implemented FXAA, SMAA works on an unaliased image.
Unlike FXAA, it requires three passes: (1) edge detection; (2) blending
weight calculation; (3) neighborhood blending. Each of the first two
passes writes an intermediate texture for use by the next pass. The
first pass also writes to a stencil buffer in order to dramatically
reduce the number of pixels that the second pass has to examine. Also
unlike FXAA, two built-in lookup textures are required; I bundle them
into the library in compressed KTX2 format.

The [reference implementation of SMAA] is in HLSL, with abundant use of
preprocessor macros to achieve GLSL compatibility. Unfortunately, the
reference implementation predates WGSL by over a decade, so I had to
translate the HLSL to WGSL manually. As much as was reasonably possible
without sacrificing readability, I tried to translate line by line,
preserving comments, both to aid reviewing and to allow patches to the
HLSL to more easily apply to the WGSL. Most of SMAA's features are
supported, but in the interests of making this patch somewhat less huge,
I skipped a few of the more exotic ones:

* The temporal variant is currently unsupported. This is and has been
used in shipping games, so supporting temporal SMAA would be useful
follow-up work. It would, however, require some significant work on TAA
to ensure compatibility, so I opted to skip it in this patch.

* Depth- and chroma-based edge detection are unimplemented; only luma
is. Depth is lower-quality, but faster; chroma is higher-quality, but
slower. Luma is the suggested default edge detection algorithm. (Note
that depth-based edge detection wouldn't work on WebGL 2 anyway, because
of the Naga bug whereby depth sampling is miscompiled in GLSL. This is
the same bug that prevents depth of field from working on that
platform.)

* Predicated thresholding is currently unsupported.

* My implementation is incompatible with SSAA and MSAA, unlike the
original; MSAA must be turned off to use SMAA in Bevy. I believe this
feature was rarely used in practice.

The `anti_aliasing` example has been updated to allow experimentation
with and testing of the different SMAA quality presets. Along the way, I
refactored the example's help text rendering code a bit to eliminate
code repetition.

SMAA is fully supported on WebGL 2.

Fixes #9819.

[*subpixel morphological antialiasing*]: https://www.iryoku.com/smaa/

[reference implementation of SMAA]: https://github.com/iryoku/smaa

## Changelog

### Added

* Subpixel morphological antialiasing, or SMAA, is now available. To use
it, add the `SmaaSettings` component to your `Camera`.

![Screenshot 2024-05-18
134311](https://github.com/bevyengine/bevy/assets/157897/ffbd611c-1b32-4491-b2e2-e410688852ee)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-06-04 17:07:34 +00:00
IceSentry
d0e1b43402
Add binding() helper function to BufferVec (#13667)
# Objective

- Other render resources have a convenient `.binding()` helper function
to get the binding to the resource

## Solution

- Add the same thing to `BufferVec`, `RawBufferVec`, and
`UninitBufferVec`
2024-06-04 15:36:08 +00:00
Mason Boeman
2b6bfdb5ea
Add dynamic slice based variants of get_many_entities methods (#13584)
# Objective

Add slice based variants of existing `get_many_entities` functions on
`World`. This allows for a collection of entries to be looked up mutably
or immutably instead of requiring a compile time constant number.

## Solution

We just take slices and return Vectors.

the following functions have been added:
- `get_many_entities_dynamic`
- `get_many_entities_dynamic_mut`
- `get_many_entities_from_set_mut`

## Testing

- Doc tests, which pass when run through Miri
2024-06-04 15:29:51 +00:00
Matty
39609f1708
Dir2 -> Rotation2d conversions (#13670)
# Objective

Filling a hole in the API: Previously, there was no particularly
ergonomic way to go from, e.g., a pair of directions to the rotation
that links them.

## Solution

We introduce a small suite of API methods to `Dir2` to address this:
```rust
/// Get the rotation that rotates this direction to `other`.
pub fn rotation_to(self, other: Self) -> Rotation2d { //... }

/// Get the rotation that rotates `other` to this direction.
pub fn rotation_from(self, other: Self) -> Rotation2d { //... }

/// Get the rotation that rotates the X-axis to this direction.
pub fn rotation_from_x(self) -> Rotation2d { //... }

/// Get the rotation that rotates this direction to the X-axis.
pub fn rotation_to_x(self) -> Rotation2d { //... }

/// Get the rotation that rotates this direction to the Y-axis.
pub fn rotation_from_y(self) -> Rotation2d { //... }

/// Get the rotation that rotates the Y-axis to this direction.
pub fn rotation_to_y(self) -> Rotation2d { //... }
```

I also removed some language from the `Rotation2d` docs that is
misleading: the radian and angle conversion functions are already clear
about which angles they spit out, and `Rotation2d` itself doesn't have
any bounds on angles or anything.
2024-06-04 14:44:29 +00:00