Commit graph

6646 commits

Author SHA1 Message Date
Ricky Taylor
efcb6d6c11
Make LoadContext use the builder pattern for loading dependent assets (#13465)
# Objective
- Fixes #13445.

## Solution
- Removes all `load_` methods from `LoadContext`.
- Introduces `fn loader()` which returns a builder.

## Testing
- I've tested with `cargo test --package=bevy_asset` and run the two
relevant examples (`asset_processing` & `asset_decompression`).

---

## Changelog
- Replaced all `load_` methods on `LoadContext` with the new `loader()`
pattern.

## Migration Guide
- Several LoadContext method calls will need to be updated:
- `load_context.load_with_settings(path, settings)` =>
`load_context.loader().with_settings(settings).load(path)`
- `load_context.load_untyped(path)` =>
`load_context.loader().untyped().load(path)`
- `load_context.load_direct(path)` =>
`load_context.loader().direct().load(path)`
- `load_context.load_direct_untyped(path)` =>
`load_context.loader().direct().untyped().load(path)`
- `load_context.load_direct_with_settings(path, settings)` =>
`load_context.loader().with_settings(settings).direct().load(path)`
- `load_context.load_direct_with_reader(reader, path)` =>
`load_context.loader().direct().with_reader(reader).load(path)`
- `load_context.load_direct_with_reader_and_settings(reader, path,
settings)` =>
`load_context.loader().with_settings(settings).direct().with_reader(reader).load(path)`
- `load_context.load_direct_untyped_with_reader(reader, path)` =>
`load_context.loader().direct().with_reader(reader).untyped().load(path)`

---

CC @alice-i-cecile / @bushrat011899 

Examples:
```rust
load_context.loader()
    .with_asset_type::<A>()
    .with_asset_type_id(TypeId::of::<A>())
    .with_settings(|mut settings| { settings.key = value; })
    // Then, for a Handle<A>:
    .load::<A>()
    // Or, for a Handle<LoadedUntypedAsset>:
    .untyped()
    .load()
    // Or, to load an `A` directly:
    .direct()
    .load::<A>()
    .await
    // Or, to load an `ErasedLoadedAsset` directly:
    .direct()
    .untyped()
    .load()
    .await
```
2024-05-22 23:35:41 +00:00
Gino Valente
faf003fc9d
bevy_reflect: enum_utility cleanup (#13424)
# Objective

The `enum_utility` module contains the `get_variant_constructors`
function, which is used to generate token streams for constructing
enums. It's used for the `FromReflect::from_reflect` implementation and
the `Reflect::try_apply` implementation.

Due to the complexity of enums, this function is understandably a little
messy and difficult to extend.

## Solution

Clean up the `enum_utility` module.

Now "clean" is a bit subjective. I believe my solution is "cleaner" in
that the logic to generate the tokens are strictly coupled with the
intended usage. Because of this, `try_apply` is also no longer strictly
coupled with `from_reflect`.

This makes it easier to extend with new functionality, which is
something I'm doing in a future unrelated PR that I have based off this
one.

## Testing

There shouldn't be any testing required other than ensuring that the
project still builds and that CI passes.
2024-05-22 21:18:57 +00:00
Vic
c4cedb12c8
simple Debug impls for query iterators (#13476)
# Objective

The current query iterators cannot be used in positions with a `Debug`
bound.
F.e. when they are packaged in `Result` in the error position, `expect`
cannot be called on them.
Required for `QueryManyIter::entities_all_unique` in #13477.

## Solution

Add simple `Debug` impls that print the query iterator names.

## Changelog

`QueryIter`, `QueryManyIter`, `QueryCombinationIter`, and
`QuerySortedIter` now implement `Debug`.
2024-05-22 18:56:09 +00:00
Alice Cecile
dda7a744cf
Further improve docs for component hooks (#13475)
# Objective

While reviewing the other open hooks-related PRs, I found that the docs
on the `ComponentHooks` struct itself didn't give enough information
about how and why the feature could be used.

## Solution

1. Clean up the docs to add additional context.
2. Add a doc test demonstrating simple usage.

## Testing

The doc test passes locally.

---------

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-05-22 18:04:56 +00:00
Olle Lukowski
1ec5cdf3f2
Optimize the values for EMPTY rect. (#13470)
I am unsure if this needs changing, so let me know if I need to change
anything else.

# Objective

Fixes #13461.

## Solution

I applied the changes as suggested in the issue, and updated the doc
comments accordingly

## Testing

I don't think this needs too much testing, but there are no `cargo test`
failures.
2024-05-22 13:34:23 +00:00
Matty
5dbd827728
Annulus sampling (#13471)
# Objective

Add random sampling for the `Annulus` primitive. This is part of ongoing
work to bring the various `bevy_math` primitives to feature parity.

## Solution

`Annulus` implements `ShapeSample`. Boundary sampling is implemented in
the obvious way, and interior sampling works exactly as in the
implementation for `Circle`, using the fact that the square of the
radius should be taken uniformly from between r^2 and R^2, where r and R
are the inner and outer radii respectively.

## Testing

I generated a bunch of random points and rendered them. Here's 1000
points on the interior of the default annulus:
<img width="1440" alt="Screenshot 2024-05-22 at 8 01 34 AM"
src="https://github.com/bevyengine/bevy/assets/2975848/19c31bb0-edba-477f-b247-2b12d854afae">

This looks kind of weird around the edges, but I verified that they're
all actually inside the annulus, so I assume it has to do with the fact
that the rendered circles have some radius.
2024-05-22 13:13:04 +00:00
Matty
d2ef88f5e8
Add Distribution access methods for ShapeSample trait (#13315)
Stolen from #12835. 

# Objective

Sometimes you want to sample a whole bunch of points from a shape
instead of just one. You can write your own loop to do this, but it's
really more idiomatic to use a `rand`
[`Distribution`](https://docs.rs/rand/latest/rand/distributions/trait.Distribution.html)
with the `sample_iter` method. Distributions also support other useful
things like mapping, and they are suitable as generic items for
consumption by other APIs.

## Solution

`ShapeSample` has been given two new automatic trait methods,
`interior_dist` and `boundary_dist`. They both have similar signatures
(recall that `Output` is the output type for `ShapeSample`):
```rust
fn interior_dist(self) -> impl Distribution<Self::Output>
where Self: Sized { //... }
```

These have default implementations which are powered by wrapper structs
`InteriorOf` and `BoundaryOf` that actually implement `Distribution` —
the implementations effectively just call `ShapeSample::sample_interior`
and `ShapeSample::sample_boundary` on the contained type.

The upshot is that this allows iteration as follows:
```rust
// Get an iterator over boundary points of a rectangle:
let rectangle = Rectangle::new(1.0, 2.0);
let boundary_iter = rectangle.boundary_dist().sample_iter(rng);
// Collect a bunch of boundary points at once:
let boundary_pts: Vec<Vec2> = boundary_iter.take(1000).collect();
```

Alternatively, you can use `InteriorOf`/`BoundaryOf` explicitly to
similar effect:
```rust
let boundary_pts: Vec<Vec2> = BoundaryOf(rectangle).sample_iter(rng).take(1000).collect();
```

---

## Changelog

- Added `InteriorOf` and `BoundaryOf` distribution wrapper structs in
`bevy_math::sampling::shape_sampling`.
- Added `interior_dist` and `boundary_dist` automatic trait methods to
`ShapeSample`.
- Made `shape_sampling` module public with explanatory documentation.

---

## Discussion

### Design choices

The main point of interest here is just the choice of `impl
Distribution` instead of explicitly using `InteriorOf`/`BoundaryOf`
return types for `interior_dist` and `boundary_dist`. The reason for
this choice is that it allows future optimizations for repeated sampling
— for example, instead of just wrapping the base type,
`interior_dist`/`boundary_dist` could construct auxiliary data that is
held over between sampling operations.
2024-05-22 12:38:08 +00:00
Matty
c7f7d906ca
Tetrahedron mesh (#13463)
# Objective

Allow the `Tetrahedron` primitive to be used for mesh generation. This
is part of ongoing work to bring unify the capabilities of `bevy_math`
primitives.

## Solution

`Tetrahedron` implements `Meshable`. Essentially, each face is just
meshed as a `Triangle3d`, but first there is an inversion step when the
signed volume of the tetrahedron is negative to ensure that the faces
all actually point outward.

## Testing

I loaded up some examples and hackily exchanged existing meshes with the
new one to see that it works as expected.
2024-05-22 12:22:11 +00:00
Ida "Iyes
60afec2a00
Fix 2D looking blurry at odd window sizes (#13440)
# Objective

This is a long-standing bug that I have experienced since many versions
of Bevy ago, possibly forever. Today I finally wanted to report it, but
the fix was so easy that I just went and fixed it. :)

The problem is that 2D graphics looks blurry at odd-sized window
resolutions. This is with the **default** 2D camera configuration! The
issue will also manifest itself with any Orthographic Projection with
`ScalingMode::WindowSize` where the viewport origin is not at one of the
corners, such as the default where the origin point is at the center.

The issue happens because the Bevy orthographic projection origin point
is specified as a fraction to be multiplied by the size. For example,
the default (origin at center) is `(0.5, 0.5)`. When this value is
multiplied by the window size, it can result in fractional values for
the actual origin of the projection, thus placing the camera "between
pixels" and misaligning the entire pixel grid.

With the default value, this happens at odd-numbered window resolutions.
It is very easy to reproduce the issue by running any Bevy 2D app with a
resizable window, and slowly resizing the window pixel by pixel. As you
move the mouse to resize the window, you can see how the 2D graphics
inside the window alternate between "crisp, blurry, crisp, blurry, ...".
If you change the projection's origin to be at the corner (say, `(0.0,
0.0)`) and run the app again, the graphics always looks crisp,
regardless of window size.

Here are screenshots from **before** this PR, to illustrate the issue:

Even window size:

![Screenshot_20240520_165304](https://github.com/bevyengine/bevy/assets/40234599/52619281-cf5f-490e-b85e-22bc5f9af737)

Odd window size:

![Screenshot_20240520_165320](https://github.com/bevyengine/bevy/assets/40234599/27a3624c-f39e-4493-ade9-ca3533802083)


## Solution

The solution is easy: just round the computed origin values for the
projection.

To make it work reliably for the general case, I decided to:
- Only do it for `ScalingMode::WindowSize`, as it doesn't make sense for
other scaling modes.
- Round to the nearest multiple of the pixel scale, if it is not 1.0.
This ensures the "pixels" stay aligned even if scaled.

## Testing

I ran Bevy's examples as well as my own projects to ensure things look
correct. I set different values for the pixel scale to test the rounding
behavior and played around with resizing the window to verify that
everything is consistent.

---

## Changelog

Fixed:
- Orthographic projection now rounds the origin point if computed from
screen pixels, so that 2D graphics do not appear blurry at odd window
sizes.
2024-05-22 02:59:40 +00:00
James O'Brien
182fe3292e
Implement a SystemBuilder for building SystemParams (#13123)
# Objective

- Implement a general purpose mechanism for building `SystemParam`.
- Unblock the usage of dynamic queries in regular systems.

## Solution

- Implement a `SystemBuilder` type.

## Examples
Here are some simple test cases for the builder:
```rust
fn local_system(local: Local<u64>) -> u64 {
    *local
}

fn query_system(query: Query<()>) -> usize {
    query.iter().count()
}

fn multi_param_system(a: Local<u64>, b: Local<u64>) -> u64 {
    *a + *b + 1
}

#[test]
fn local_builder() {
    let mut world = World::new();

    let system = SystemBuilder::<()>::new(&mut world)
        .builder::<Local<u64>>(|x| *x = 10)
        .build(local_system);

    let result = world.run_system_once(system);
    assert_eq!(result, 10);
}

#[test]
fn query_builder() {
    let mut world = World::new();

    world.spawn(A);
    world.spawn_empty();

    let system = SystemBuilder::<()>::new(&mut world)
        .builder::<Query<()>>(|query| {
            query.with::<A>();
        })
        .build(query_system);

    let result = world.run_system_once(system);
    assert_eq!(result, 1);
}

#[test]
fn multi_param_builder() {
    let mut world = World::new();

    world.spawn(A);
    world.spawn_empty();

    let system = SystemBuilder::<()>::new(&mut world)
        .param::<Local<u64>>()
        .param::<Local<u64>>()
        .build(multi_param_system);

    let result = world.run_system_once(system);
    assert_eq!(result, 1);
}
```
This will be expanded as this PR is iterated.
2024-05-22 00:58:37 +00:00
Patrick Walton
a785e3c20d
Fix UI elements randomly not appearing after #13277. (#13462)
We invoked the `extract_default_ui_camera_view` system twice: once for
2D cameras and once for 3D cameras. This was fine before moving to
resources for render phases, but, after the move to resources, the first
thing such systems do is to clear out all the entities-to-be-rendered
from the previous frame. So, if the scheduler happened to run
`extract_default_ui_camera_view::<Camera2d>` first, then all the UI
elements that it queued would be overwritten by the
`extract_default_ui_camera_view::<Camera3d>` system, or vice versa. The
ordering dependence is the reason why this problem was intermittent.

This commit fixes the problem by merging the two systems into one
systems, using an `Or` query filter.

## Migration Guide

* The `bevy_ui::render::extract_default_ui_camera_view` system is no
longer parameterized over the specific type of camera and is hard-wired
to either `Camera2d` or `Camera3d` components.
2024-05-21 22:06:25 +00:00
SpecificProtagonist
6c95d54652
Fix doc for Added, Changed (#13458)
# Objective

Fixes #13426

## Solution

Correct documentation to describe current behavior

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-05-21 21:23:24 +00:00
Vitaliy Sapronenko
151e198d94
Add slerp function for Dir2, Dir3, Dir3A (#13451)
# Objective

- Fixes #13407 .

## Solution

- Used Quat and Rotation2d.

## Testing

- Added tests based on 0°, 30°, 45°, 60° and 90° angles
2024-05-21 21:13:32 +00:00
Martín Maita
f9da5eecf2
Rename Rect inset() method to inflate() (#13452)
# Objective

- Fixes #13092.

## Solution

- Renamed the `inset()` method in `Rect`, `IRect` and `URect` to
`inflate()`.
- Added `EMPTY` constants to all `Rect` variants, represented by corners
with the maximum numerical values for each kind.

---

## Migration Guide

- Replace `Rect::inset()`, `IRect::inset()` and `URect::inset()` calls
with `inflate()`.
2024-05-21 20:53:55 +00:00
François Mockers
5a1c62faae
fix lava emissive strength in depth of field example (#13449)
# Objective

- Since #13350 the lava is way too bright

![ba6ab328bc334085a237550e66ce91effa8950c7241ddef3eb10a8be336a68ef](https://github.com/bevyengine/bevy/assets/8672791/3a7aa7c0-5481-4616-8f84-2b69b57cf81c)

## Solution

- Change the emissive value in the material in the glb file from 20000
to 20

## Testing

- Run the example `depth_of_field`
2024-05-21 19:35:08 +00:00
Lynn
9ef9f3b3a4
Inconsistent segments/resolution naming (#13438)
# Objective

- Fixes #13412

## Solution

- Renamed `segments` in `bevy_gizmos` to `resolution` and adjusted
examples

## Migration Guide

- When working with gizmos, replace all calls to `.segments(...)` with
`.resolution(...)`
2024-05-21 18:42:59 +00:00
Matty
b7ec19bb2d
Tetrahedron sampling (#13430)
# Objective

Add interior and boundary sampling for the `Tetrahedron` primitive. This
is part of ongoing work to bring the primitives to parity with each
other in terms of their capabilities.

## Solution

`Tetrahedron` implements the `ShapeSample` trait. To support this, there
is a new public method `Tetrahedron::faces` which gets the faces of a
tetrahedron as `Triangle3d`s. There are more sophisticated ideas for
getting the faces we might want to consider in the future (e.g.
adjusting according to the orientation), but this method gives the most
mathematically straightforward answer, giving the faces the orientation
induced by the tetrahedron itself.
2024-05-21 18:40:03 +00:00
Vic
399fd23797
implement the full set of sort methods on QueryIter (#13417)
# Objective

Currently, a query iterator can be collected into a `Vec` and sorted,
but this can be quite unwieldy, especially when many `Component`s are
involved. The `itertools` crate helps somewhat, but the need to write a
closure over all of `QueryData`
can sometimes hurt ergonomics, anywhere from slightly to strongly. A key
extraction function only partially helps, as `sort_by_key` does not
allow returning non-`Copy` data. `sort_by` does not suffer from the
`Copy` restriction, but now the user has to write out a `cmp` function
over two `QueryData::Item`s when it could have just been handled by the
`Ord` impl for the key.
`sort` requires the entire `Iterator` Item to be `Ord`, which is rarely
usable without manual helper functionality. If the user wants to hide
away unused components with a `..` range, they need to track item tuple
order across their function. Mutable `QueryData` can also introduce
further complexity.
Additionally, sometimes users solely include `Component`s /`Entity` to
guarantee iteration order.

For a user to write a function to abstract away repeated sorts over
various `QueryData` types they use would require reaching for the
`all_tuples!` macro, and continue tracking tuple order afterwards.

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

## Solution

Custom sort methods on `QueryIter`, which take a query lens as a generic
argument, like `transmute_lens` in `Query`.
This allows users to choose what part of their queries they pass to
their sort function calls, serving as a kind of "key extraction
function" before the sort call. F.e. allowing users to implement `Ord`
for a Component, then call `query.iter().sort::<OrdComponent>()`

This works independent of mutability in `QueryData`, `QueryData` tuple
order, or the underlying `iter/iter_mut` call.
Non-`Copy` components could also be used this way, an internal
`Arc<usize>` being an example.
If `Ord` impls on components do not suffice, other sort methods can be
used. Notably useful when combined with `EntityRef` or `EntityMut`.
Another boon from using underlying `transmute` functionality, is that
with the [allowed
transmutes](http://dev-docs.bevyengine.org/bevy/ecs/prelude/struct.Query.html#allowed-transmutes),
it is possible to sort a `Query` with `Entity` even if it wasn't
included in the original `Query`.
The additional generic parameter on the methods other than `sort` and
`sort_unstable` currently cannot be removed due to Rust limitations,
however their types can be inferred.

The new methods do not conflict with the `itertools` sort methods, as
those use the "sorted" prefix.

This is implemented barely touching existing code. That change to
existing code being that `QueryIter` now holds on to the reference to
`UnsafeWorldCell` that is used to initialize it.
A lens query is constructed with `Entity` attached at the end, sorted,
and turned into an iterator. The iterator maps away the lens query,
leaving only an iterator of `Entity`, which is used by `QuerySortedIter`
to retrieve the actual items.
`QuerySortedIter` resembles a combination of `QueryManyIter` and
`QueryIter`, but it uses an entity list that is guaranteed to contain
unique entities, and implements `ExactSizeIterator`,
`DoubleEndedIterator`, `FusedIterator` regardless of mutability or
filter kind (archetypal/non-archetypal).

The sort methods are not allowed to be called after `next`, and will
panic otherwise. This is checked using `QueryIterationCursor` state,
which is unique on initialization. Empty queries are an exception to
this, as they do not return any item in the first place.
That is because tracking how many iterations have already passed would
require regressing either normal query iteration a slight bit, or sorted
iteration by a lot. Besides, that would not be the intended use of these
methods.

## Testing

To ensure that `next` being called before `sort` results in a panic, I
added some tests. I also test that empty `QueryIter`s do not exhibit
this restriction.

The query sorts test checks for equivalence to the underlying sorts.
This change requires that `Query<(Entity, Entity)>` remains legal, if
that is not already guaranteed, which is also ensured by the
aforementioned test.

## Next Steps

Implement the set of sort methods for `QueryManyIter` as well.
- This will mostly work the same, other than needing to return a new
`QuerySortedManyIter` to account for iteration
over lists of entities that are not guaranteed to be unique. This new
query iterator will need a bit of internal restructuring
to allow for double-ended mutable iteration, while not regressing
read-only iteration.

The implementations for each pair of 
- `sort`, `sort_unstable`, 
- `sort_by`, sort_unstable_by, 
- `sort_by_key,` `sort_by_cached_key`

are the same aside from the panic message and the sort call, so they
could be merged with an inner function.
That would require the use of higher-ranked trait bounds on
`WorldQuery::Item<'1>`, and is unclear to me whether it is currently
doable.

Iteration in QuerySortedIter might have space for improvement.
When sorting by `Entity`, an `(Entity, Entity)` lens `QueryData` is
constructed, is that worth remedying?
When table sorts are implemented, a fast path could be introduced to
these sort methods.

## Future Possibilities

Implementing `Ord` for EntityLocation might be useful.
Some papercuts in ergonomics can be improved by future Rust features:
- The additional generic parameter aside from the query lens can be
removed once this feature is stable:
    `Fn -> impl Trait` (`impl Trait` in `Fn` trait return position)
- With type parameter defaults, the query lens generic can be defaulted
to `QueryData::Item`, allowing the sort methods
to look and behave like `slice::sort` when no query lens is specified.
- With TAIT, the iterator generic on `QuerySortedIter` and thus the huge
visible `impl Iterator` type in the sort function
   signatures can be removed. 
- With specialization, the bound on `L` could be relaxed to `QueryData`
when the underlying iterator is mutable.

## Changelog

Added `sort`, `sort_unstable`, `sort_by`, `sort_unstable_by`,
`sort_by_key`, `sort_by_cached_key` to `QueryIter`.
2024-05-21 18:35:19 +00:00
Ricky Taylor
26df1c1179
Add more load_direct implementations (#13415)
# Objective
- Introduce variants of `LoadContext::load_direct` which allow picking
asset type & configuring settings.
- Fixes #12963.

## Solution
- Implements `ErasedLoadedAsset::downcast` and adds some accessors to
`LoadedAsset<A>`.
- Changes `load_direct`/`load_direct_with_reader` to be typed, and
introduces `load_direct_untyped`/`load_direct_untyped_with_reader`.
- Introduces `load_direct_with_settings` and
`load_direct_with_reader_and_settings`.

## Testing
- I've run cargo test and played with the examples which use
`load_direct`.
- I also extended the `asset_processing` example to use the new typed
version of `load_direct` and use `load_direct_with_settings`.

---

## Changelog
- Introduced new `load_direct` methods in `LoadContext` to allow
specifying type & settings

## Migration Guide
- `LoadContext::load_direct` has been renamed to
`LoadContext::load_direct_untyped`. You may find the new `load_direct`
is more appropriate for your use case (and the migration may only be
moving one type parameter).
- `LoadContext::load_direct_with_reader` has been renamed to
`LoadContext::load_direct_untyped_with_reader`.

---

This might not be an obvious win as a solution because it introduces
quite a few new `load_direct` alternatives - but it does follow the
existing pattern pretty well. I'm very open to alternatives.
😅
2024-05-21 18:32:00 +00:00
Lynn
2857eb6b9d
Fix normals during mesh scaling (#13380)
# Objective

- Fixes scaling normals and tangents of meshes

## Solution

- When scaling a mesh by `Vec3::new(1., 1., -1.)`, the normals should be
flipped along the Z-axis. For example a normal of `Vec3::new(0., 0.,
1.)` should become `Vec3::new(0., 0., -1.)` after scaling. This is
achieved by multiplying the normal by the reciprocal of the scale,
cheking for infinity and normalizing. Before, the normal was multiplied
by a covector of the scale, which is incorrect for normals.
- Tangents need to be multiplied by the `scale`, not its reciprocal as
before

---------

Co-authored-by: vero <11307157+atlv24@users.noreply.github.com>
2024-05-21 18:28:03 +00:00
Patrick Walton
9da0b2a0ec
Make render phases render world resources instead of components. (#13277)
This commit makes us stop using the render world ECS for
`BinnedRenderPhase` and `SortedRenderPhase` and instead use resources
with `EntityHashMap`s inside. There are three reasons to do this:

1. We can use `clear()` to clear out the render phase collections
instead of recreating the components from scratch, allowing us to reuse
allocations.

2. This is a prerequisite for retained bins, because components can't be
retained from frame to frame in the render world, but resources can.

3. We want to move away from storing anything in components in the
render world ECS, and this is a step in that direction.

This patch results in a small performance benefit, due to point (1)
above.

## Changelog

### Changed

* The `BinnedRenderPhase` and `SortedRenderPhase` render world
components have been replaced with `ViewBinnedRenderPhases` and
`ViewSortedRenderPhases` resources.

## Migration Guide

* The `BinnedRenderPhase` and `SortedRenderPhase` render world
components have been replaced with `ViewBinnedRenderPhases` and
`ViewSortedRenderPhases` resources. Instead of querying for the
components, look the camera entity up in the
`ViewBinnedRenderPhases`/`ViewSortedRenderPhases` tables.
2024-05-21 18:23:04 +00:00
BD103
53f4c38e7b
Fix lints on beta Rust (#13444)
# Objective

- Fixes #13437!

## Solution

- Use `f32::INFINITY` instead of `std::f32::INFINITY`.

## Testing

```shell
cargo +beta clippy --workspace --all-targets --all-features -- -Dwarnings
```
2024-05-20 20:40:59 +00:00
BD103
2940636e0a
Deprecate dynamic plugins (#13080)
# Objective

- The current implementation for dynamic plugins is unsound. Please see
#11969 for background and justification.
- Closes #11969 and closes #13073.

## Solution

- Deprecate all dynamic plugin items for Bevy 0.14, with plans to remove
them for Bevy 0.15.

## Discussion

One thing I want to make clear is that I'm not opposed to dynamic
plugins _in general_. I think they can be handy, especially for DLC and
modding, but I think the current system is the wrong approach. It's too
much of a footgun for the meager benefit is provides.

---

## Changelog

- Deprecated the current dynamic plugin system.
- Dynamic plugins will be removed in Bevy 0.15. For now you can continue
using them by marking your code with `#[allow(deprecated)]`.

## Migration Guide

If possible, remove all usage of dynamic plugins.

```rust
// Old
#[derive(DynamicPlugin)]
pub struct MyPlugin;

App::new()
    .load_plugin("path/to/plugin")
    .run();

// New
pub struct MyPlugin;

App::new()
    .add_plugins(MyPlugin)
    .run();
```

If you are unable to do that, you may temporarily silence the
deprecation warnings.

```rust
#[allow(deprecated)]
```

Please note that the current dynamic plugin system will be removed by
the next major Bevy release, so you will have to migrate eventually. You
may be interested in these safer alternatives:

- [Bevy Assets - Scripting]: Scripting and modding libraries for Bevy
- [Bevy Assets - Development tools]: Hot reloading and other development
functionality
- [`stabby`]: Stable Rust ABI

[Bevy Assets - Scripting]: https://bevyengine.org/assets/#scripting
[Bevy Assets - Development tools]:
https://bevyengine.org/assets/#development-tools
[`stabby`]: https://github.com/ZettaScaleLabs/stabby
2024-05-20 20:01:28 +00:00
Spooky Th Ghost
612e77ef78
Adds doc note that Timer and Stopwatch must be progressed manually (#13441)
# Objective
- Fix #13421 

## Solution

- Add an explicit note at the root of each struct that they must be
ticked manually

## Testing

- Generated the docs and the changes look good
---

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-05-20 19:46:25 +00:00
Gino Valente
5db52663b3
bevy_reflect: Custom attributes (#11659)
# Objective

As work on the editor starts to ramp up, it might be nice to start
allowing types to specify custom attributes. These can be used to
provide certain functionality to fields, such as ranges or controlling
how data is displayed.

A good example of this can be seen in
[`bevy-inspector-egui`](https://github.com/jakobhellermann/bevy-inspector-egui)
with its
[`InspectorOptions`](https://docs.rs/bevy-inspector-egui/0.22.1/bevy_inspector_egui/struct.InspectorOptions.html):

```rust
#[derive(Reflect, Default, InspectorOptions)]
#[reflect(InspectorOptions)]
struct Slider {
    #[inspector(min = 0.0, max = 1.0)]
    value: f32,
}
```

Normally, as demonstrated in the example above, these attributes are
handled by a derive macro and stored in a corresponding `TypeData`
struct (i.e. `ReflectInspectorOptions`).

Ideally, we would have a good way of defining this directly via
reflection so that users don't need to create and manage a whole proc
macro just to allow these sorts of attributes.

And note that this doesn't have to just be for inspectors and editors.
It can be used for things done purely on the code side of things.

## Solution

Create a new method for storing attributes on fields via the `Reflect`
derive.

These custom attributes are stored in type info (e.g. `NamedField`,
`StructInfo`, etc.).

```rust
#[derive(Reflect)]
struct Slider {
    #[reflect(@0.0..=1.0)]
    value: f64,
}

let TypeInfo::Struct(info) = Slider::type_info() else {
    panic!("expected struct info");
};

let field = info.field("value").unwrap();

let range = field.get_attribute::<RangeInclusive<f64>>().unwrap();
assert_eq!(*range, 0.0..=1.0);
```

## TODO

- [x] ~~Bikeshed syntax~~ Went with a type-based approach, prefixed by
`@` for ease of parsing and flexibility
- [x] Add support for custom struct/tuple struct field attributes
- [x] Add support for custom enum variant field attributes
- [x] ~~Add support for custom enum variant attributes (maybe?)~~ ~~Will
require a larger refactor. Can be saved for a future PR if we really
want it.~~ Actually, we apparently still have support for variant
attributes despite not using them, so it was pretty easy to add lol.
- [x] Add support for custom container attributes
- [x] Allow custom attributes to store any reflectable value (not just
`Lit`)
- [x] ~~Store attributes in registry~~ This PR used to store these in
attributes in the registry, however, it has since switched over to
storing them in type info
- [x] Add example

## Bikeshedding

> [!note]
> This section was made for the old method of handling custom
attributes, which stored them by name (i.e. `some_attribute = 123`). The
PR has shifted away from that, to a more type-safe approach.
>
> This section has been left for reference.

There are a number of ways we can syntactically handle custom
attributes. Feel free to leave a comment on your preferred one! Ideally
we want one that is clear, readable, and concise since these will
potentially see _a lot_ of use.

Below is a small, non-exhaustive list of them. Note that the
`skip_serializing` reflection attribute is added to demonstrate how each
case plays with existing reflection attributes.

<details>
<summary>List</summary>

##### 1. `@(name = value)`

> The `@` was chosen to make them stand out from other attributes and
because the "at" symbol is a subtle pneumonic for "attribute". Of
course, other symbols could be used (e.g. `$`, `#`, etc.).

```rust
#[derive(Reflect)]
struct Slider {
    #[reflect(@(min = 0.0, max = 1.0), skip_serializing)]
    #[[reflect(@(bevy_editor::hint = "Range: 0.0 to 1.0"))]
    value: f32,
}
```

##### 2. `@name = value`

> This is my personal favorite.

```rust
#[derive(Reflect)]
struct Slider {
    #[reflect(@min = 0.0, @max = 1.0, skip_serializing)]
    #[[reflect(@bevy_editor::hint = "Range: 0.0 to 1.0")]
    value: f32,
}
```

##### 3. `custom_attr(name = value)`

> `custom_attr` can be anything. Other possibilities include `with` or
`tag`.

```rust
#[derive(Reflect)]
struct Slider {
    #[reflect(custom_attr(min = 0.0, max = 1.0), skip_serializing)]
    #[[reflect(custom_attr(bevy_editor::hint = "Range: 0.0 to 1.0"))]
    value: f32,
}
```

##### 4. `reflect_attr(name = value)`

```rust
#[derive(Reflect)]
struct Slider {
    #[reflect(skip_serializing)]
    #[reflect_attr(min = 0.0, max = 1.0)]
    #[[reflect_attr(bevy_editor::hint = "Range: 0.0 to 1.0")]
    value: f32,
}
```

</details>

---

## Changelog

- Added support for custom attributes on reflected types (i.e.
`#[reflect(@Foo::new("bar")]`)
2024-05-20 19:30:21 +00:00
Vitaliy Sapronenko
2aed777435
Fixed incorrect behaviour of headless_renderer depending on image dimensions (#13388)
# Objective

- Fixes #13384 .

## Solution

- If the image became wider when copying from the texture to the buffer,
then the data is reduced to its original size when copying from the
buffer to the image.

## Testing

- Ran example with 1919x1080 resolution

![000](https://github.com/bevyengine/bevy/assets/17225606/47d95ed7-1c8c-4be4-a45a-1f485a3d6aa7)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-05-19 00:15:15 +00:00
IceSentry
bf2aced279
Remove another .view_layouts (#13410)
I forgot to save that file when submitting #13394 😅
2024-05-19 00:08:27 +00:00
Patrick Walton
846757cb38
Make the prepass shader compile when lightmaps are present. (#13402)
Commit 3f5a090b1b added a reference to
`STANDARD_MATERIAL_FLAGS_BASE_COLOR_UV_BIT`, a nonexistent identifier,
in the alpha discard portion of the prepass shader. Moreover, the logic
didn't make sense to me. I think the code was trying to choose between
the two UV sets depending on which is present, so I made it do that.

I noticed this when trying Bistro with #13277. I'm not sure why this
issue didn't manifest itself before, but it's clearly a bug, so here's a
fix. We should probably merge this before 0.14.
2024-05-18 22:28:31 +00:00
François Mockers
a55e0e31e8
fix normals computation for gltf (#13396)
# Objective

- some gltf files are broken since #13333 

```
thread 'IO Task Pool (2)' panicked at crates/bevy_render/src/mesh/mesh/mod.rs:581:9:
`compute_flat_normals` can't work on indexed geometry. Consider calling either `Mesh::compute_smooth_normals` or `Mesh::duplicate_vertices` followed by `Mesh::compute_flat_normals`.
```

- test with example `custom_gltf_vertex_attribute` or
`gltf_skinned_mesh`


## Solution

- Call the wrapper function for normals that will either call
`compute_flat_normals` or `compute_smooth_normals` as appropriate

## Testing

- Ran the two examples mentioned above
2024-05-18 12:07:27 +00:00
Lynn
450a9202d0
Common MeshBuilder trait (#13411)
# Objective

- All `ShapeMeshBuilder`s have some methods/implementations in common.
These are `fn build(&self) -> Mesh` and this implementation:
```rust
impl From<ShapeMeshBuilder> for Mesh { 
    fn from(builder: ShapeMeshBuilder) -> { 
        builder.build() 
    } 
}
``` 

- For the sake of consistency, these can be moved into a shared trait

## Solution

- Add `trait MeshBuilder` containing a `fn build(&self) -> Mesh` and
implementing `MeshBuilder for ShapeMeshBuilder`
- Implement `From<T: MeshBuilder> for Mesh`

## Migration Guide

- When calling `.build()` you need to import
`bevy_render::mesh::primitives::MeshBuilder`
2024-05-18 11:58:11 +00:00
Alice Cecile
ee6dfd35c9
Revert "Add on_unimplemented Diagnostics to Most Public Traits" (#13413)
# Objective

- Rust 1.78 breaks all Android support, see
https://github.com/bevyengine/bevy/issues/13331
- We should not bump the MSRV to 1.78 until that's resolved in #13366.

## Solution

- Temporarily revert https://github.com/bevyengine/bevy/pull/13347

Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
2024-05-17 17:00:43 +00:00
Johannes Hackel
1fcf6a444f
Add emissive_exposure_weight to the StandardMaterial (#13350)
# Objective

- The emissive color gets multiplied by the camera exposure value. But
this cancels out almost any emissive effect.
- Fixes #13133
- Closes PR #13337 

## Solution
- Add emissive_exposure_weight to the StandardMaterial
- In the shader this value is stored in the alpha channel of the
emissive color.
- This value defines how much the exposure influences the emissive
color.
- It's equal to Google's Filament:
https://google.github.io/filament/Materials.html#emissive

4f021583f1/shaders/src/shading_lit.fs (L287)

## Testing

- The result of
[EmissiveStrengthTest](https://github.com/KhronosGroup/glTF-Sample-Models/tree/main/2.0/EmissiveStrengthTest)
with the default value of 0.0:

without bloom:

![emissive_fix](https://github.com/bevyengine/bevy/assets/688816/8f8c131a-464a-4d7b-a9e4-4e28d679ee5d)

with bloom:

![emissive_fix_bloom](https://github.com/bevyengine/bevy/assets/688816/89f200ee-3bd5-4daa-bf64-8999b56df3fa)
2024-05-17 13:49:53 +00:00
Rob Parrett
47d6e967b2
De-clutter 2d_gizmos example (#13401)
# Objective

Fixes #13395

## Solution

A minimal set of changes that should make the example a bit more
readable without totally redesigning it.

- Prune the top left instruction text and make its style consistent with
other examples.
    (see https://github.com/bevyengine/bevy/pull/8478)
- Remove one of the circles, which was demonstrating "not overriding
segments."
- Make the grid a more subtle color
- Make the rectangles larger and remove their rotation, moving the arc
to make room

## Before / After


![screenshot-before](https://github.com/bevyengine/bevy/assets/200550/1b324e63-aca1-4b70-9e31-0c73bb4cf676)

![screenshot-after](https://github.com/bevyengine/bevy/assets/200550/e7d6d786-cdf8-44dc-be1e-787ba94c5429)
2024-05-17 13:08:45 +00:00
Zachary Harrold
11f0a2dcde
Add on_unimplemented Diagnostics to Most Public Traits (#13347)
# Objective

- Fixes #12377

## Solution

Added simple `#[diagnostic::on_unimplemented(...)]` attributes to some
critical public traits providing a more approachable initial error
message. Where appropriate, a `note` is added indicating that a `derive`
macro is available.

## Examples

<details>
<summary>Examples hidden for brevity</summary>

Below is a collection of examples showing the new error messages
produced by this change. In general, messages will start with a more
Bevy-centric error message (e.g., _`MyComponent` is not a `Component`_),
and a note directing the user to an available derive macro where
appropriate.

### Missing `#[derive(Resource)]`

<details>
<summary>Example Code</summary>

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

struct MyResource;

fn main() {
    App::new()
        .insert_resource(MyResource)
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `MyResource` is not a `Resource`
   --> examples/app/empty.rs:7:26
    |
7   |         .insert_resource(MyResource)
    |          --------------- ^^^^^^^^^^ invalid `Resource`
    |          |
    |          required by a bound introduced by this call
    |
    = help: the trait `Resource` is not implemented for `MyResource`       
    = note: consider annotating `MyResource` with `#[derive(Resource)]`    
    = help: the following other types implement trait `Resource`:
              AccessibilityRequested
              ManageAccessibilityUpdates
              bevy::bevy_a11y::Focus
              DiagnosticsStore
              FrameCount
              bevy::prelude::State<S>
              SystemInfo
              bevy::prelude::Axis<T>
            and 141 others
note: required by a bound in `bevy::prelude::App::insert_resource`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:419:31
    |
419 |     pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
    |                               ^^^^^^^^ required by this bound in `App::insert_resource`
```

</details>

### Putting A `QueryData` in a `QueryFilter` Slot

<details>
<summary>Example Code</summary>

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

#[derive(Component)]
struct A;

#[derive(Component)]
struct B;

fn my_system(_query: Query<&A, &B>) {}

fn main() {
    App::new()
        .add_systems(Update, my_system)
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `&B` is not a valid `Query` filter
   --> examples/app/empty.rs:9:22
    |
9   | fn my_system(_query: Query<&A, &B>) {}
    |                      ^^^^^^^^^^^^^ invalid `Query` filter
    |
    = help: the trait `QueryFilter` is not implemented for `&B`
    = help: the following other types implement trait `QueryFilter`:
              With<T>
              Without<T>
              bevy::prelude::Or<()>
              bevy::prelude::Or<(F0,)>
              bevy::prelude::Or<(F0, F1)>
              bevy::prelude::Or<(F0, F1, F2)>
              bevy::prelude::Or<(F0, F1, F2, F3)>
              bevy::prelude::Or<(F0, F1, F2, F3, F4)>
            and 28 others
note: required by a bound in `bevy::prelude::Query`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\query.rs:349:51
    |
349 | pub struct Query<'world, 'state, D: QueryData, F: QueryFilter = ()> {
    |                                                   ^^^^^^^^^^^ required by this bound in `Query`
```

</details>

### Missing `#[derive(Component)]`

<details>
<summary>Example Code</summary>

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

struct A;

fn my_system(mut commands: Commands) {
    commands.spawn(A);
}

fn main() {
    App::new()
        .add_systems(Startup, my_system)
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `A` is not a `Bundle`
   --> examples/app/empty.rs:6:20
    |
6   |     commands.spawn(A);
    |              ----- ^ invalid `Bundle`
    |              |
    |              required by a bound introduced by this call
    |
    = help: the trait `bevy::prelude::Component` is not implemented for `A`, which is required by `A: Bundle`
    = note: consider annotating `A` with `#[derive(Component)]` or `#[derive(Bundle)]`
    = help: the following other types implement trait `Bundle`:
              TransformBundle
              SceneBundle
              DynamicSceneBundle
              AudioSourceBundle<Source>
              SpriteBundle
              SpriteSheetBundle
              Text2dBundle
              MaterialMesh2dBundle<M>
            and 34 others
    = note: required for `A` to implement `Bundle`
note: required by a bound in `bevy::prelude::Commands::<'w, 's>::spawn`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\commands\mod.rs:243:21
    |
243 |     pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
    |                     ^^^^^^ required by this bound in `Commands::<'w, 's>::spawn`
```

</details>

### Missing `#[derive(Asset)]`

<details>
<summary>Example Code</summary>

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

struct A;

fn main() {
    App::new()
        .init_asset::<A>()
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `A` is not an `Asset`
   --> examples/app/empty.rs:7:23
    |
7   |         .init_asset::<A>()
    |          ----------   ^ invalid `Asset`
    |          |
    |          required by a bound introduced by this call
    |
    = help: the trait `Asset` is not implemented for `A`
    = note: consider annotating `A` with `#[derive(Asset)]`
    = help: the following other types implement trait `Asset`:
              Font
              AnimationGraph
              DynamicScene
              Scene
              AudioSource
              Pitch
              bevy::bevy_gltf::Gltf
              GltfNode
            and 17 others
note: required by a bound in `init_asset`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_asset\src\lib.rs:307:22
    |
307 |     fn init_asset<A: Asset>(&mut self) -> &mut Self;
    |                      ^^^^^ required by this bound in `AssetApp::init_asset`
```

</details>

### Mismatched Input and Output on System Piping

<details>
<summary>Example Code</summary>

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

fn producer() -> u32 {
    123
}

fn consumer(_: In<u16>) {}

fn main() {
    App::new()
        .add_systems(Update, producer.pipe(consumer))
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `fn(bevy::prelude::In<u16>) {consumer}` is not a valid system with input `u32` and output `_`
   --> examples/app/empty.rs:11:44
    |
11  |         .add_systems(Update, producer.pipe(consumer))
    |                                       ---- ^^^^^^^^ invalid system
    |                                       |
    |                                       required by a bound introduced by this call
    |
    = help: the trait `bevy::prelude::IntoSystem<u32, _, _>` is not implemented for fn item `fn(bevy::prelude::In<u16>) {consumer}`
    = note: expecting a system which consumes `u32` and produces `_`
note: required by a bound in `pipe`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\mod.rs:168:12
    |
166 |     fn pipe<B, Final, MarkerB>(self, system: B) -> PipeSystem<Self::System, B::System>
    |        ---- required by a bound in this associated function
167 |     where
168 |         B: IntoSystem<Out, Final, MarkerB>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `IntoSystem::pipe`
```

</details>

### Missing Reflection

<details>
<summary>Example Code</summary>

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

#[derive(Component)]
struct MyComponent;

fn main() {
    App::new()
        .register_type::<MyComponent>()
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `MyComponent` does not provide type registration information
   --> examples/app/empty.rs:8:26
    |
8   |         .register_type::<MyComponent>()
    |          -------------   ^^^^^^^^^^^ the trait `GetTypeRegistration` is not implemented for `MyComponent`
    |          |
    |          required by a bound introduced by this call
    |
    = note: consider annotating `MyComponent` with `#[derive(Reflect)]`
    = help: the following other types implement trait `GetTypeRegistration`:
              bool
              char
              isize
              i8
              i16
              i32
              i64
              i128
            and 443 others
note: required by a bound in `bevy::prelude::App::register_type`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:619:29
    |
619 |     pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::register_type`
```

</details>

### Missing `#[derive(States)]` Implementation

<details>
<summary>Example Code</summary>

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

#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash)]
enum AppState {
    #[default]
    Menu,
    InGame {
        paused: bool,
        turbo: bool,
    },
}

fn main() {
    App::new()
        .init_state::<AppState>()
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: the trait bound `AppState: FreelyMutableState` is not satisfied
   --> examples/app/empty.rs:15:23
    |
15  |         .init_state::<AppState>()
    |          ----------   ^^^^^^^^ the trait `FreelyMutableState` is not implemented for `AppState`
    |          |
    |          required by a bound introduced by this call
    |
    = note: consider annotating `AppState` with `#[derive(States)]`
note: required by a bound in `bevy::prelude::App::init_state`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:282:26
    |
282 |     pub fn init_state<S: FreelyMutableState + FromWorld>(&mut self) -> &mut Self {
    |                          ^^^^^^^^^^^^^^^^^^ required by this bound in `App::init_state`
```

</details>

### Adding a `System` with Unhandled Output

<details>
<summary>Example Code</summary>

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

fn producer() -> u32 {
    123
}

fn main() {
    App::new()
        .add_systems(Update, consumer)
        .run();
}
```

</details>

<details>
<summary>Error Generated</summary>

```error
error[E0277]: `fn() -> u32 {producer}` does not describe a valid system configuration
   --> examples/app/empty.rs:9:30
    |
9   |         .add_systems(Update, producer)
    |          -----------         ^^^^^^^^ invalid system configuration
    |          |
    |          required by a bound introduced by this call
    |
    = help: the trait `IntoSystem<(), (), _>` is not implemented for fn item `fn() -> u32 {producer}`, which is required by `fn() -> u32 {producer}: IntoSystemConfigs<_>`
    = help: the following other types implement trait `IntoSystemConfigs<Marker>`:
              <Box<(dyn bevy::prelude::System<In = (), Out = ()> + 'static)> as IntoSystemConfigs<()>>
              <NodeConfigs<Box<(dyn bevy::prelude::System<In = (), Out = ()> + 'static)>> as IntoSystemConfigs<()>>
              <(S0,) as IntoSystemConfigs<(SystemConfigTupleMarker, P0)>>
              <(S0, S1) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1)>>
              <(S0, S1, S2) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2)>>
              <(S0, S1, S2, S3) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3)>>
              <(S0, S1, S2, S3, S4) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3, P4)>>
              <(S0, S1, S2, S3, S4, S5) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3, P4, P5)>>
            and 14 others
    = note: required for `fn() -> u32 {producer}` to implement `IntoSystemConfigs<_>`
note: required by a bound in `bevy::prelude::App::add_systems`
   --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:342:23
    |
339 |     pub fn add_systems<M>(
    |            ----------- required by a bound in this associated function
...
342 |         systems: impl IntoSystemConfigs<M>,
    |                       ^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::add_systems`
```

</details>
</details>

## Testing

CI passed locally.

## Migration Guide

Upgrade to version 1.78 (or higher) of Rust.

## Future Work

- Currently, hints are not supported in this diagnostic. Ideally,
suggestions like _"consider using ..."_ would be in a hint rather than a
note, but that is the best option for now.
- System chaining and other `all_tuples!(...)`-based traits have bad
error messages due to the slightly different error message format.

---------

Co-authored-by: Jamie Ridding <Themayu@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-05-17 00:49:05 +00:00
François Mockers
104dcf5a67
example render_to_texture: remove extra light (#13398)
# Objective

- in example `render_to_texture`, #13317 changed the comment on the
existing light saying lights don't work on multiple layers, then add a
light on multiple layers explaining that it will work. it's confusing

## Solution

- Keep the original light, with the updated comment

## Testing

- Run example `render_to_texture`, lighting is correct
2024-05-16 23:26:55 +00:00
Rob Parrett
7cbc0357be
Use load_with_settings instead of manually overriding srgbness in examples (#13399)
# Objective

`parallax_mapping` and `deferred_rendering` both use a roundabout way of
manually overriding the srgbness of their normal map textures.

This can now be done with `load_with_settings` in one line of code.

## Solution

- Delete the override systems and use `load_with_settings` instead
- Make `deferred_rendering`'s instruction text style consistent with
other examples while I'm in there.
    (see #8478)

## Testing

Tested by running with `load` instead of `load_settings` and confirming
that lighting looks bad when `is_srgb` is not configured, and good when
it is.

## Discussion

It would arguably make more sense to configure this in a `.meta` file,
but I used `load_with_settings` because that's how it was done in the
`clearcoat` example and it does seem nice for documentation purposes to
call this out explicitly in code.
2024-05-16 23:26:22 +00:00
IceSentry
aa907d5437
Remove unnecessary .view_layouts (#13394)
# Objective

- The volumetric fog PR originally needed to be modified to use
`.view_layouts` but that was changed in another PR. The merge with main
still kept those around.

## Solution

- Remove them because they aren't necessary
2024-05-16 19:12:36 +00:00
Ben Harper
be03ba1b68
Add reflect impls for bevy_math curve structs (#13348)
# Objective

Fixes #13189

## Solution

To add the reflect impls I needed to make all the struct fields pub. I
don't think there's any harm for these types, but just a note for
review.

---------

Co-authored-by: Ben Harper <ben@tukom.org>
2024-05-16 17:59:56 +00:00
Patrick Walton
19bfa41768
Implement volumetric fog and volumetric lighting, also known as light shafts or god rays. (#13057)
This commit implements a more physically-accurate, but slower, form of
fog than the `bevy_pbr::fog` module does. Notably, this *volumetric fog*
allows for light beams from directional lights to shine through,
creating what is known as *light shafts* or *god rays*.

To add volumetric fog to a scene, add `VolumetricFogSettings` to the
camera, and add `VolumetricLight` to directional lights that you wish to
be volumetric. `VolumetricFogSettings` has numerous settings that allow
you to define the accuracy of the simulation, as well as the look of the
fog. Currently, only interaction with directional lights that have
shadow maps is supported. Note that the overhead of the effect scales
directly with the number of directional lights in use, so apply
`VolumetricLight` sparingly for the best results.

The overall algorithm, which is implemented as a postprocessing effect,
is a combination of the techniques described in [Scratchapixel] and
[this blog post]. It uses raymarching in screen space, transformed into
shadow map space for sampling and combined with physically-based
modeling of absorption and scattering. Bevy employs the widely-used
[Henyey-Greenstein phase function] to model asymmetry; this essentially
allows light shafts to fade into and out of existence as the user views
them.

Volumetric rendering is a huge subject, and I deliberately kept the
scope of this commit small. Possible follow-ups include:

1. Raymarching at a lower resolution.

2. A post-processing blur (especially useful when combined with (1)).

3. Supporting point lights and spot lights.

4. Supporting lights with no shadow maps.

5. Supporting irradiance volumes and reflection probes.

6. Voxel components that reuse the volumetric fog code to create voxel
shapes.

7. *Horizon: Zero Dawn*-style clouds.

These are all useful, but out of scope of this patch for now, to keep
things tidy and easy to review.

A new example, `volumetric_fog`, has been added to demonstrate the
effect.

## Changelog

### Added

* A new component, `VolumetricFog`, is available, to allow for a more
physically-accurate, but more resource-intensive, form of fog.

* A new component, `VolumetricLight`, can be placed on directional
lights to make them interact with `VolumetricFog`. Notably, this allows
such lights to emit light shafts/god rays.

![Screenshot 2024-04-21
162808](https://github.com/bevyengine/bevy/assets/157897/7a1fc81d-eed5-4735-9419-286c496391a9)

![Screenshot 2024-04-21
132005](https://github.com/bevyengine/bevy/assets/157897/e6d3b5ca-8f59-488d-a3de-15e95aaf4995)

[Scratchapixel]:
https://www.scratchapixel.com/lessons/3d-basic-rendering/volume-rendering-for-developers/intro-volume-rendering.html

[this blog post]: https://www.alexandre-pestana.com/volumetric-lights/

[Henyey-Greenstein phase function]:
https://www.pbr-book.org/4ed/Volume_Scattering/Phase_Functions#TheHenyeyndashGreensteinPhaseFunction
2024-05-16 17:13:18 +00:00
charlotte
4c3b7679ec
#12502 Remove limit on RenderLayers. (#13317)
# Objective

Remove the limit of `RenderLayer` by using a growable mask using
`SmallVec`.

Changes adopted from @UkoeHB's initial PR here
https://github.com/bevyengine/bevy/pull/12502 that contained additional
changes related to propagating render layers.

Changes

## Solution

The main thing needed to unblock this is removing `RenderLayers` from
our shader code. This primarily affects `DirectionalLight`. We are now
computing a `skip` field on the CPU that is then used to skip the light
in the shader.

## Testing

Checked a variety of examples and did a quick benchmark on `many_cubes`.
There were some existing problems identified during the development of
the original pr (see:
https://discord.com/channels/691052431525675048/1220477928605749340/1221190112939872347).
This PR shouldn't change any existing behavior besides removing the
layer limit (sans the comment in migration about `all` layers no longer
being possible).

---

## Changelog

Removed the limit on `RenderLayers` by using a growable bitset that only
allocates when layers greater than 64 are used.

## Migration Guide

- `RenderLayers::all()` no longer exists. Entities expecting to be
visible on all layers, e.g. lights, should compute the active layers
that are in use.

---------

Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2024-05-16 16:15:47 +00:00
Lynn
05e2552a68
Add Rounded box gizmos (#11948)
# Objective

- Implement rounded cuboids and rectangles, suggestion of #9400 

## Solution

- Added `Gizmos::rounded_cuboid`, `Gizmos::rounded_rect` and
`Gizmos::rounded_rect_2d`.
- All of these return builders that allow configuring of the corner/edge
radius using `.corner_radius(...)` or `.edge_radius(...)` as well as the
line segments of each arc using `.arc_segments(...)`.

---

## Changelog

- Added a new `rounded_box` module to `bevy_gizmos` containing all of
the above methods and builders.
- Updated the examples `2d_gizmos` and `3d_gizmos`

## Additional information

The 3d example now looks like this:

<img width="1440" alt="Screenshot 2024-02-28 at 01 47 28"
src="https://github.com/bevyengine/bevy/assets/62256001/654e30ca-c091-4f14-a402-90138e95c71b">

And this is the updated 2d example showcasing negative corner radius:

<img width="1440" alt="Screenshot 2024-02-28 at 01 59 37"
src="https://github.com/bevyengine/bevy/assets/62256001/3904697a-5462-4ee7-abd9-3e893ca07082">
<img width="1440" alt="Screenshot 2024-02-28 at 01 59 47"
src="https://github.com/bevyengine/bevy/assets/62256001/a8892cfd-3aad-4c0c-87eb-559c17c8864c">

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: James Gayfer <10660608+jgayfer@users.noreply.github.com>
2024-05-16 16:13:49 +00:00
Adith Ramachandran
65e62ba5eb
Revert "Support calculating normals for indexed meshes" (#12716) and add support for calculating smooth normals (#13333)
# Objective

- Refactor the changes merged in #11654 to compute flat normals for
indexed meshes instead of smooth normals.
- Fixes #12716 

## Solution

- Partially revert the changes in #11654 to compute flat normals for
both indexed and unindexed meshes in `compute_flat_normals`
- Create a new method, `compute_smooth_normals`, that computes smooth
normals for indexed meshes
- Create a new method, `compute_normals`, that computes smooth normals
for indexed meshes and flat normals for unindexed meshes by default. Use
this new method instead of `compute_flat_normals`.

## Testing

- Run the example with and without the changes to ensure that the
results are identical.
2024-05-16 14:54:35 +00:00
Johannes Hackel
1efa578ffb
Fix transmission by setting the correct value for transmissive_lighting_input.F_ab (#13379)
# Objective

- The clearcoat PR #13031 had a small typo which broke transmission
- Fixes #13284

## Solution

- Set transmissive_lighting_input.F_ab to the correct value


![transmission_fix](https://github.com/bevyengine/bevy/assets/688816/92158117-de3a-4fa5-8af8-dcbd1d5eee04)
2024-05-16 14:33:32 +00:00
Xzihnago
eba8744a70
Add Debug derive for ScreenSpaceAmbientOcclusionSettings struct (#13387)
# Objective

To streamline the code which utilizes `Debug` in user's struct like
`GraphicsSettings`. This addition aims to enhance code simplicity and
readability.

## Solution

Add `Debug` derive for `ScreenSpaceAmbientOcclusionSettings` struct.

## Testing

Should have no impact.
2024-05-16 11:29:34 +00:00
IceSentry
d9993a8092
Enable depth of field on webgpu (#13374)
# Objective

- Depth of field is currently disabled on any wasm targets, but the bug
it's trying to avoid is only an issue in webgl.

## Solution

- Enable dof when compiling for webgpu
- I also remove the msaa check because sampling a depth texture doesn't
work with or without msaa in webgl
- Unfortunately, Bokeh seems to be broken when using webgpu, so default
to Gaussian instead to make sure the defaults have the broadest platform
support

## Testing

- I added dof to the 3d_shapes example and compiled it to webgpu to
confirm it works
- I also tried compiling to webgl to confirm things still works and dof
isn't rendered.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-05-16 06:48:28 +00:00
IcyLeave6109
f61c55fd90
Allow shapes to be constructed with zero values (#13365)
# Objective

Fixes #13332.

## Solution

The assertion `circumradius >= 0.0` to allow zero.

Are there any other shapes that need to be allowed to be constructed
with zero?

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-05-16 02:22:50 +00:00
Pietro
d17fb160b0
Fix ClearColor in 2d pipelines (#13378)
# Objective

- Fixes #13377
- Fixes https://github.com/bevyengine/bevy/issues/13383

## Solution

- Even if the number of renderables is empty, the transparent phase need
to run to set the clear color.

## Testing

- Tested on the `clear_color` example
2024-05-15 20:36:02 +00:00
floppyhammer
8da4fcb616
Fix UI border artifacts caused by incorrect blending (#12725)
Fixes https://github.com/bevyengine/bevy/issues/12702.

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-05-15 18:50:30 +00:00
JMS55
debcf3fb1d
Misc asset code quality and docs (#13382)
* Fix a doc comment for AssetSources
* Move some complicated generics to a where clause and write out T ->
Transformer fully
2024-05-15 18:49:04 +00:00
Csányi István
f91fd322b7
Skip redundant mesh_position_local_to_world call in vertex prepass shader (#13158)
# Objective

Optimize vertex prepass shader maybe?
Make it consistent with the base vertex shader

## Solution

`mesh_position_local_to_clip` just calls `mesh_position_local_to_world`
and then `position_world_to_clip`
since `out.world_position` is getting calculated anyway a few lines
below, just move it up and use it's output to calculate `out.position`.

It is the same as in the base vertex shader (`mesh.wgsl`).

Note: I have no idea if there is a reason that it was this way. I'm not
an expert, just noticed this inconsistency while messing with custom
shaders.
2024-05-14 16:31:58 +00:00