Commit graph

7717 commits

Author SHA1 Message Date
Phoqinu
c6147e57f4
Make StateTransitionSteps public (#16612)
# Objective

- Fixes #16594 

## Solution

- `StateTransitionSteps` was made public

## Testing

- _Did you test these changes? If so, how?_
 I am now able to import it and use it.

---

## Showcase

- Users can now write their own state scoped resources

```rust
    fn init_state_scoped_resource<R: Resource + FromWorld>(
        &mut self,
        state: impl States,
    ) -> &mut Self {
        use bevy::state::state::StateTransitionSteps; // this PR in action

        self.add_systems(
            StateTransition,
            (
                clear_state_scoped_resource_impl::<_, R>(state.clone())
                    .in_set(StateTransitionSteps::ExitSchedules), // and here
                init_state_scoped_resource_impl::<_, R>(state)
                    .in_set(StateTransitionSteps::EnterSchedules), // here too
            ),
        );

        self
    }
```
2024-12-03 19:48:00 +00:00
SpecificProtagonist
d92fc1e456
Move required components doc to type doc (#16575)
# Objective

Make documentation of a component's required components more visible by
moving it to the type's docs

## Solution

Change `#[require]` from a derive macro helper to an attribute macro.

Disadvantages:
- this silences any unused code warnings on the component, as it is used
by the macro!
- need to import `require` if not using the ecs prelude (I have not
included this in the migration guilde as Rust tooling already suggests
the fix)

---

## Showcase
![Documentation of
Camera](https://github.com/user-attachments/assets/3329511b-747a-4c8d-a43e-57f7c9c71a3c)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2024-12-03 19:45:20 +00:00
ickshonpe
dd49dc71d2
Rename UiBoxShadowSamples to BoxShadowSamples. (#16505)
# Objective

The `UiBoxShadowSamples` resource should be renamed to
`BoxShadowSamples` so it matches the `BoxShadow` component.

## Migration Guide

`UiBoxShadowSamples` has been renamed to `BoxShadowSamples`
2024-12-03 19:43:26 +00:00
SpecificProtagonist
1a6b94c5e8
Remove flush_and_reserve_invalid_assuming_no_entities (#16460)
# Objective

`flush_and_reserve_invalid_assuming_no_entities` was made for the old
rendering world (which was reset every frame) and is usused since the
0.15 retained rendering world, but wasn't removed yet. It is pub, but is
undocumented apart from the safety comment.

## Solution

Remove `flush_and_reserve_invalid_assuming_no_entities` and the safety
invariants this method required for `EntityMeta`, `EntityLocation`,
`TableId` and `TableRow`. This reduces the amount of unsafe code &
safety invariants and makes #16047 easier.

## Alternatives
- Document `flush_and_reserve_invalid_assuming_no_entities` and keep it
unchanged
- Document `flush_and_reserve_invalid_assuming_no_entities` and change
it to be based on `EntityMeta::INVALID`


## Migration Guide
- exchange `Entities::flush_and_reserve_invalid_assuming_no_entities`
for `reserve` and `flush_as_invalid` and notify us if that's
insufficient

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2024-12-03 19:42:22 +00:00
ickshonpe
343a52a789
Remove the min and max fields from LayoutContext. (#16459)
# Objective

Remove the `min` and `max` fields from `LayoutContext`. 
It doesn't seem useful to cache these values, it's simpler just to call
`min_element` and `max_element` on the `physical_size`
field.

##  Migration Guide

The `min` and `max` fields have been removed from `LayoutContext`. To
retrieve these values call `min_element` and `max_element` on
`LayoutContent::physical_size` instead.
2024-12-03 19:39:45 +00:00
Matty Weatherley
9d142a8025
Use IntoIterator instead of Into<Vec<..>> in cubic splines interfaces (#16402)
# Objective

This was always a bit weird; `IntoIterator` is considered more idiomatic
in Rust.

The reason these used `Into<Vec<..>>` in the first place was (to my
knowledge) because of concerns that passing an already-owned vector
would cause a redundant allocation if the iterator API was used instead.
However, I have looked at simple examples for this scenario and the
generated assembly is identical (i.e. `into_iter().collect()` is
effectively converted to a no-op).

## Solution

As described in the title.

## Testing

It compiles. Ran existing tests.

## Migration Guide

The cubic splines API now uses `IntoIterator` in places where it used
`Into<Vec<..>>`. For most users, this will have little to no effect (it
is largely more permissive). However, in case you were using some
unusual input type that implements `Into<Vec<..>>` without implementing
`IntoIterator`, you can migrate by converting the input to a `Vec<..>`
before passing it into the interface.
2024-12-03 19:35:14 +00:00
Michael Walter Van Der Velden
93dc596d2e
Add optional transparency passthrough for sprite backend with bevy_picking (#16388)
# Objective

- Allow bevy_sprite_picking backend to pass through transparent sections
of the sprite.
- Fixes #14929

## Solution

- After sprite picking detects the cursor is within a sprites rect,
check the pixel at that location on the texture and check that it meets
an optional transparency cutoff. Change originally created for
mod_picking on bevy 0.14
(https://github.com/aevyrie/bevy_mod_picking/pull/373)

## Testing

- Ran Sprite Picking example to check it was working both with
transparency enabled and disabled
- ModPicking version is currently in use in my own isometric game where
this has been an extremely noticeable issue

## Showcase

![Sprite Picking
Text](https://github.com/user-attachments/assets/76568c0d-c359-422b-942d-17c84d3d3009)

## Migration Guide

Sprite picking now ignores transparent regions (with an alpha value less
than or equal to 0.1). To configure this, modify the
`SpriteBackendSettings` resource.

---------

Co-authored-by: andriyDev <andriydzikh@gmail.com>
2024-12-03 19:32:52 +00:00
Patrick Walton
5adf831b42
Add a bindless mode to AsBindGroup. (#16368)
This patch adds the infrastructure necessary for Bevy to support
*bindless resources*, by adding a new `#[bindless]` attribute to
`AsBindGroup`.

Classically, only a single texture (or sampler, or buffer) can be
attached to each shader binding. This means that switching materials
requires breaking a batch and issuing a new drawcall, even if the mesh
is otherwise identical. This adds significant overhead not only in the
driver but also in `wgpu`, as switching bind groups increases the amount
of validation work that `wgpu` must do.

*Bindless resources* are the typical solution to this problem. Instead
of switching bindings between each texture, the renderer instead
supplies a large *array* of all textures in the scene up front, and the
material contains an index into that array. This pattern is repeated for
buffers and samplers as well. The renderer now no longer needs to switch
binding descriptor sets while drawing the scene.

Unfortunately, as things currently stand, this approach won't quite work
for Bevy. Two aspects of `wgpu` conspire to make this ideal approach
unacceptably slow:

1. In the DX12 backend, all binding arrays (bindless resources) must
have a constant size declared in the shader, and all textures in an
array must be bound to actual textures. Changing the size requires a
recompile.

2. Changing even one texture incurs revalidation of all textures, a
process that takes time that's linear in the total size of the binding
array.

This means that declaring a large array of textures big enough to
encompass the entire scene is presently unacceptably slow. For example,
if you declare 4096 textures, then `wgpu` will have to revalidate all
4096 textures if even a single one changes. This process can take
multiple frames.

To work around this problem, this PR groups bindless resources into
small *slabs* and maintains a free list for each. The size of each slab
for the bindless arrays associated with a material is specified via the
`#[bindless(N)]` attribute. For instance, consider the following
declaration:

```rust
#[derive(AsBindGroup)]
#[bindless(16)]
struct MyMaterial {
    #[buffer(0)]
    color: Vec4,
    #[texture(1)]
    #[sampler(2)]
    diffuse: Handle<Image>,
}
```

The `#[bindless(N)]` attribute specifies that, if bindless arrays are
supported on the current platform, each resource becomes a binding array
of N instances of that resource. So, for `MyMaterial` above, the `color`
attribute is exposed to the shader as `binding_array<vec4<f32>, 16>`,
the `diffuse` texture is exposed to the shader as
`binding_array<texture_2d<f32>, 16>`, and the `diffuse` sampler is
exposed to the shader as `binding_array<sampler, 16>`. Inside the
material's vertex and fragment shaders, the applicable index is
available via the `material_bind_group_slot` field of the `Mesh`
structure. So, for instance, you can access the current color like so:

```wgsl
// `uniform` binding arrays are a non-sequitur, so `uniform` is automatically promoted
// to `storage` in bindless mode.
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
    let color = material_color[mesh[in.instance_index].material_bind_group_slot];
    ...
}
```

Note that portable shader code can't guarantee that the current platform
supports bindless textures. Indeed, bindless mode is only available in
Vulkan and DX12. The `BINDLESS` shader definition is available for your
use to determine whether you're on a bindless platform or not. Thus a
portable version of the shader above would look like:

```wgsl
#ifdef BINDLESS
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
#else // BINDLESS
@group(2) @binding(0) var<uniform> material_color: Color;
#endif // BINDLESS
...
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
#ifdef BINDLESS
    let color = material_color[mesh[in.instance_index].material_bind_group_slot];
#else // BINDLESS
    let color = material_color;
#endif // BINDLESS
    ...
}
```

Importantly, this PR *doesn't* update `StandardMaterial` to be bindless.
So, for example, `scene_viewer` will currently not run any faster. I
intend to update `StandardMaterial` to use bindless mode in a follow-up
patch.

A new example, `shaders/shader_material_bindless`, has been added to
demonstrate how to use this new feature.

Here's a Tracy profile of `submit_graph_commands` of this patch and an
additional patch (not submitted yet) that makes `StandardMaterial` use
bindless. Red is those patches; yellow is `main`. The scene was Bistro
Exterior with a hack that forces all textures to opaque. You can see a
1.47x mean speedup.
![Screenshot 2024-11-12
161713](https://github.com/user-attachments/assets/4334b362-42c8-4d64-9cfb-6835f019b95c)

## Migration Guide

* `RenderAssets::prepare_asset` now takes an `AssetId` parameter.
* Bin keys now have Bevy-specific material bind group indices instead of
`wgpu` material bind group IDs, as part of the bindless change. Use the
new `MaterialBindGroupAllocator` to map from bind group index to bind
group ID.
2024-12-03 18:00:34 +00:00
Martín Maita
bfb2ff16e8
Update rodio requirement from 0.19 to 0.20 (#16359)
# Objective

- Supersedes #16344

## Solution

- Updated `rodio` version requirement to `0.20`.
-
[Changelog](https://github.com/RustAudio/rodio/blob/master/CHANGELOG.md)

## Testing

- CI checks.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 17:55:42 +00:00
Benjamin Brienen
afd0f1322d
Move all_tuples to a new crate (#16161)
# Objective

Fixes #15941

## Solution

Created https://crates.io/crates/variadics_please and moved the code
there; updating references

`bevy_utils/macros` is deleted.

## Testing

cargo check

## Migration Guide

Use `variadics_please::{all_tuples, all_tuples_with_size}` instead of
`bevy::utils::{all_tuples, all_tuples_with_size}`.
2024-12-03 17:41:09 +00:00
eugineerd
2e267bba5a
Entity cloning (#16132)
## Objective

Fixes #1515 

This PR implements a flexible entity cloning system. The primary use
case for it is to clone dynamically-generated entities.

Example:
```rs
#[derive(Component, Clone)]
pub struct Projectile;

#[derive(Component, Clone)]
pub struct Damage {
    value: f32,
}

fn player_input(
    mut commands: Commands,
    projectiles: Query<Entity, With<Projectile>>,
    input: Res<ButtonInput<KeyCode>>,
) {
    // Fire a projectile
    if input.just_pressed(KeyCode::KeyF) {
        commands.spawn((Projectile, Damage { value: 10.0 }));
    }

    // Triplicate all active projectiles
    if input.just_pressed(KeyCode::KeyT) {
        for projectile in projectiles.iter() {
            // To triplicate a projectile we need to create 2 more clones
            for _ in 0..2{
                commands.clone_entity(projectile)
            }
        }
    }
}
```

## Solution

### Commands
Add a `clone_entity` command to create a clone of an entity with all
components that can be cloned. Components that can't be cloned will be
ignored.
```rs
commands.clone_entity(entity)
```
If there is a need to configure the cloning process (like set to clone
recursively), there is a second command:
```rs
commands.clone_entity_with(entity, |builder| {
    builder.recursive(true)
});
```
Both of these commands return `EntityCommands` of the cloned entity, so
the copy can be modified afterwards.

### Builder
All these commands use `EntityCloneBuilder` internally. If there is a
need to clone an entity using `World` instead, it is also possible:
```rs
let entity = world.spawn(Component).id();
let entity_clone = world.spawn_empty().id();
EntityCloneBuilder::new(&mut world).clone_entity(entity, entity_clone);
```

Builder has methods to `allow` or `deny` certain components during
cloning if required and can be extended by implementing traits on it.
This PR includes two `EntityCloneBuilder` extensions:
`CloneEntityWithObserversExt` to configure adding cloned entity to
observers of the original entity, and `CloneEntityRecursiveExt` to
configure cloning an entity recursively.

### Clone implementations
By default, all components that implement either `Clone` or `Reflect`
will be cloned (with `Clone`-based implementation preferred in case
component implements both).

This can be overriden on a per-component basis:
```rs
impl Component for SomeComponent {
    const STORAGE_TYPE: StorageType = StorageType::Table;

    fn get_component_clone_handler() -> ComponentCloneHandler {
        // Don't clone this component
        ComponentCloneHandler::Ignore
    }
}
```

### `ComponentCloneHandlers`
Clone implementation specified in `get_component_clone_handler` will get
registered in `ComponentCloneHandlers` (stored in
`bevy_ecs::component::Components`) at component registration time.

The clone handler implementation provided by a component can be
overriden after registration like so:
```rs
let component_id = world.components().component_id::<Component>().unwrap()
world.get_component_clone_handlers_mut()
     .set_component_handler(component_id, ComponentCloneHandler::Custom(component_clone_custom))
```
The default clone handler for all components that do not explicitly
define one (or don't derive `Component`) is
`component_clone_via_reflect` if `bevy_reflect` feature is enabled, and
`component_clone_ignore` (noop) otherwise.
Default handler can be overriden using
`ComponentCloneHandlers::set_default_handler`

### Handlers
Component clone handlers can be used to modify component cloning
behavior. The general signature for a handler that can be used in
`ComponentCloneHandler::Custom` is as follows:
```rs
pub fn component_clone_custom(
    world: &mut DeferredWorld,
    entity_cloner: &EntityCloner,
) {
    // implementation
}
```
The `EntityCloner` implementation (used internally by
`EntityCloneBuilder`) assumes that after calling this custom handler,
the `target` entity has the desired version of the component from the
`source` entity.

### Builder handler overrides
Besides component-defined and world-overriden handlers,
`EntityCloneBuilder` also has a way to override handlers locally. It is
mainly used to allow configuration methods like `recursive` and
`add_observers`.
```rs
// From observer clone handler implementation
impl CloneEntityWithObserversExt for EntityCloneBuilder<'_> {
    fn add_observers(&mut self, add_observers: bool) -> &mut Self {
        if add_observers {
            self.override_component_clone_handler::<ObservedBy>(ComponentCloneHandler::Custom(
                component_clone_observed_by,
            ))
        } else {
            self.remove_component_clone_handler_override::<ObservedBy>()
        }
    }
}
```

## Testing
Includes some basic functionality tests and doctests.

Performance-wise this feature is the same as calling `clone` followed by
`insert` for every entity component. There is also some inherent
overhead due to every component clone handler having to access component
data through `World`, but this can be reduced without breaking current
public API in a later PR.
2024-12-03 17:38:10 +00:00
JMS55
d221665386
Native unclipped depth on supported platforms (#16095)
# Objective
- Fixes #16078

## Solution

- Rename things to clarify that we _want_ unclipped depth for
directional light shadow views, and need some way of disabling the GPU's
builtin depth clipping
- Use DEPTH_CLIP_CONTROL instead of the fragment shader emulation on
supported platforms
- Pass only the clip position depth instead of the whole clip position
between vertex->fragment shader (no idea if this helps performance or
not, compiler might optimize it anyways)
- Meshlets
- HW raster always uses DEPTH_CLIP_CONTROL since it targets a more
limited set of platforms
- SW raster was not handling DEPTH_CLAMP_ORTHO correctly, it ended up
pretty much doing nothing.
- This PR made me realize that SW raster technically should have depth
clipping for all views that are not directional light shadows, but I
decided not to bother writing it. I'm not sure that it ever matters in
practice. If proven otherwise, I can add it.

## Testing

- Did you test these changes? If so, how?
- Lighting example. Both opaque (no fragment shader) and alpha masked
geometry (fragment shader emulation) are working with
depth_clip_control, and both work when it's turned off. Also tested
meshlet example.
- Are there any parts that need more testing?
  - Performance. I can't figure out a good test scene.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Toggle depth_clip_control_supported in prepass/mod.rs line 323 to turn
this PR on or off.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - Native

---

## Migration Guide
- `MeshPipelineKey::DEPTH_CLAMP_ORTHO` is now
`MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO`
- The `DEPTH_CLAMP_ORTHO` shaderdef has been renamed to
`UNCLIPPED_DEPTH_ORTHO_EMULATION`
- `clip_position_unclamped: vec4<f32>` is now `unclipped_depth: f32`
2024-12-03 17:30:14 +00:00
Shane Celis
f375422ddd
Compute better smooth normals for cheaper, maybe (#16050)
# Objective

Avoid a premature normalize operation and get better smooth normals for
it.

## Inspiration

@IceSentry suggested `face_normal()` could have its normalize removed
based on [this article](https://iquilezles.org/articles/normals/) in PR
#16039.

## Solution

I did not want to change `face_normal()` to return a vector that's not
normalized. The name "normal" implies it'll be normalized. Instead I
added the `face_area_normal()` function, whose result is not normalized.
Its magnitude is equal two times the triangle's area. I've noted why
this is the case in its doc comment.

I changed `compute_smooth_normals()` from computing normals from
adjacent faces with equal weight to use the area of the faces as a
weight. This has the benefit of being cheaper computationally and
hopefully produces better normals.

The `compute_flat_normals()` is unchanged and still uses
`face_normal()`.

## Testing

One test was added which shows the bigger triangle having an effect on
the normal, but the previous test that uses the same size triangles is
unchanged.

**WARNING:** No visual test has been done yet. No example exists that
demonstrates the compute_smooth_normals(). Perhaps there's a good model
to demonstrate what the differences are. I would love to have some input
on this.

I'd suggest @IceSentry and @stepancheg to review this PR.

## Further Considerations

It's possible weighting normals by their area is not definitely better
than unweighted. It's possible there may be aesthetic reasons to prefer
one over the other. In such a case, we could offer two variants:
weighted or unweighted. Or we could offer another function perhaps like
this: `compute_smooth_normals_with_weights(|normal, area| 1.0)` which
would restore the original unweighted sum of normals.

---

## Showcase

Smooth normal calculation now weights adjacent face normals by their
area.

## Migration Guide
2024-12-03 17:25:10 +00:00
HugoPeters1024
b9cc6e16da
bevy_winit(emit raw winit events) (#15884)
# Objective

- Exposes raw winit events making Bevy even more modular and powerful
for custom plugin developers (e.g. a custom render plugin).

XRef: https://github.com/bevyengine/bevy/issues/5977
It doesn't quite close the issue as sending events is not supported (or
not very useful to be precise). I would think that supporting that
requires some extra considerations by someone a bit more familiar with
the `bevy_winit` crate. That said, this PR could be a nice step forward.

## Solution

Emit `RawWinitWindowEvent` objects for each received event.

## Testing

I verified that the events are emitted using a basic test app. I don't
think it makes sense to solidify this behavior in one of the examples.

---

## Showcase

My example usage for a custom `egui_winit` integration:

```rust
for ev in winit_events.read() {
    if ev.window_id == window.id {
        let _ = egui_winit.on_window_event(&window, &ev.event);
    }
}
```

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-12-03 17:20:43 +00:00
Nico Burns
1fe38b85f1
Upgrade to Taffy 0.6 (#15844)
# Objective

- Keep Taffy version up to date

Taffy 0.6 doesn't include a huge amount relevant to Bevy. But it does:

- Add the `box_sizing` style
- Expose the computed `margin` in layout
- Traitifies the `Style` struct, which opens up the possibility of using
Bevy's `Style` struct directly (although Bevy currently does some style
resolution at conversion time which would no longer be cached if it was
used directly).
- Have a few bug fixes in the layout algorithms

## Solution

- Upgrade Taffy to `0.6.0`

## Testing

- I've run the `grid` example. All looks good.
- More testing is probably warranted. We have had regressions from Taffy
upgrades before
- Having said that, most of the algorithm changes this cycle were driven
by fixing WPT tests run through the new Servo integration. So they're
possibly less likely than usual to cause regressions.

## Breaking changes

The only "breaking" change is adding a field to `Style`. Probably
doesn't bear mentioning?

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-03 17:16:35 +00:00
Zachary Harrold
a8b9c945c7
Add no_std Support to bevy_math (#15810)
# Objective

- Contributes to #15460

## Solution

- Added two new features, `std` (default) and `alloc`, gating `std` and
`alloc` behind them respectively.
- Added missing `f32` functions to `std_ops` as required. These `f32`
methods have been added to the `clippy.toml` deny list to aid in
`no_std` development.

## Testing

- CI
- `cargo clippy -p bevy_math --no-default-features --features libm
--target "x86_64-unknown-none"`
- `cargo test -p bevy_math --no-default-features --features libm`
- `cargo test -p bevy_math --no-default-features --features "libm,
alloc"`
- `cargo test -p bevy_math --no-default-features --features "libm,
alloc, std"`
- `cargo test -p bevy_math --no-default-features --features "std"`

## Notes

The following items require the `alloc` feature to be enabled:

- `CubicBSpline`
- `CubicBezier`
- `CubicCardinalSpline`
- `CubicCurve`
- `CubicGenerator`
- `CubicHermite`
- `CubicNurbs`
- `CyclicCubicGenerator`
- `RationalCurve`
- `RationalGenerator`
- `BoxedPolygon`
- `BoxedPolyline2d`
- `BoxedPolyline3d`
- `SampleCurve`
- `SampleAutoCurve`
- `UnevenSampleCurve`
- `UnevenSampleAutoCurve`
- `EvenCore`
- `UnevenCore`
- `ChunkedUnevenCore`

This requirement could be relaxed in certain cases, but I had erred on
the side of gating rather than modifying. Since `no_std` is a new set of
platforms we are adding support to, and the `alloc` feature is enabled
by default, this is not a breaking change.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
Co-authored-by: Matty <2975848+mweatherley@users.noreply.github.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-12-03 17:14:51 +00:00
Vic
aa600ae95e
implement the full set of sorts on QueryManyIter (#13443)
# Objective

~Blocked on #13417~

Motivation is the same as in #13417. If users can sort `QueryIter`, to
only makes sense to also allow them to use this functionality on
`QueryManyIter`.

## Solution

Also implement the sorts on `QueryManyIter`. 

The implementation of the sorts themselves are mostly the same as with
`QueryIter` in #13417.
They differ in that they re-use the `entity_iter` passed to the
`iter_many`, and internally call `iter_many_unchecked_manual` on the
lens `QueryState` with it.
These methods also return a different struct, `QuerySortedManyIter`,
because there is no longer a guarantee of unique entities.
`QuerySortedManyIter` implements the various `Iterator` traits for
read-only iteration, as `QueryManyIter` does + `DoubleEndedIterator`.
For mutable iteration, there is both a `fetch_next` and a
`fetch_next_back` method. However, they only become available after the
user calls `collect_inner` on `QuerySortedManyIter` first. This collects
the inner `entity_iter` (this is the sorted one, **not** the original
the user passed) to drop all query lens items to avoid aliasing.
When TAITs are available this `collect_inner` could be hidden away,
until then it is unfortunately not possible to elide this without either
regressing read-only iteration, or introducing a whole new type, mostly
being a copy of `QuerySortedIter`.

As a follow-up we could add a `entities_all_unique` method to check
whether the entity list consists of only unique entities, and then
return a `QuerySortedIter` from it (under opaque impl Trait if need be),
*allowing mutable `Iterator` trait iteration* over what was originally
an `iter_many` call.
Such a method can also be added to `QueryManyIter`, albeit needing a
separate, new return type.

## Testing

I've switched the third example/doc test under `sort` out for one that
shows the collect_inner/fetch_next_back functionality, otherwise the
examples are the same as in #13417, adjusted to use `iter_many` instead
of `iter`.

The `query-iter-many-sorts` test checks for equivalence to the
underlying sorts.
The test after shows that these sorts *do not* panic after
`fetch`/`fetch_next` calls.

## Changelog

Added `sort`, `sort_unstable`, `sort_by`, `sort_unstable_by`,
`sort_by_key`, `sort_by_cached_key` to `QueryManyIter`.
Added `QuerySortedManyIter`.
2024-12-03 17:02:37 +00:00
atlv
d4883a9b5f
switch bevy_image to use wgpu-types wherever possible instead of wgpu (#16620)
# Objective

- dont depend on wgpu if we dont have to

## Solution

- works towards this, but doesnt fully accomplish it. the remaining
types stopping us from doing this need to be moved upstream, i will PR
this

## Testing

- 3d_scene runs

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-12-03 11:46:10 +00:00
Zachary Harrold
c02696b609
Add Commands::run_schedule (#16537)
# Objective

- Fixes #16495

## Solution

- Added `Commands::run_schedule`, which internally calls
`World::try_run_schedule`, logging any issues.

## Testing

- Added doctest
- Ran CI

## Showcase

Instead of writing:

```rust
commands.queue(|world: &mut World| world.run_schedule(FooSchedule));
```

You can now write:

```rust
commands.run_schedule(FooSchedule);
```
2024-12-02 22:16:58 +00:00
James O'Brien
793e2f2000
Update Contributor's Guide link in README.md (#16592)
# Objective

- Fix outdated link in README.md

Perhaps the link name should be updated as well since the article is no
longer labelled as "Contributor's Guide"?
Either way better to avoid making users click twice.
2024-12-02 15:18:19 +00:00
ickshonpe
56d5591028
Multiple box shadow support (#16502)
# Objective

Add support for multiple box shadows on a single `Node`.

## Solution

* Rename `BoxShadow` to `ShadowStyle` and remove its `Component` derive.
* Create a new `BoxShadow` component that newtypes a `Vec<ShadowStyle>`.
* Add a `new` constructor method to `BoxShadow` for single shadows.
* Change `extract_shadows` to iterate through a list of shadows per
node.

Render order is determined implicitly from the order of the shadows
stored in the `BoxShadow` component, back-to-front.
Might be more efficient to use a `SmallVec<[ShadowStyle; 1]>` for the
list of shadows but not sure if the extra friction is worth it.

## Testing

Added a node with four differently coloured shadows to the `box_shadow`
example.

---

## Showcase

```
cargo run --example box_shadow
```

<img width="460" alt="four-shadow"
src="https://github.com/user-attachments/assets/2f728c47-33b4-42e1-96ba-28a774b94b24">

## Migration Guide

Bevy UI now supports multiple shadows per node. A new struct
`ShadowStyle` is used to set the style for each shadow. And the
`BoxShadow` component is changed to a tuple struct wrapping a vector
containing a list of `ShadowStyle`s. To spawn a node with a single
shadow you can use the `new` constructor function:
```rust
commands.spawn((
    Node::default(),
    BoxShadow::new(
        Color::BLACK.with_alpha(0.8),
        Val::Percent(offset.x),
        Val::Percent(offset.y),
        Val::Percent(spread),
        Val::Px(blur),
    )
));
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-01 21:30:08 +00:00
Sou1gh0st
206f4f7f5f
Add .contains_aabb for Frustum (#16022)
# Objective

- Fixes: #15663

## Solution

- Add an `is_forward_plane` method to `Aabb`, and a `contains_aabb`
method to `Frustum`.

## Test
- I have created a frustum with an offset along with three unit tests to
evaluate the `contains_aabb` algorithm.

## Explanation for the Test Cases
- To facilitate the code review, I will explain how the frustum is
created. Initially, we create a frustum without any offset and then
create a cuboid that is just contained within it.

<img width="714" alt="image"
src="https://github.com/user-attachments/assets/a9ac53a2-f8a3-4e09-b20b-4ee71b27a099">

- Secondly, we move the cuboid by 2 units along both the x-axis and the
y-axis to make it more general.


## Reference
- [Frustum
Culling](https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling#)
- [AABB Plane
intersection](https://gdbooks.gitbooks.io/3dcollisions/content/Chapter2/static_aabb_plane.html)

---------

Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
2024-12-01 21:30:01 +00:00
François Mockers
fcfb685821
enable_state_scoped_entities() as a derive attribute (#16180)
# Objective

- I got tired of calling `enable_state_scoped_entities`, and though it
would make more sense to define that at the place where the state is
defined

## Solution

- add a derive attribute `#[states(scoped_entities)]` when derive
`States` or `SubStates` that enables it automatically when adding the
state

## Testing

- Ran the examples using it, they still work
2024-12-01 20:09:36 +00:00
vil'mo
2a1064ec5e
Getting QueryState from immutable World reference (#16434)
# Objective

There is currently no way of getting `QueryState` from `&World`, so it
is hard to, for example, iterate over all entities with a component,
only having `&World`.

## Solution

Add `try_new` function to `QueryState` that internally uses
`WorldQuery`'s `get_state`.

## Testing

No testing
2024-12-01 20:09:29 +00:00
Christian Hughes
6fe4b1440c
Refactor FunctionSystem to use a single Option (#16514)
# Objective

Combine the `Option<_>` state in `FunctionSystem` into a single `Option`
to provide clarity and save space.

## Solution

Simplifies `FunctionSystem`'s layout by using a single
`Option<FunctionSystemState>` for state that must be initialized before
running, and saves a byte by removing the need to store an enum tag.
Additionally, calling `System::run` on an uninitialized `System` will
now give a more descriptive message prior to verifying the `WorldId`.

## Testing

Ran CI checks locally.
2024-12-01 20:09:22 +00:00
François Mockers
4282c3fe40
make example external_source_external_thread deterministic (#16574)
# Objective

- make example external_source_external_thread deterministic

## Solution

- Don't depend on real time
2024-12-01 20:09:13 +00:00
Armin Schäfer M.Sc.
2309c07e8e
Updated comment: ZIndex::Local(0) -> ZIndex(0). (#16585)
# Objective

In c5742ff43e ZIndex::Local() and
ZIndex::Global() were replaced with ZIndex() and GlobalZIndex().

A comment was likely forgotten.

## Solution

- Remove the deprecated "::Local" in the comment.
2024-12-01 20:09:09 +00:00
Arnav Mummineni
39842170a5
Update example link (#16581)
# Objective

Redirects broken example link to point to the most similar alternative
2024-12-01 09:47:22 +00:00
Rob Parrett
c425c32064
Fix a couple typos (#16573)
# Objective

Fix typo reported on
[discord](https://discord.com/channels/691052431525675048/743559241461399582/1312485153284558932).

## Solution

- Search for "will can."
- Fix typo
- Fix another related typo
2024-11-30 19:28:53 +00:00
Vic
eaa7dfedea
fix QueryIter::sort_unstable_by (#16565)
# Objective

`QueryIter::sort_unstable_by` is mistakenly using `slice::sort_by`.

## Solution

Use `slice::sort_unstable_by`.
2024-11-30 15:24:35 +00:00
Niklas Eicker
89d094e50f
Remove duplicated default feature (#16552)
# Objective

- The feature `android-game-activity` was in the default feature list
twice

## Solution

- Remove one of the features
2024-11-30 02:02:25 +00:00
Matty Weatherley
83b725f41e
Make bevy_gltf compile without bevy_animation feature (#16551)
# Objective

See title.

## Solution

Move `bevy_animation` import to where it is used.

## Testing

Compiled with and without `bevy_animation` feature enabled.
2024-11-30 00:04:30 +00:00
François Mockers
2745aa102d
Fix example build for wasm (#16557)
# Objective

- Some examples failed to build for wasm on the website

## Solution

- Fix them
  - `Msaa` is now a component instead of a resource
2024-11-30 00:02:04 +00:00
François Mockers
c1d392a5c6
Reduce iOS cpu usage (#16548)
# Objective

- Avoid recreating the monitor every loop (temp fix until it's done
properly on winit side)
- Add a new `WinitSettings` preset for mobile that makes the winit loop
wait more and recommend its usage
2024-11-29 00:34:40 +00:00
Alice Cecile
75c92fb47b
Clarify inheritance behavior of required components (#16546)
Co-authored by: @BenjaminBrienen

# Objective

Fixes #16494. Closes #16539, which this replaces. Suggestions alone
weren't enough, so now we have a new PR!

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-11-28 21:09:26 +00:00
UkoeHB
696c00641f
Improve ZIndex docs (#16536)
# Objective

- In 0.14, ZIndex and GlobalZIndex where split from a shared enum into
separate components. There have been a few people confused by the
behavior of ZIndex when they really needed GlobalZIndex.

## Solution

- Update ZIndex docs to improve discoverability of GlobalZIndex.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2024-11-28 17:31:03 +00:00
Lomírus
740e8f74dd
fix: scroll list is non-scrollable (#16540)
# Objective

Run `testbed_ui` example:

```
cargo run --example testbed_ui
```

The scroll list is non-scrollable because it's blocked by the front
four-icon node.

## Solution

Add `PickingBehavior::IGNORE` for the front node

## Testing

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

Yes.

- Are there any parts that need more testing?

No, I guess.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
```
cargo run --example testbed_ui
```
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

macOS.
2024-11-28 17:27:58 +00:00
Alice Cecile
0438f78c94
Fix newline in AnimationEvaluationState docs (#16542)
# Objective

CI [is
broken](https://github.com/bevyengine/bevy/actions/runs/12070933255/job/33661528875)
by the new Rust version.

## Solution

Appease the crab gods by fixing our doc comments.

## Testing

CI has my back!
2024-11-28 17:13:21 +00:00
Kristoffer Søholm
3d72e08f32
Fix CAS toggle broken by retained render world (#16533)
# Objective

Fixes #16531

I also added change detection when creating the pipeline, which
technically isn't needed but it felt weird leaving it as is.

## Solution

Remove the pipeline if CAS is disabled. The uniform was already being
removed, which caused flickering / weirdness.

## Testing

Tested the anti_alias example by toggling CAS a bunch on/off.
2024-11-27 23:38:09 +00:00
Carter Anderson
af10aa38aa
AnimatedField and Rework Evaluators (#16484)
# Objective

Animating component fields requires too much boilerplate at the moment:

```rust
#[derive(Reflect)]
struct FontSizeProperty;

impl AnimatableProperty for FontSizeProperty {
    type Component = TextFont;

    type Property = f32;

    fn get_mut(component: &mut Self::Component) -> Option<&mut Self::Property> {
        Some(&mut component.font_size)
    }
}

animation_clip.add_curve_to_target(
    animation_target_id,
    AnimatableKeyframeCurve::new(
        [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
            .into_iter()
            .zip([24.0, 80.0, 24.0, 80.0, 24.0, 80.0, 24.0]),
    )
    .map(AnimatableCurve::<FontSizeProperty, _>::from_curve)
    .expect("should be able to build translation curve because we pass in valid samples"),
);
```

## Solution

This adds `AnimatedField` and an `animated_field!` macro, enabling the
following:

```rust
animation_clip.add_curve_to_target(
    animation_target_id,
    AnimatableCurve::new(
        animated_field!(TextFont::font_size),
        AnimatableKeyframeCurve::new(
            [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
                .into_iter()
                .zip([24.0, 80.0, 24.0, 80.0, 24.0, 80.0, 24.0]),
        )
        .expect(
            "should be able to build translation curve because we pass in valid samples",
        ),
    ),
);
```

This required reworking the internals a bit, namely stripping out a lot
of the `Reflect` usage, as that implementation was fundamentally
incompatible with the `AnimatedField` pattern. `Reflect` was being used
in this context just to downcast traits. But we can get downcasting
behavior without the `Reflect` requirement by implementing `Downcast`
for `AnimationCurveEvaluator`.

This also reworks "evaluator identity" to support either a (Component /
Field) pair, or a TypeId. This allows properties to reuse evaluators,
even if they have different accessor methods. The "contract" here is
that for a given (Component / Field) pair, the accessor will return the
same value. Fields are identified by their Reflect-ed field index. The
(TypeId, usize) is prehashed and cached to optimize for lookup speed.

This removes the built-in hard-coded TranslationCurve / RotationCurve /
ScaleCurve in favor of AnimatableField.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-11-27 22:19:55 +00:00
Carter Anderson
a6e13977d5
Fix CAS shader alpha accessor (#16530)
# Objective

Fixes #16528 

## Solution

Use `a` to access alpha instead of `w`
2024-11-27 21:51:29 +00:00
MichiRecRoom
2a66bf0909
Clarify that bevy_app::App.world() (and mut variant) returns the main SubApp's World (#16527)
# Objective
The documentation for `bevy_app::App.world()` (and its mut variant)
could confuse some into thinking that this is the only World that the
App will contain.

## Solution
Clarify the documentation for `bevy_app::App.world()` (and its mut
variant), to say that it returns the main subapp's world. This helps
imply that Apps can contain more than one world (albeit, only one per
SubApp).

## Testing
This is a documentation change, with no changes to doctests. Thus,
testing is not necessary beyond ensuring the link syntax is correct.
2024-11-27 16:09:09 +00:00
Carter Anderson
0a8e2a3c9d
Skip empty spans when updating text buffers (#16524)
# Objective

Fixes #16521

## Solution

If an empty span is encountered (such as the default `Text` value), we
skip it entirely when updating buffers. This prevents unnecessarily
bailing when the font doesn't exist (ex: when the default font is
disabled)
2024-11-27 03:28:43 +00:00
Carter Anderson
6659f37df1
Revert "Update sysinfo version to 0.32.1 (#16517)" (#16523)
This reverts commit 3476a9f3a658fe7c8326ca0e618ad543914ca7f4.

# Objective

#16517 makes it impossible to select a libc version, now that the
"breaking" libc release was yanked

## Solution

Revert the version bump so we can select a version of sysinfo that
builds (the previous version)
2024-11-26 22:44:23 +00:00
François Mockers
98d433a174
use scale factor for touches in UI focus (#16522)
# Objective

- Fix the issue mentioned on iOS in
https://github.com/bevyengine/bevy/issues/16363#issuecomment-2499766031
- touch on the button in the mobile example are not detected

## Solution

- UI focus now uses the window scale factor for touches
2024-11-26 21:23:12 +00:00
Guillaume Gomez
6ce566cb07
Update sysinfo version to 0.32.1 (#16517)
Fixes bug for new libc release.
2024-11-26 11:44:17 +00:00
François Mockers
ed8ac30836
use wgpu patch 23.0.1 (#16513)
# Objective

- Fixes #16363
- Ensure that someone using minimum version doesn't get the bugs that
were fixed in the 23.0.1 patch

## Solution

- Use wgpu 23.0.1
2024-11-25 22:47:31 +00:00
ickshonpe
efd2982a88
BorderRadius::percent fix (#16506)
# Objective

Fix the `BorderRadius::percent` function so that it sets percentage
values, not pixel.
2024-11-25 16:40:51 +00:00
Rich Churcher
bb81a2cdb3
Simple integration testing (adopted) (#16489)
# Objective

This older PR from `Wcubed` seemed well worth saving, adopted from
#7314. See also tracking issue #2896 for ongoing discussion of Bevy
testability. Thanks `Wcubed`!

## Solution

- Updated for 0.15
- Added the `expected`/`actual` pattern
- Switched to function plugin
- Tweaked a bit of description

## Testing

Green.

---------

Co-authored-by: Wybe Westra <dev@wwestra.nl>
Co-authored-by: Wybe Westra <wybe.westra@protonmail.com>
2024-11-24 20:54:59 +00:00
Joona Aalto
da68bfe94b
Fix Single doc links (#16493)
# Objective

In the [*Similar parameters* section of
`Query`](https://dev-docs.bevyengine.org/bevy/ecs/prelude/struct.Query.html#similar-parameters),
the doc link for `Single` actually links to `Query::single`, and
`Option<Single>` just links to `Option`. They should both link to
`Single`!

The first link is broken because there is a reference-style link defined
for `single`, but not for `Single`, and rustdoc treats the link as
case-insensitive for some reason.

## Solution

Fix the links!

## Testing

I built the docs locally with `cargo doc` and tested the links.
2024-11-24 18:44:00 +00:00