Commit graph

5971 commits

Author SHA1 Message Date
ickshonpe
86ee8e4376
Move UiImage from ui_node to the widget::image module (#16084)
# Objective

`UiImage` isn't just a general image component now, it's the defining
component for the image widget so it belongs in the image widget's
module.
2024-10-27 19:14:46 +00:00
Hexroll by Pen, Dice & Paper
d01db9b672
Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization (#16090)
# Objective

Order independent transparency can filter fragment writes based on the
alpha value and it is currently hard-coded to anything higher than 0.0.
By making that value configurable, users can optimize fragment writes,
potentially reducing the number of layers needed and improving
performance in favor of some transparency quality.

## Solution

This PR adds `alpha_threshold` to the
OrderIndependentTransparencySettings component and uses the struct to
configure a corresponding shader uniform. This uniform is then used
instead of the hard-coded value.

To configure OIT with a custom alpha threshold, use:

```rust
fn setup(mut commands: Commands) {
    commands.spawn((
        Camera3d::default(),
        OrderIndependentTransparencySettings {
            layer_count: 8,
            alpha_threshold: 0.2,
        },
    ));
}
```

## Testing

I tested this change using the included OIT example, as well as with two
additional projects.

## Migration Guide

If you previously explicitly initialized
OrderIndependentTransparencySettings with your own `layer_count`, you
will now have to add either a `..default()` statement or an explicit
`alpha_threshold` value:

```rust
fn setup(mut commands: Commands) {
    commands.spawn((
        Camera3d::default(),
        OrderIndependentTransparencySettings {
            layer_count: 16,
            ..default()
        },
    ));
}
```

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2024-10-27 19:08:34 +00:00
Miles Silberling-Cook
7451900e71
Emit picking event streams (#16105)
# Objective

In `bevy_mod_picking` events are accessible through event listeners or
`EventReader`s. When I replaced event listeners with observers, I
removed the `EventReader` for simplicity. This adds it back.

## Solution

All picking events are now properly registered, and can be accessed
through `EventReader<Pointer<E>>`. `Pointer` now tracks the entity the
event targeted initially, and this can also be helpful in observers
(which don't currently do this).

## Testing

The picking examples run fine. This shouldn't really change anything.

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
2024-10-27 19:05:31 +00:00
Aevyrie
54b323ec80
Mesh picking fixes (#16110)
# Objective

- Mesh picking is noisy when a non triangle list is used
- Mesh picking runs even when users don't need it
- Resolve #16065 

## Solution

- Don't add the mesh picking plugin by default
- Remove error spam
2024-10-27 19:03:48 +00:00
Tau Gärtli
a644ac73f7
More #[doc(fake_variadic)] goodness (#16108)
This PR adds `#[doc(fake_variadic)]` to that were previously not
supported by rustdoc.

Thanks to an [upstream
contribution](https://github.com/rust-lang/rust/pull/132115) by yours
truly, `#[doc(fake_variadic)]` is now supported on impls such as `impl
QueryData for AnyOf<(T, ...)>` 🎉
Requires the latest nightly compiler (2024-10-25) which is already
available on [docs.rs](https://docs.rs/about/builds).


![image](https://github.com/user-attachments/assets/68589c7e-f68f-44fb-9a7b-09d24ccf19c9)

![image](https://github.com/user-attachments/assets/f09d20d6-d89b-471b-9a81-4a72c8968178)

This means that the impl sections for `QueryData` and `QueryFilter` are
now nice and tidy 

---

I also added `fake_variadic` to some impls that use
`all_tuples_with_size`, however I'm not entirely happy because the docs
are slightly misleading now:


![image](https://github.com/user-attachments/assets/fac93d08-dc02-430f-9f34-c97456256c56)

Note that the docs say `IntoBindGroupLayoutEntryBuilderArray<1>` instead
of
`IntoBindGroupLayoutEntryBuilderArray<N>`.
2024-10-27 19:01:50 +00:00
François Mockers
60b2c7ce77
fix bevy_dev_tools build (#16099)
# Objective

- bevy_dev_tools 0.15.0-rc.1 failed to build docs
- it use bevy_text feature in bevy_ui but it's not enabled by default
- https://docs.rs/crate/bevy_dev_tools/0.15.0-rc.1
- 
## Solution

- enable bevy_text feature of bevy_ui
2024-10-25 20:14:39 +00:00
BD103
7c593179e3
Fix bevy_picking plugin suffixes (#16082)
# Objective

- `MeshPickingBackend` and `SpritePickingBackend` do not have the
`Plugin` suffix
- `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality
it should be a `PluginGroup`
- Fixes #16081.

## Solution

- Rename some structures:

|Original Name|New Name|
|-|-|
|`MeshPickingBackend`|`MeshPickingPlugin`|
|`MeshPickingBackendSettings`|`MeshPickingSettings`|
|`SpritePickingBackend`|`SpritePickingPlugin`|
|`UiPickingBackendPlugin`|`UiPickingPlugin`|

- Make `DefaultPickingPlugins` a `PluginGroup`.
- Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin
group, I also added support for nested plugin groups to the
`plugin_group!` macro.

## Testing

- I used ripgrep to ensure all references were properly renamed.
- For the `plugin_group!` macro, I used `cargo expand` to manually
inspect the expansion of `DefaultPlugins`.

---

## Migration Guide

> [!NOTE]
>
> All 3 of the changed structures were added after 0.14, so this does
not need to be included in the 0.14 to 0.15 migration guide.

- `MeshPickingBackend` is now named `MeshPickingPlugin`.
- `MeshPickingBackendSettings` is now named `MeshPickingSettings`.
- `SpritePickingBackend` is now named `SpritePickingPlugin`.
- `UiPickingBackendPlugin` is now named `UiPickingPlugin`.
- `DefaultPickingPlugins` is now a a `PluginGroup` instead of a
`Plugin`.
2024-10-25 20:11:51 +00:00
Ludwig DUBOS
611ba8b98e
Add AsyncSeekForwardExt trait to allows a similar API to the previous Bevy version (#16027)
# Objective

This PR introduces an `AsyncSeekForwardExt` trait, which I forgot in my
previous PR #14194.

This new trait is analogous to `AsyncSeekExt` and allows all
implementors of `AsyncSeekForward` to directly use the `seek_forward`
function in async contexts.

## Solution

- Implement a new `AsyncSeekForwardExt` trait
- Automatically implement this trait for all types that implement
`AsyncSeekForward`

## Showcase

This new trait allows a similar API to the previous Bevy version:

```rust
#[derive(Default)]
struct UniverseLoader;

#[derive(Asset, TypePath, Debug)]
struct JustALilAsteroid([u8; 128]);

impl AssetLoader for UniverseLoader {
    type Asset = JustALilAsteroid;
    type Settings = ();
    type Error = std::io::Error;

    async fn load<'a>(
        &'a self,
        reader: &'a mut Reader<'a>,
        _settings: &'a Self::Settings,
        _context: &'a mut LoadContext<'_>,
    ) -> Result<Self::Asset, Self::Error> {
        // read the asteroids entry table
        let entry_offset: u64 = /* ... */;
        let current_offset: u64 = reader.seek_forward(0).await?;

        // jump to the entry
        reader.seek_forward(entry_offset - current_offset).await?;

        let mut asteroid_buf = [0; 128];
        reader.read_exact(&mut asteroid_buf).await?;

        Ok(JustALilAsteroid(asteroid_buf))
    }
    
    fn extensions(&self) -> &[&str] {
        &["celestial"]
    }
}
```
2024-10-25 20:08:14 +00:00
Patrick Walton
c6a66a7e96
Place percentage-closer soft shadows behind a feature gate to save on samplers. (#16068)
The two additional linear texture samplers that PCSS added caused us to
blow past the limit on Apple Silicon macOS and WebGL. To fix the issue,
this commit adds a `--feature pbr_pcss` feature gate that disables PCSS
if not present.

Closes #15345.
Closes #15525.
Closes #15821.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-10-24 21:16:00 +00:00
Patrick Walton
897404ee1e
Reduce the clusterable object UBO size below 16384 for WebGL 2. (#16069)
The PCSS PR #13497 increased the size of clusterable objects from 64
bytes to 80 bytes but didn't decrease the UBO size to compensate, so we
blew past the 16kB limit on WebGL 2. This commit fixes the issue by
lowering the maximum number of clusterable objects to 204, which puts us
under the 16kB limit again.

Closes #15998.
2024-10-24 21:00:11 +00:00
Carter Anderson
9274bfed27
Move TextureAtlas into UiImage and remove impl Component for TextureAtlas (#16072)
# Objective

Fixes #16064

## Solution

- Add TextureAtlas to `UiImage::texture_atlas`
- Add `TextureAtlas::from_atlas_image` for parity with `Sprite`
- Rename `UiImage::texture` to `UiImage::image` for parity with `Sprite`
- Port relevant implementations and uses
- Remove `derive(Component)` for `TextureAtlas`

---

## Migration Guide

Before:
```rust
commands.spawn((
  UiImage::new(image),
  TextureAtlas { index, layout },
));
```

After:
```rust
commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout }));
```

Before:
```rust
commands.spawn(UiImage {
    texture: some_image,
    ..default()
})
```

After:
```rust
commands.spawn(UiImage {
    image: some_image,
    ..default()
})
```
2024-10-23 23:24:17 +00:00
Viktor Gustavsson
2cdad48b30
Ensure ghost nodes are skipped when getting parent clipping rect (#16058)
# Objective

- Follow up on #16044
- `extract_uinode_borders` uses `bevy_hierarchy` directly instead of
going through the traversal utilities, meaning it won't handle
`GhostNode`s properly.

## Solution

- Replaced the use of `bevy_hierarchy::Parent` with
`UIChildren::get_parent`

## Testing

- Ran the `overflow` example, clipping looks ok.

---

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-23 21:51:39 +00:00
ickshonpe
c9a3f34f5d
Fixes for a few minor borders and outlines bugs (#16071)
# Objective

1. Nodes with `Display::None` set are removed from the layout and have
no position or size. Outlines should not be drawn for a node with
`Display::None` set.
2. The outline and border colors are checked for transparency together.
If only one of the two is transparent, both will get queued.
3. The `node.is_empty()` check is insufficient to check if a border is
present since a non-zero sized node can have a zero width border.

## Solution

1. Add a check to `extract_uinode_borders` and ignore the node if
`Display::None` is set.
2. Filter the border and outline optional components by
`is_fully_transparent`.
3.  Check if all the border widths are zero instead.

## Testing

I added dark cyan outlines around the left and right sections in the
`display_and_visibility` example. If you run the example and set the
outermost node to `Display::None` on the right, then you'll see the that
the outline on the left disappears.
2024-10-23 20:41:42 +00:00
Carter Anderson
7577895d0c
Use CosmicFontSystem in public bevy_text APIs and remove cosmic_text re-export (#16063)
# Objective

Fixes #16006

## Solution

We currently re-export `cosmic_text`, which is seemingly motivated by
the desire to use `cosmic_text::FontSystem` in `bevy_text` public APIs
instead of our `CosmicFontSystem` resource wrapper type.

This change makes `bevy_text` a "true" abstraction over `cosmic_text`
(it in fact, was already built to be that way generally and has this one
"leak").

This allows us to remove the `cosmic_text` re-export, which helps clean
up the Rust Analyzer imports and generally makes this a "cleaner" API.
2024-10-23 20:05:28 +00:00
JMS55
3fb6cefb2f
Meshlet fill cluster buffers rewritten (#15955)
# Objective
- Make the meshlet fill cluster buffers pass slightly faster
- Address https://github.com/bevyengine/bevy/issues/15920 for meshlets
- Added PreviousGlobalTransform as a required meshlet component to avoid
extra archetype moves, slightly alleviating
https://github.com/bevyengine/bevy/issues/14681 for meshlets
- Enforce that MeshletPlugin::cluster_buffer_slots is not greater than
2^25 (glitches will occur otherwise). Technically this field controls
post-lod/culling cluster count, and the issue is on pre-lod/culling
cluster count, but it's still valid now, and in the future this will be
more true.

Needs to be merged after https://github.com/bevyengine/bevy/pull/15846
and https://github.com/bevyengine/bevy/pull/15886

## Solution

- Old pass dispatched a thread per cluster, and did a binary search over
the instances to find which instance the cluster belongs to, and what
meshlet index within the instance it is.
- New pass dispatches a workgroup per instance, and has the workgroup
loop over all meshlets in the instance in order to write out the cluster
data.
- Use a push constant instead of arrayLength to fix the linked bug
- Remap 1d->2d dispatch for software raster only if actually needed to
save on spawning excess workgroups

## Testing

- Did you test these changes? If so, how?
- Ran the meshlet example, and an example with 1041 instances of 32217
meshlets per instance. Profiled the second scene with nsight, went from
0.55ms -> 0.40ms. Small savings. We're pretty much VRAM bandwidth bound
at this point.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Run the meshlet example

## Changelog (non-meshlets)
- PreviousGlobalTransform now implements the Default trait
2024-10-23 19:18:49 +00:00
JMS55
6d42830c7f
Meshlet builder improvements redux (#15886)
Take a bunch more improvements from @zeux's nanite.cpp code.

* Use position-only vertices (discard other attributes) to determine
meshlet connectivity for grouping
* Rather than using the lock borders flag when simplifying meshlet
groups, provide the locked vertices ourselves. The lock borders flag
locks the entire border of the meshlet group, but really we only want to
lock the edges between meshlet groups - outwards facing edges are fine
to unlock. This gives a really significant increase to the DAG quality.
* Add back stuck meshlets (group has only a single meshlet,
simplification failed) to the simplification queue to allow them to get
used later on and have another attempt at simplifying
* Target 8 meshlets per group instead of 4 (second biggest improvement
after manual locks)
* Provide a seed to metis for deterministic meshlet building
* Misc other improvements

We can remove the usage of unsafe after the next upstream meshopt
release, but for now we need to use the ffi function directly. I'll do
another round of improvements later, mainly attribute-aware
simplification and using spatial weights for meshlet grouping.

Need to merge https://github.com/bevyengine/bevy/pull/15846 first.
2024-10-23 16:56:50 +00:00
akimakinai
50d38f2757
Fix point light count limit (#16062)
# Objective

- I made a mistake in #15902, specifically [this
diff](e2faedb99c)
-- the `point_light_count` variable is used for all point lights, not
just shadow mapped ones, so I cannot add `.min(max_texture_cubes)`
there. (Despite `spot_light_count` having `.min(..)`)

It may have broken code like this (where `index` is index of
`point_light` vec):


9930df83ed/crates/bevy_pbr/src/render/light.rs (L848-L850)

and also causes panic here:

9930df83ed/crates/bevy_pbr/src/render/light.rs (L1173-L1174)

## Solution

- Adds `.min(max_texture_cubes)` directly to the loop where texture
views for point lights are created.

## Testing

- `lighting` example (with the directional light removed; original
example doesn't crash as only 1 directional-or-spot light in total is
shadow-mapped on webgl) no longer crashes on webgl
2024-10-22 23:29:58 +00:00
JMS55
2223f6ec3a
Meshlet fix software rasterization (#16049)
# Objective
1. Prevent weird glitches with stray pixels scattered around the scene

![image](https://github.com/user-attachments/assets/f12adb38-5996-4dc7-bea6-bd326b7317e1)
2. Prevent weird glitchy full-screen triangles that pop-up and destroy
perf (SW rasterizing huge triangles is slow)

![image](https://github.com/user-attachments/assets/d3705427-13a5-47bc-a54b-756f0409da0b)

## Solution
1. Use floating point math in the SW rasterizer bounding box calculation
to handle negative verticss, and add backface culling
2. Force hardware raster for clusters that clip the near plane, and let
the hardware rasterizer handle the clipping

I also adjusted the SW rasterizer threshold to < 64 pixels (little bit
better perf in my test scene, but still need to do a more comprehensive
test), and enabled backface culling for the hardware raster pipeline.

## Testing

- Did you test these changes? If so, how?
  - Yes, on an example scene. Issues no longer occur.
- Are there any parts that need more testing?
  - No.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
  - Run the meshlet example.
2024-10-22 23:05:40 +00:00
François Mockers
fac0b34b20
remove reference to missing file in bevy_remote cargo.toml (#16057)
# Objective

- bevy_remote Cargo.toml file references a readme that doesn't exist
- This is blocking releasing the rc

## Solution

- Remove the reference
2024-10-22 20:21:19 +00:00
JMS55
9d54fe0370
Meshlet new error projection (#15846)
* New error projection code taken from @zeux's meshoptimizer nanite.cpp
demo for determining LOD (thanks zeux!)
* Builder: `compute_lod_group_data()`
* Runtime: `lod_error_is_imperceptible()`
2024-10-22 20:14:30 +00:00
ickshonpe
9930df83ed
UI borders and outlines clipping fix (#16044)
# Objective

fixes #15502

Clipped borders and outlines aren't drawn correctly.

### Borders aren't clipped

Spawn two nodes with the same dimensions and border thickness, but clip
on of the nodes so that only its top left quarter is visible:

<img width="194" alt="clip"
src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294">

You can see that instead of clipping the border, instead the border is
scaled to fit inside of the unclipped section.

```rust
use bevy::color::palettes::css::BLUE;
use bevy::prelude::*;
use bevy::winit::WinitSettings;

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

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands
        .spawn(Node {
            width: Val::Percent(100.),
            height: Val::Percent(100.),
            justify_content: JustifyContent::Center,
            align_items: AlignItems::Center,
            ..Default::default()
        })
        .with_children(|commands| {
            commands
                .spawn(Node {
                    column_gap: Val::Px(10.),
                    ..Default::default()
                })
                .with_children(|commands| {
                    commands
                        .spawn(Node {
                            width: Val::Px(100.),
                            height: Val::Px(100.),
                            overflow: Overflow::clip(),
                            ..Default::default()
                        })
                        .with_child((
                            Node {
                                position_type: PositionType::Absolute,
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                border: UiRect::all(Val::Px(10.)),
                                ..Default::default()
                            },
                            BackgroundColor(Color::WHITE),
                            BorderColor(BLUE.into()),
                        ));

                    commands
                        .spawn(Node {
                            width: Val::Px(50.),
                            height: Val::Px(50.),
                            overflow: Overflow::clip(),
                            ..Default::default()
                        })
                        .with_child((
                            Node {
                                position_type: PositionType::Absolute,
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                border: UiRect::all(Val::Px(10.)),
                                ..Default::default()
                            },
                            BackgroundColor(Color::WHITE),
                            BorderColor(BLUE.into()),
                        ));
                });
        });
}
```

You can also see this problem in the `overflow` example. If you hover
over any of the clipped nodes you'll see that the outline only wraps the
visible section of the node

### Outlines are clipped incorrectly

A UI nodes Outline's are drawn outside of its bounds, so applying the
local clipping rect to the outline doesn't make any sense.
Instead an `Outline` should be clipped using its parent's clipping rect.

## Solution

* Pass the `point` value into the vertex shader instead of calculating
it in the shader.
* In `extract_uinode_borders` use the parents clipping rect when
clipping outlines.

The extra parameter isn't a great solution I think, but I wanted to fix
borders for the 0.15 release and this is the most minimal approach I
could think of without replacing the whole shader and prepare function.

 ## Showcase

<img width="149" alt="clipp"
src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd">

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-21 22:54:09 +00:00
Stepan Koltsov
d0af199249
Add a test for Mesh::triangles and fix for TriangleStrip (#16026)
# Objective

- Illustrate behavior with a test
- Fix a bug revealed by a test

## Solution

- Add a test and fix

## Testing

Test added.
2024-10-21 15:57:52 +00:00
Stepan Koltsov
465d1139e7
Replace TwoIterators with Either in bevy_animation (#16036)
# Objective

- Less code
- Better iterator (implements `size_hint` for example)

## Solution

- Use `either`
- This change is free because `bevy_animation` depends on `bevy_asset`,
which already depends on `either`

## Testing

CI
2024-10-21 02:17:59 +00:00
Rob Parrett
30d84519a2
Use en-us locale for typos (#16037)
# Objective

Bevy seems to want to standardize on "American English" spellings. Not
sure if this is laid out anywhere in writing, but see also #15947.

While perusing the docs for `typos`, I noticed that it has a `locale`
config option and tried it out.

## Solution

Switch to `en-us` locale in the `typos` config and run `typos -w`

## Migration Guide

The following methods or fields have been renamed from `*dependants*` to
`*dependents*`.

- `ProcessorAssetInfo::dependants`
- `ProcessorAssetInfos::add_dependant`
- `ProcessorAssetInfos::non_existent_dependants`
- `AssetInfo::dependants_waiting_on_load`
- `AssetInfo::dependants_waiting_on_recursive_dep_load`
- `AssetInfos::loader_dependants`
- `AssetInfos::remove_dependants_and_labels`
2024-10-20 18:55:17 +00:00
Stepan Koltsov
472bbaae26
Unnecessary division in compute_smooth_normals (#16039)
# Objective

- Less code
- Simpler code

## Solution

- Remove unnecessary division: `normalize` already does that

## Testing

- Test added in #16038
2024-10-20 18:55:08 +00:00
Stepan Koltsov
2e2d669406
Add a test for Mesh::compute_smooth_normals (#16038)
# Objective

- Code is safer with tests

## Solution

- Add a test

## Testing

- Test added
2024-10-20 18:10:41 +00:00
SpecificProtagonist
3eec0f0a77
QueryEntityError: Use short name for components (#16032)
Use the new `disqualified` crate in `QueryEntityError` to make the error
message more readable.

---

## Showcase

Old:
QueryDoesNotMatch(0v1 with components my_game::main::foo::A,
my_game::main::foo::B, bevy_pbr::light::point_light::PointLight,
bevy_render::primitives::CubemapFrusta,
bevy_pbr::bundle::CubemapVisibleEntities,
bevy_transform::components::transform::Transform,
bevy_transform::components::global_transform::GlobalTransform,
bevy_render::view::visibility::Visibility,
bevy_render::view::visibility::InheritedVisibility,
bevy_render::view::visibility::ViewVisibility,
bevy_render::sync_world::SyncToRenderWorld)

New:
QueryDoesNotMatch(0v1 with components A, B, PointLight, CubemapFrusta,
CubemapVisibleEntities, Transform, GlobalTransform, Visibility,
InheritedVisibility, ViewVisibility, SyncToRenderWorld)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-20 17:56:43 +00:00
Stepan Koltsov
34c9a64779
Mute unreachable patterns/code warnings (#16012)
# Objective

Make compiler output more helpful when running `cargo check -p
bevy_mesh`. Currently it contains a lot of unreachable patterns/code
warnings due to features disabled by default.

## Solution

Mute the warnings.

## Testing

CI
2024-10-20 14:27:02 +00:00
Stepan Koltsov
405fa3e8ea
Mute non-local definition warnings in bevy_reflect (#16013)
# Objective

```
cargo check -p bevy_reflect
```

outputs a lot of warnings like:

```
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
   --> crates/bevy_reflect/src/impls/std.rs:223:13
    |
223 |               impl_type_path!($ty);
    |               ^-------------------
    |               |
    |               `TypePath` is not local
    |               move the `impl` block outside of this constant `_` and up 2 bodies
...
346 | / impl_reflect_for_atomic!(
347 | |     ::core::sync::atomic::AtomicIsize,
    | |     --------------------------------- `AtomicIsize` is not local
348 | |     ::core::sync::atomic::Ordering::SeqCst
349 | | );
    | |_- in this macro invocation
    |
    = note: the macro `impl_type_path` defines the non-local `impl`, and may need to be changed
    = note: the macro `impl_type_path` may come from an old version of the `bevy_reflect_derive` crate, try updating your dependency with `cargo update -p bevy_reflect_derive`
    = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
    = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint
    = note: `#[warn(non_local_definitions)]` on by default
    = note: this warning originates in the macro `impl_type_path` which comes from the expansion of the macro `impl_reflect_for_atomic` (in Nightly builds, run with -Z macro-backtrace for more info)

```

## Solution

Move `impl_type_path!` into global scope. Warnings no longer pop up.

## Testing

CI
2024-10-20 13:52:52 +00:00
Stepan Koltsov
0cc53458cc
Indices::push(u32) (#16014)
# Objective

Making work with `Indices` struct easier. Currently when building
indices in some quick-and-dirty code we need to do matches and handle
enum variants.

## Solution

`Indices::push` utility which works transparently with `U16` and `U32`
variants.

## Testing

Unit test added.
2024-10-20 13:51:55 +00:00
Peter Hayman
75096fbf97
fix: add reflect to SceneInstanceReady and other observers/events (#16018)
# Objective

Built-in observers & events should be `Reflect` so that components that
interact with them can be serialized in scenes. This is a similar pr to
#14259.
2024-10-20 13:51:41 +00:00
Liam Gallagher
26a5f7f9ca
Feature gate bevy_remote http transport. (#16019)
## Objective
Be able to depend on the crate for the types without bringing in
`smol-hyper` and other http dependencies.

## Solution

Create a new `HTTP` feature that is enabled by default.
2024-10-20 13:49:55 +00:00
Rob Parrett
da5d2fccf5
Fix some duplicate words in docs/comments (#15980)
# Objective

Stumbled upon one of these, and set off in search of more, armed with my
trusty `\b(\w+)\s+\1\b`.

## Solution

Remove ~one~ one of them.
2024-10-20 01:03:27 +00:00
ickshonpe
79e73738c7
Optional UI rendering (#8997)
# Objective

Make UI rendering optional.

Quite a few people have been experimenting with using Bevy UI for layout
and interaction but replacing the rendering with `bevy_prototype_lyon`
or whatever. It's awkward to do though as there is no way to disable the
existing UI rendering requiring users to create their own custom node
bundles and components. Also, you can't replace the UI's shader and a
number of other things.

This PR makes the setup and initialization of UI rendering for the
RenderApp optional. Then you can do whatever you want by replacing
`build_ui_render` with your own function. For instance, one that loads a
custom shader.

The UI layout and interaction components are still updated as normal.

## Solution

Add a field `enable_rendering` to `UiPlugin`.
Only call `build_ui_render` and initialize the `UiPipeline` if
`enable_rendering` is false.

I thought about implementing a "bevy_ui_render" feature but suspect
everything is too tightly coupled atm and it would be very fragile.
Similar to the struggles with the "bevy_text" feature but worse.

---

## Changelog

  `UiPlugin`
  * Added a bool field `enable_rendering`.
* Only calls `build_ui_render` and initializes the `UiPipeline` if
`enable_rendering` is true.

## Migration Guide

`UiPlugin` has a new field `enable_rendering`. If set to false, the UI's
rendering systems won't be added to the `RenderApp` and no UI elements
will be drawn. The layout and interaction components will still be
updated as normal.
2024-10-19 22:52:33 +00:00
Elabajaba
8f31c09e60
Add docs for how to manually add a WinitPlugin to a MinimalPlugins setup. (#15989)
# Objective

Adding a `WinitPlugin` to a `MinimalPlugins` setup is a bit tricky and
confusing due to having a terrible error message and no examples in the
repo.

## Solution

Document what you need to add.
2024-10-19 21:44:02 +00:00
akimakinai
f821768e62
Resolve unused_qualifications warnings (#16001)
# Objective

Fixes the following warning when compiling to wasm.

```
warning: unnecessary qualification
   --> crates\bevy_asset\src\io\mod.rs:733:19
    |
733 |         _cx: &mut core::task::Context<'_>,
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: requested on the command line with `-W unused-qualifications`
help: remove the unnecessary path segments
    |
733 -         _cx: &mut core::task::Context<'_>,
733 +         _cx: &mut Context<'_>,
    |
```

## Solution

- Removes the qualification.
2024-10-19 16:59:58 +00:00
akimakinai
61350cd36f
Remove components if not extracted (#15948)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/15871
(Camera is done in #15946)

## Solution

- Do the same as #15904 for other extraction systems
- Added missing `SyncComponentPlugin` for DOF, TAA, and SSAO
(According to the
[documentation](https://dev-docs.bevyengine.org/bevy/render/sync_component/struct.SyncComponentPlugin.html),
this plugin "needs to be added for manual extraction implementations."
We may need to check this is done.)

## Testing

Modified example locally to add toggles if not exist.
- [x] DOF - toggling DOF component and perspective in `depth_of_field`
example
- [x] TAA - toggling `Camera.is_active` and TAA component
- [x] clusters - not entirely sure, toggling `Camera.is_active` in
`many_lights` example (no crash/glitch even without this PR)
- [x] previous_view - toggling `Camera.is_active` in `skybox` (no
crash/glitch even without this PR)
- [x] lights - toggling `Visibility` of `DirectionalLight` in `lighting`
example
- [x] SSAO - toggling `Camera.is_active` and SSAO component in `ssao`
example
- [x] default UI camera view - toggling `Camera.is_active` (nop without
#15946 because UI defaults to some camera even if `DefaultCameraView` is
not there)
- [x] volumetric fog - toggling existence of volumetric light. Looks
like optimization, no change in behavior/visuals
2024-10-19 15:13:39 +00:00
Rafał Harabień
fe7f98f7f0
Fix deactivated camera still being used in render world (#15946)
# Objective

Switch to retained render world causes the extracted cameras in render
world to not be removed until camera in main world is despawned. When
extracting data from main world inactive cameras are skipped. Therefore
camera that was active and became inactive has a retained
`ExtractedCamera` component from previous frames (when it was active)
and is processed the same way as if it were active (there is no `active`
field on `ExtractedCamera`). This breakes switching between cameras in
`render_primitives` example.
Fixes #15822

## Solution

Fix it by removing `ExtractedCamera` and related components from
inactive cameras.
Note that despawning inactive camera seems to be bad option because they
are spawned using `SyncToRenderWorld` component.

## Testing

Switching camera in `render_primitives` example now works correctly.

---------

Co-authored-by: akimakinai <105044389+akimakinai@users.noreply.github.com>
2024-10-19 15:13:14 +00:00
IceSentry
fcf6067a10
Fix OIT depth test (#15991)
# Objective

- The depth test was only using the final depth but it should be testing
each fragments
- Fully transparent fragments should not be added to the list

## Solution

- Test each fragment after sorting

## Testing

before:
TODO

after:
TODO
2024-10-19 01:16:17 +00:00
Sou1gh0st
3a478ad5c1
Fix lightmaps break when deferred rendering is enabled (#14599)
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/13552

## Solution
- Thanks for the guidance from @DGriffin91, the current solution is to
transmit the light_map through the emissive channel to avoid increasing
the bandwidth of deferred shading.
- <del>Store lightmap sample result into G-Buffer and pass them into the
`Deferred Lighting Pipeline`, therefore we can get the correct indirect
lighting via the `apply_pbr_lighting` function.</del>
- <del>The original G-Buffer lacks storage for lightmap data, therefore
a new buffer is added. We can only use Rgba16Uint here due to the
32-byte limit on the render targets.</del>

## Testing
- Need to test all the examples that contains a prepass, with both the
forward and deferred rendering mode.
- I have tested the ones below.
- `lightmaps` (adjust the code based on the issue and check the
rendering result)
    - `transmission` (it contains a prepass)
    - `ssr` (it also uses the G-Bufffer)
    - `meshlet` (forward and deferred)
    - `pbr`

## Showcase
By updating the `lightmaps` example to use deferred rendering, this pull
request enables correct rendering result of the Cornell Box.

```
diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs
index 564a3162b..11a748fba 100644
--- a/examples/3d/lightmaps.rs
+++ b/examples/3d/lightmaps.rs
@@ -1,12 +1,14 @@
 //! Rendering a scene with baked lightmaps.
 
-use bevy::pbr::Lightmap;
+use bevy::core_pipeline::prepass::DeferredPrepass;
+use bevy::pbr::{DefaultOpaqueRendererMethod, Lightmap};
 use bevy::prelude::*;
 
 fn main() {
     App::new()
         .add_plugins(DefaultPlugins)
         .insert_resource(AmbientLight::NONE)
+        .insert_resource(DefaultOpaqueRendererMethod::deferred())
         .add_systems(Startup, setup)
         .add_systems(Update, add_lightmaps_to_meshes)
         .run();
@@ -19,10 +21,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
         ..default()
     });
 
-    commands.spawn(Camera3dBundle {
-        transform: Transform::from_xyz(-278.0, 273.0, 800.0),
-        ..default()
-    });
+    commands
+        .spawn(Camera3dBundle {
+            transform: Transform::from_xyz(-278.0, 273.0, 800.0),
+            ..default()
+        })
+        .insert(DeferredPrepass);
 }
 
 fn add_lightmaps_to_meshes(
```

<img width="1280" alt="image"
src="https://github.com/user-attachments/assets/17fd3367-61cc-4c23-b956-e7cfc751af3c">

## Emissive Issue
**The emissive light object appears incorrectly rendered because the
alpha channel of emission is set to 1 in deferred rendering and 0 in
forward rendering, leading to different emissive light result. Could
this be a bug?**

```wgsl
// pbr_deferred_functions.wgsl - pbr_input_from_deferred_gbuffer
let emissive = rgb9e5::rgb9e5_to_vec3_(gbuffer.g);
if ((pbr.material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) != 0u) {
    pbr.material.base_color = vec4(emissive, 1.0);
    pbr.material.emissive = vec4(vec3(0.0), 1.0);
} else {
    pbr.material.base_color = vec4(pow(base_rough.rgb, vec3(2.2)), 1.0);
    pbr.material.emissive = vec4(emissive, 1.0);
}

// pbr_functions.wgsl - apply_pbr_lighting
emissive_light = emissive_light * mix(1.0, view_bindings::view.exposure, emissive.a);
```

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2024-10-18 23:18:11 +00:00
Carter Anderson
015f2c69ca
Merge Style properties into Node. Use ComputedNode for computed properties. (#15975)
# Objective

Continue improving the user experience of our UI Node API in the
direction specified by [Bevy's Next Generation Scene / UI
System](https://github.com/bevyengine/bevy/discussions/14437)

## Solution

As specified in the document above, merge `Style` fields into `Node`,
and move "computed Node fields" into `ComputedNode` (I chose this name
over something like `ComputedNodeLayout` because it currently contains
more than just layout info. If we want to break this up / rename these
concepts, lets do that in a separate PR). `Style` has been removed.

This accomplishes a number of goals:

## Ergonomics wins

Specifying both `Node` and `Style` is now no longer required for
non-default styles

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

## Conceptual clarity

`Style` was never a comprehensive "style sheet". It only defined "core"
style properties that all `Nodes` shared. Any "styled property" that
couldn't fit that mold had to be in a separate component. A "real" style
system would style properties _across_ components (`Node`, `Button`,
etc). We have plans to build a true style system (see the doc linked
above).

By moving the `Style` fields to `Node`, we fully embrace `Node` as the
driving concept and remove the "style system" confusion.

## Next Steps

* Consider identifying and splitting out "style properties that aren't
core to Node". This should not happen for Bevy 0.15.

---

## Migration Guide

Move any fields set on `Style` into `Node` and replace all `Style`
component usage with `Node`.

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

For any usage of the "computed node properties" that used to live on
`Node`, use `ComputedNode` instead:

Before:
```rust
fn system(nodes: Query<&Node>) {
    for node in &nodes {
        let computed_size = node.size();
    }
}
```

After:
```rust
fn system(computed_nodes: Query<&ComputedNode>) {
    for computed_node in &computed_nodes {
        let computed_size = computed_node.size();
    }
}
```
2024-10-18 22:25:33 +00:00
VitalyR
eb19a9ea0b
Migrate UI bundles to required components (#15898)
# Objective

- Migrate UI bundles to required components, fixes #15889

## Solution

- deprecate `NodeBundle` in favor of `Node`
- deprecate `ImageBundle` in favor of `UiImage`
- deprecate `ButtonBundle` in favor of `Button`

## Testing

CI.

## Migration Guide

- Replace all uses of `NodeBundle` with `Node`. e.g.
```diff
     commands
-        .spawn(NodeBundle {
-            style: Style {
+        .spawn((
+            Node::default(),
+            Style {
                 width: Val::Percent(100.),
                 align_items: AlignItems::Center,
                 justify_content: JustifyContent::Center,
                 ..default()
             },
-            ..default()
-        })
+        ))
``` 
- Replace all uses of `ButtonBundle` with `Button`. e.g.
```diff
                     .spawn((
-                        ButtonBundle {
-                            style: Style {
-                                width: Val::Px(w),
-                                height: Val::Px(h),
-                                // horizontally center child text
-                                justify_content: JustifyContent::Center,
-                                // vertically center child text
-                                align_items: AlignItems::Center,
-                                margin: UiRect::all(Val::Px(20.0)),
-                                ..default()
-                            },
-                            image: image.clone().into(),
+                        Button,
+                        Style {
+                            width: Val::Px(w),
+                            height: Val::Px(h),
+                            // horizontally center child text
+                            justify_content: JustifyContent::Center,
+                            // vertically center child text
+                            align_items: AlignItems::Center,
+                            margin: UiRect::all(Val::Px(20.0)),
                             ..default()
                         },
+                        UiImage::from(image.clone()),
                         ImageScaleMode::Sliced(slicer.clone()),
                     ))
```
- Replace all uses of `ImageBundle` with `UiImage`. e.g.
```diff
-    commands.spawn(ImageBundle {
-        image: UiImage {
+    commands.spawn((
+        UiImage {
             texture: metering_mask,
             ..default()
         },
-        style: Style {
+        Style {
             width: Val::Percent(100.0),
             height: Val::Percent(100.0),
             ..default()
         },
-        ..default()
-    });
+    ));
 ```

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-17 21:11:02 +00:00
Clar Fon
683d6c90a9
Remove AVIF feature (#15973)
Resolves #15968. Since this feature never worked, and enabling it in the
`image` crate requires system dependencies, we've decided that it's best
to just remove it and let other plugin crates offer support for it as
needed.

## Migration Guide

AVIF images are no longer supported. They never really worked, and
require system dependencies (libdav1d) to work correctly, so, it's
better to simply offer this support via an unofficial plugin instead as
needed. The corresponding types have been removed from Bevy to account
for this.
2024-10-17 19:47:28 +00:00
Alice Cecile
2bd328220b
Improve API for scaling orthographic cameras (#15969)
# Objective

Fixes #15791.

As raised in #11022, scaling orthographic cameras is confusing! In Bevy
0.14, there were multiple completely redundant ways to do this, and no
clear guidance on which to use.

As a result, #15075 removed the `scale` field from
`OrthographicProjection` completely, solving the redundancy issue.

However, this resulted in an unintuitive API and a painful migration, as
discussed in #15791. Users simply want to change a single parameter to
zoom, rather than deal with the irrelevant details of how the camera is
being scaled.

## Solution

This PR reverts #15075, and takes an alternate, more nuanced approach to
the redundancy problem. `ScalingMode::WindowSize` was by far the biggest
offender. This was the default variant, and stored a float that was
*fully* redundant to setting `scale`.

All of the other variants contained meaningful semantic information and
had an intuitive scale. I could have made these unitless, storing an
aspect ratio, but this would have been a worse API and resulted in a
pointlessly painful migration.

In the course of this work I've also:

- improved the documentation to explain that you should just set `scale`
to zoom cameras
- swapped to named fields for all of the variants in `ScalingMode` for
more clarity about the parameter meanings
- substantially improved the `projection_zoom` example
- removed the footgunny `Mul` and `Div` impls for `ScalingMode`,
especially since these no longer have the intended effect on
`ScalingMode::WindowSize`.
- removed a rounding step because this is now redundant 🎉 

## Testing

I've tested these changes as part of my work in the `projection_zoom`
example, and things seem to work fine.

## Migration Guide

`ScalingMode` has been refactored for clarity, especially on how to zoom
orthographic cameras and their projections:

- `ScalingMode::WindowSize` no longer stores a float, and acts as if its
value was 1. Divide your camera's scale by any previous value to achieve
identical results.
- `ScalingMode::FixedVertical` and `FixedHorizontal` now use named
fields.

---------

Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
2024-10-17 17:50:06 +00:00
Lynn
b4e04f9d9f
Remove write access to ConvexPolygon.vertices (#15965)
# Objective

- Fixes #15963

## Solution

- Implement `TryFrom<Polygon<N> for ConvexPolygon<N>`
- Implement `From<ConvexPolygon<N>> for Polygon<N>`
- Remove `pub` from `vertices`
- Add `ConvexPolygon::vertices()` to get read only access to the
vertices of a convex polygon.
2024-10-16 22:21:01 +00:00
Alice Cecile
76744bf58c
Mark ghost nodes as experimental and partially feature flag them (#15961)
# Objective

As discussed in #15341, ghost nodes are a contentious and experimental
feature. In the interest of enabling ecosystem experimentation, we've
decided to keep them in Bevy 0.15.

That said, we don't use them internally, and don't expect third-party
crates to support them. If the experimentation returns a negative result
(they aren't very useful, an alternative design is preferred etc) they
will be removed.

We should clearly communicate this status to users, and make sure that
users don't use ghost nodes in their projects without a very clear
understanding of what they're getting themselves into.

## Solution

To make life easy for users (and Bevy), `GhostNode` and all associated
helpers remain public and are always available.

However, actually constructing these requires enabling a feature flag
that's clearly marked as experimental. To do so, I've added a
meaningless private field.

When the feature flag is enabled, our constructs (`new` and `default`)
can be used. I've added a `new` constructor, which should be preferred
over `Default::default` as that can be readily deprecated, allowing us
to prompt users to swap over to the much nicer `GhostNode` syntax once
this is a unit struct again.

Full credit: this was mostly @cart's design: I'm just implementing it!

## Testing

I've run the ghost_nodes example and it fails to compile without the
feature flag. With the feature flag, it works fine :)

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-10-16 22:20:48 +00:00
Tim
f4d9c52c0d
Add read-only access to PointerInteraction (#15964)
# Objective
Re-add missing read-only access to `PointerInteraction`. This was missed
when bevy_mod_picking was upstreamed.
See
[here](https://docs.rs/bevy_mod_picking/latest/bevy_mod_picking/pointer/struct.PointerInteraction.html).
2024-10-16 21:21:19 +00:00
andristarr
7482a0d26d
aligning public apis of Time,Timer and Stopwatch (#15962)
Fixes #15834

## Migration Guide

The APIs of `Time`, `Timer` and `Stopwatch` have been cleaned up for
consistency with each other and the standard library's `Duration` type.
The following methods have been renamed:

- `Stowatch::paused` -> `Stopwatch::is_paused`
- `Time::elapsed_seconds` -> `Time::elasped_secs` (including `_f64` and
`_wrapped` variants)
2024-10-16 21:09:32 +00:00
François Mockers
7495d68b41
UI materials: don't reserve in loop when enough capacity (#15919)
# Objective

- UI materials reserve too much capacity in a vec: for every node in the
transparent phase, it reserves enough memory to store all the nodes
- Update #10437 

## Solution

- Only reserve extra memory if there's not enough
- Only reserve the needed memory, not more
2024-10-16 17:59:30 +00:00
ickshonpe
fc659a6143
Default UI shadow samples fix (#15953)
# Objective

In `queue_shadows`, the `UiBoxShadows` option is unwrapped incorrectly
which results in the number of shadow samples being set to
`u32::default()` instead of `UiBoxShadows::default()` if the camera
entity doesn't have the component.

## Solution

Just use `unwrap_or_default` directly without `map`.
2024-10-16 17:01:10 +00:00
ickshonpe
396aff906e
Remove bevy_ui's "bevy_text" feature (#15951)
# Objective

Remove `bevy-ui`'s non-functional "bevy_text" feature.

Fixes #15900

## Solution

Remove all the "bevy_text" cfg gates.

I tried to fix it at first but couldn't figure it out. I'll happily
withdraw this in favour of another PR that gets the feature gate
working.
2024-10-16 16:43:57 +00:00
poopy
40b9a0ae52
register TextFont and TextColor in app type registry (#15950)
# Objective

`TextFont` and `TextColor` is not registered in the app type registry
and serializing a scene with a a `Text2d` doesn't save the color and
font of the text entity.

## Solution

register `TextFont`  and `TextColor`  in the type registry
2024-10-16 15:49:43 +00:00
ickshonpe
6d3965f520
Overflow clip margin (#15561)
# Objective

Limited implementation of the CSS property `overflow-clip-margin`
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-margin

Allows you to control the visible area for clipped content when using
overfllow-clip, -hidden, or -scroll and expand it with a margin.

Based on #15442

Fixes #15468

## Solution

Adds a new field to Style: `overflow_clip_margin: OverflowClipMargin`.
The field is ignored unless overflow-clip, -hidden or -scroll is set on
at least one axis.

`OverflowClipMargin` has these associated constructor functions:
```
pub const fn content_box() -> Self;
pub const fn padding_box() -> Self;
pub const fn border_box() -> Self;
```
You can also use the method `with_margin` to increases the size of the
visible area:
```
commands
  .spawn(NodeBundle {
      style: Style {
          width: Val::Px(100.),
          height: Val::Px(100.),
          padding: UiRect::all(Val::Px(20.)),
          border: UiRect::all(Val::Px(5.)),
          overflow: Overflow::clip(),
          overflow_clip_margin: OverflowClipMargin::border_box().with_margin(25.),
          ..Default::default()
      },
      border_color: Color::BLACK.into(),
      background_color: GRAY.into(),
      ..Default::default()
  })
```
`with_margin` expects a length in logical pixels, negative values are
clamped to zero.

## Notes
* To keep this PR as simple as possible I omitted responsive margin
values support. This could be added in a follow up if we want it.
* CSS also supports a `margin-box` option but we don't have access to
the margin values in `Node` so it's probably not feasible to implement
atm.

## Testing

```cargo run --example overflow_clip_margin```

<img width="396" alt="overflow-clip-margin" src="https://github.com/user-attachments/assets/07b51cd6-a565-4451-87a0-fa079429b04b">

## Migration Guide

Style has a new field `OverflowClipMargin`.  It allows users to set the visible area for clipped content when using overflow-clip, -hidden, or -scroll and expand it with a margin.

There are three associated constructor functions `content_box`, `padding_box` and `border_box`:
* `content_box`: elements painted outside of the content box area (the innermost part of the node excluding the padding and border) of the node are clipped. This is the new default behaviour.
* `padding_box`: elements painted outside outside of the padding area of the node are clipped. 
* `border_box`:  elements painted outside of the bounds of the node are clipped. This matches the behaviour from Bevy 0.14.

There is also a `with_margin` method that increases the size of the visible area by the given number in logical pixels, negative margin values are clamped to zero.

`OverflowClipMargin` is ignored unless overflow-clip, -hidden or -scroll is also set on at least one axis of the UI node.

---------

Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-16 13:17:49 +00:00
mgi388
87c33da139
Fix typos from greyscale -> grayscale (#15947)
# Objective

I was grepping for "grayscale" and thought I'd fix these while I'm here
so I don't need to look for both forms.

## Solution

From [wikipedia]:

> In [digital
photography](https://en.wikipedia.org/wiki/Digital_photography),
[computer-generated
imagery](https://en.wikipedia.org/wiki/Computer-generated_imagery), and
[colorimetry](https://en.wikipedia.org/wiki/Colorimetry), a greyscale
(more common in [Commonwealth
English](https://en.wikipedia.org/wiki/Commonwealth_English)) or
grayscale (more common in [American
English](https://en.wikipedia.org/wiki/American_English))

[wikipedia]: https://en.wikipedia.org/wiki/Grayscale
2024-10-16 12:30:23 +00:00
andriyDev
b109787764
Delete ImageLoader::COUNT in favour of ImageLoader::SUPPORTED_FORMATS.len(). (#15939)
# Objective

- This is a followup to #15812.

## Solution

I just deleted the `COUNT` const and replaced it. I didn't realize for
loops are not const yet, so improving the other const variables is not
obvious.

Note: `slice::len` has been const since Rust 1.39, so we're not relying
on a brand new feature or anything.

## Testing

- It builds!
2024-10-16 00:50:50 +00:00
andriyDev
fbb53140e9
Fix bevy_color not compiling standalone. (#15938)
# Objective

On HEAD, `bevy_color` does not compile on its own with `--all-features`
enabled. This PR fixes that.

## Solution

- Added the `curve` feature on `bevy_math` to `bevy_color`.
- Added the `serialize` feature on `bevy_math` to
`bevy_color/serialize`.

## Testing

- Compiled with `cargo b -p bevy_color --all-features` on HEAD and on
this PR: it fails to compile on HEAD but compiles with this PR.
2024-10-15 23:52:45 +00:00
akimakinai
c78886e649
Remove ExtractComponent::Out (#15926)
# Objective

- `C: ExtractComponent` inserts `C::Out` instead of `C`, so we need to
remove `C::Out`. cc #15904.

## Solution

- `C` -> `C::Out`

## Testing

- CAS has `<ContrastAdaptiveSharpening as ExtractComponent>::Out =
(DenoiseCas, CasUniform)`. Setting its strength to zero correctly
removes the effect after this change.
2024-10-15 23:42:35 +00:00
Tau Gärtli
ed351294ec
Use #[doc(fake_variadic)] on StableInterpolate (#15933)
This is a follow-up to #15931 that adds `#[doc(fake_variadic)]` for
improved docs output :)
2024-10-15 23:40:42 +00:00
Shane Celis
5157fef84b
Add window drag move and drag resize without decoration example. (#15814)
# Objective

Add an example for the new drag move and drag resize introduced by PR
#15674 and fix #15734.

## Solution

I created an example that allows the user to exercise drag move and drag
resize separately. The user can also choose what direction the resize
works in.

![Screenshot 2024-10-10 at 4 06
43 AM](https://github.com/user-attachments/assets/1da558ab-a80f-49af-8b7d-bb635b0f038f)

### Name

The example is called `window_drag_move`. Happy to have that
bikeshedded.

### Contentious Refactor?

This PR removed the `ResizeDirection` enumeration in favor of using
`CompassOctant` which had the same variants. Perhaps this is
contentious.

### Unsafe?

In PR #15674 I mentioned that `start_drag_move()` and
`start_drag_resize()`'s requirement to only be called in the presence of
a left-click looks like a compiler-unenforceable contract that can cause
intermittent panics when not observed, so perhaps the functions should
be marked them unsafe. **I have not made that change** here since I
didn't see a clear consensus on that.

## Testing

I exercised this on x86 macOS. However, winit for macOS does not support
drag resize. It reports a good error when `start_drag_resize()` is
called. I'd like to see it tested on Windows and Linux.

---

## Showcase

Example window_drag_move shows how to drag or resize a window without
decoration.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-15 23:38:35 +00:00
Matty
a09104b62c
Infer StableInterpolate on tuples (#15931)
# Objective

Make `StableInterpolate` "just work" on tuples whose parts are each
`StableInterpolate` types. These types arise notably through
`Curve::zip` (or just through explicit mapping of a similar form). It
would otherwise be kind of frustrating to stumble upon such a thing and
then realize that, e.g., automatic resampling just doesn't work, even
though there is a very "obvious" way to do it.

## Solution

Infer `StableInterpolate` on tuples of up to size 11. I can make that
number bigger, if desired. Unfortunately, I don't think that our
standard "fake variadics" tools actually work for this; the anonymous
field accessors of tuples are `:tt` for purposes of macro expansion,
which means that you can't simplify away the identifiers by doing
something clever like using recursion (which would work if they were
`:expr`). Maybe someone who knows some incredibly dark magic could chime
in with a better solution.

The expanded impls look like this:
```rust
impl<
        T0: StableInterpolate,
        T1: StableInterpolate,
        T2: StableInterpolate,
        T3: StableInterpolate,
        T4: StableInterpolate,
    > StableInterpolate for (T0, T1, T2, T3, T4)
{
    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
        (
            <T0 as StableInterpolate>::interpolate_stable(&self.0, &other.0, t),
            <T1 as StableInterpolate>::interpolate_stable(&self.1, &other.1, t),
            <T2 as StableInterpolate>::interpolate_stable(&self.2, &other.2, t),
            <T3 as StableInterpolate>::interpolate_stable(&self.3, &other.3, t),
            <T4 as StableInterpolate>::interpolate_stable(&self.4, &other.4, t),
        )
    }
}
```

## Testing

Expanded macros; it compiles.

## Future

Make a version of the fake variadics workflow that supports this kind of
thing.
2024-10-15 19:55:36 +00:00
Joona Aalto
c1a4b82762
Revert default mesh materials (#15930)
# Objective

Closes #15799.

Many rendering people and maintainers are in favor of reverting default
mesh materials added in #15524, especially as the migration to required
component is already large and heavily breaking.

## Solution

Revert default mesh materials, and adjust docs accordingly.

- Remove `extract_default_materials`
- Remove `clear_material_instances`, and move the logic back into
`extract_mesh_materials`
- Remove `HasMaterial2d` and `HasMaterial3d`
- Change default material handles back to pink instead of white
- 2D uses `Color::srgb(1.0, 0.0, 1.0)`, while 3D uses `Color::srgb(1.0,
0.0, 0.5)`. Not sure if this is intended.

There is now no indication at all about missing materials for `Mesh2d`
and `Mesh3d`. Having a mesh without a material renders nothing.

## Testing

I ran `2d_shapes`, `mesh2d_manual`, and `3d_shapes`, with and without
mesh material components.
2024-10-15 19:47:40 +00:00
andriyDev
15440c189b
Move SUPPORTED_FILE_EXTENSIONS to ImageLoader and remove unsupported formats. (#15917)
# Objective

Fixes #15730.

## Solution

As part of #15586, we made a constant to store all the supported image
formats. However since the `ImageFormat` does actually include Hdr and
OpenExr, it also included the `"hdr"` and `"exr"` file extensions. These
are supported by separate loaders though: `HdrTextureLoader` and
`ExrTextureLoader`. This led to a warning about duplicate asset loaders.

Therefore, instead of having the constant for `ImageFormat`, I made the
constant just for `ImageLoader`. This lets us correctly remove `"hdr"`
and `"exr"` from the image formats supported by `ImageLoader`, returning
us to having a single asset loader for every image format.

Note: we could have just removed `hdr` and `exr` from
`ImageFormat::SUPPORTED_FILE_EXTENSIONS`, but this would be very
confusing. Then the list of `ImageFormat`s would not match the list of
supported formats!

## Testing

- I ran the `sprite` example and got no warning! I also replaced the
sprite in that example with an HDR file and everything worked as
expected.
2024-10-15 18:06:34 +00:00
François Mockers
812e599f77
don't clip text that is rotated (#15925)
# Objective

- Fixes #15922 , #15853 
- Don't clip text that is rotated by some angles

## Solution

- Compare to the absolute size before clipping
2024-10-15 15:21:28 +00:00
Lucas
af93e78b72
Fix overflow panic on Stopwatch at Duration::MAX (#15927)
See #15924 for more details
close #15924

from the issue, this code panic:
```rust
use bevy::time::Stopwatch;
use std::time::Duration;

fn main() {
    let second = Duration::from_secs(1);

    let mut stopwatch = Stopwatch::new();
    // lot of time has passed... or a timer with Duration::MAX that was artificially set has "finished":
    // timer.set_elapsed(timer.remaining());
    stopwatch.set_elapsed(Duration::MAX);
    // panic
    stopwatch.tick(second);

    let mut stopwatch = Stopwatch::new();
    stopwatch.set_elapsed(Duration::MAX - second);
    // this doesnt panic as its still one off the max
    stopwatch.tick(second);
    // this panic
    stopwatch.tick(second);
}
```

with this PR changes, the code now doesn't panic.

have a good day !
2024-10-15 14:14:44 +00:00
Brett Striker
de08fb2afa
[bevy_ui/layout] Add tests, missing asserts, and missing debug fields for UiSurface (#12803)
This is 3 of 5 iterative PR's that affect bevy_ui/layout

- [x] Blocked by https://github.com/bevyengine/bevy/pull/12801
- [x] Blocked by https://github.com/bevyengine/bevy/pull/12802

---

# Objective

- Add tests to `UiSurface`
- Add missing asserts in `_assert_send_sync_ui_surface_impl_safe`
- Add missing Debug field print for `camera_entity_to_taffy`

## Solution

- Adds tests to `UiSurface`
- Adds missing asserts in `_assert_send_sync_ui_surface_impl_safe`
- Adds missing impl Debug field print for `camera_entity_to_taffy`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-15 14:06:17 +00:00
akimakinai
4ac528a579
Despawn unused light-view entity (#15902)
# Objective

- Fixes #15897

## Solution

- Despawn light view entities when they go unused or when the
corresponding view is not alive.

## Testing

- `scene_viewer` example no longer prints "The preprocessing index
buffer wasn't present" warning
- modified an example to try toggling shadows for all kinds of light:
https://gist.github.com/akimakinai/ddb0357191f5052b654370699d2314cf
2024-10-15 13:54:09 +00:00
charlotte
acbed6040e
Attempt to remove component from render world if not extracted. (#15904)
# Objective

Ensure that components that are conditionally extracted do not linger in
the render world when not extracted from the main world.

## Solution

If the `ExtractComponent` returns `None`, we'll remove the render world
component. I think this is the most sensible behavior here. In the
future if there really is a use case for keeping the previous render
component around, we could add a `Option<Self::Out>` parameter for the
previous render component to the method, or something similar. I think
that this follows the principle of least surprise here relative to what
`None` would suggest and the way that render nodes are typically
written. The alternative would be to add an `enabled` field to pretty
much every camera settings component, or duplicate the extraction
condition as #15856 does.

## Testing

`transmission` no longer crashes.

## Migration Guide

Components that implement `ExtractComponent` and return `None` will
cause the extracted component to be removed from the render world.
2024-10-15 04:21:53 +00:00
Zachary Harrold
c1bb4b255d
[Adopted] Add a method for asynchronously waiting for an asset to load (#15913)
# Objective

Currently, is is very painful to wait for an asset to load from the
context of an `async` task. While bevy's `AssetServer` is asynchronous
at its core, the public API is mainly focused on being used from
synchronous contexts such as bevy systems. Currently, the best way of
waiting for an asset handle to finish loading is to have a system that
runs every frame, and either listens for `AssetEvents` or manually polls
the asset server. While this is an acceptable interface for bevy
systems, it is extremely awkward to do this in a way that integrates
well with the `async` task system. At my work we had to create our own
(inefficient) abstraction that encapsulated the boilerplate of checking
an asset's load status and waking up a task when it's done.

## Solution

Add the method `AssetServer::wait_for_asset`, which returns a future
that suspends until the asset associated with a given `Handle` either
finishes loading or fails to load.

## Testing

- CI

## Notes

This is an adoption of #14431, the above description is directly from
that original PR.

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: andriyDev <andriydzikh@gmail.com>
2024-10-15 02:50:33 +00:00
Benjamin Brienen
63a3a987c6
Fix detailed_trace module scope (#15912)
# Objective

Fixes #15615

## Solution

`$crate` is a cool keyword metavariable

## Testing

Created a test crate and used the macro

## Showcase

![image](https://github.com/user-attachments/assets/f0567224-126d-44e4-8905-26103da4ba14)
2024-10-15 02:48:36 +00:00
Matty
8a655e4d27
Add module-level docs for Curve (#15905)
# Objective

Improve the average user's ability to understand what the heck is going
on with the Curve API.

## Solution

I wrote some docs. I doubt these are perfect; I'm probably far too close
to this for that to be the case. :)
2024-10-15 02:45:45 +00:00
MiniaczQ
f602edad09
Text Rework cleanup (#15887)
# Objective

Cleanup naming and docs, add missing migration guide after #15591 

All text root nodes now use `Text` (UI) / `Text2d`.
All text readers/writers use `Text<Type>Reader`/`Text<Type>Writer`
convention.

---

## Migration Guide

Doubles as #15591 migration guide.

Text bundles (`TextBundle` and `Text2dBundle`) were removed in favor of
`Text` and `Text2d`.
Shared configuration fields were replaced with `TextLayout`, `TextFont`
and `TextColor` components.
Just `TextBundle`'s additional field turned into `TextNodeFlags`
component,
while `Text2dBundle`'s additional fields turned into `TextBounds` and
`Anchor` components.

Text sections were removed in favor of hierarchy-based approach.
For root text entities with `Text` or `Text2d` components, child
entities with `TextSpan` will act as additional text sections.
To still access text spans by index, use the new `TextUiReader`,
`Text2dReader` and `TextUiWriter`, `Text2dWriter` system parameters.
2024-10-15 02:32:34 +00:00
andriyDev
73f7fd0c12
Move ImageLoader and CompressedImageSaver to bevy_image. (#15812)
# Objective

This is a follow-up to #15650. While the core `Image` stuff moved from
`bevy_render` to `bevy_image`, the `ImageLoader` and the
`CompressedImageSaver` remained in `bevy_render`.

## Solution

I moved `ImageLoader` and `CompressedImageSaver` to `bevy_image` and
re-exported everything out from `bevy_render`. The second step isn't
strictly necessary, but `bevy_render` is already doing this for all the
other `bevy_image` types, so I kept it the same for consistency.

Unfortunately I had to give `ImageLoader` a constructor so I can keep
the `RenderDevice` stuff in `bevy_render`.

## Testing

It compiles!

## Migration Guide

- `ImageLoader` can no longer be initialized directly through
`init_asset_loader`. Now you must use
`app.register_asset_loader(ImageLoader::new(supported_compressed_formats))`
(check out the implementation of `bevy_render::ImagePlugin`). This only
affects you if you are initializing the loader manually and does not
affect users of `bevy_render::ImagePlugin`.

## Followup work

- We should be able to move most of the `ImagePlugin` to `bevy_image`.
This would likely require an `ImagePlugin` and a `RenderImagePlugin` or
something though.
2024-10-15 02:18:10 +00:00
Christian Hughes
345f935b1a
Add Trigger::components, which lists the component targets that were triggered (#15811)
# Objective

- Closes #14774 

## Solution

Added:

```rust
impl<'w, E, B: Bundle> Trigger<'w, E, B> {
    pub fn components(&self) -> &[ComponentId];
}
```

I went with storing it in the trigger as a `SmallVec<[Component; 1]>`
because a singular target component will be the most common case, and it
remains the same size as `Vec<ComponentId>`.

## Testing

Added a test.
2024-10-15 02:17:03 +00:00
Torstein Grindvik
9f5f5d3d41
bevy_reflect: get_represented_kind_info APIs for reflected kinds (#14380)
# Objective

Fixes #14378

---------

Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-15 02:08:31 +00:00
ickshonpe
b78a060af2
Clip to the UI node's content box (#15442)
# Objective

Change UI clipping to respect borders and padding.

Fixes #15335

## Solution

Based on #15163

1. Add a `padding` field to `Node`.
2. In `ui_layout_size` copy the padding values from taffy to
`Node::padding`.
4. Determine the node's content box (The innermost part of the node
excluding the padding and border).
5. In `update_clipping` perform the clipping intersection with the
node's content box.

## Notes

* `Rect` probably needs some helper methods for working with insets but
because `Rect` and `BorderRect` are in different crates it's awkward to
add them. Left for a follow up.
* We could have another `Overflow` variant (probably called
`Overflow::Hidden`) to that clips inside of the border box instead of
the content box. Left it out here as I'm not certain about the naming or
behaviour though. If this PR is adopted, it would be trivial to add a
`Hidden` variant in a follow up.
* Depending on UI scaling there are sometimes gaps in the layout:
<img width="532" alt="rounding-bug"
src="https://github.com/user-attachments/assets/cc29aa0d-44fe-403f-8f0e-cd28a8b1d1b3">
This is caused by existing bugs in `ui_layout_system`'s coordinates
rounding and not anything to do with the changes in this PR.

## Testing

This PR also changes the `overflow` example to display borders on the
overflow nodes so you can see how this works:

#### main (The image is clipped at the edges of the node, overwriting
the border).
<img width="722" alt="main_overflow"
src="https://github.com/user-attachments/assets/eb316cd0-fff8-46ee-b481-e0cd6bab3f5c">

#### this PR  (The image is clipped at the edges of the node's border).
<img width="711" alt="content-box-clip"
src="https://github.com/user-attachments/assets/fb302e56-9302-47b9-9a29-ec3e15fe9a9f">

## Migration Guide

Migration guide is on #15561

---------

Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-15 02:05:08 +00:00
Clar Fon
e79bc7811d
Fix *most* clippy lints (#15906)
# Objective

Another clippy-lint fix: the goal is so that `ci lints` actually
displays the problems that a contributor caused, and not a bunch of
existing stuff in the repo. (when run on nightly)

## Solution

This fixes all but the `clippy::needless_lifetimes` lint, which will
result in substantially more fixes and be in other PR(s). I also
explicitly allow `non_local_definitions` since it is [not working
correctly, but will be
fixed](https://github.com/rust-lang/rust/issues/131643).

A few things were manually fixed: for example, some places had an
explicitly defined `div_ceil` function that was used, which is no longer
needed since this function is stable on unsigned integers. Also, empty
lines in doc comments were handled individually.

## Testing

I ran `cargo clippy --workspace --all-targets --all-features --fix
--allow-staged` with the `clippy::needless_lifetimes` lint marked as
`allow` in `Cargo.toml` to avoid fixing that too. It now passes with all
but the listed lint.
2024-10-14 20:52:35 +00:00
François Mockers
89e19aaff0
force last update after setting state to Suspended (#15888)
# Objective

- Android doesn't receive lifecycle event `Suspended` before suspension

## Solution

- Fix update triggering just after state change on android

## Testing

- Tested on the android emulator
2024-10-14 01:40:03 +00:00
Benjamin Brienen
93fc2d12cf
Remove incorrect equality comparisons for asset load error types (#15890)
# Objective

The type `AssetLoadError` has `PartialEq` and `Eq` impls, which is
problematic due to the fact that the `AssetLoaderError` and
`AddAsyncError` variants lie in their impls: they will return `true` for
any `Box<dyn Error>` with the same `TypeId`, even if the actual value is
different. This can lead to subtle bugs if a user relies on the equality
comparison to ensure that two values are equal.

The same is true for `DependencyLoadState`,
`RecursiveDependencyLoadState`.

More generally, it is an anti-pattern for large error types involving
dynamic dispatch, such as `AssetLoadError`, to have equality
comparisons. Directly comparing two errors for equality is usually not
desired -- if some logic needs to branch based on the value of an error,
it is usually more correct to check for specific variants and inspect
their fields.

As far as I can tell, the only reason these errors have equality
comparisons is because the `LoadState` enum wraps `AssetLoadError` for
its `Failed` variant. This equality comparison is only used to check for
`== LoadState::Loaded`, which we can easily replace with an `is_loaded`
method.

## Solution

Remove the `{Partial}Eq` impls from `LoadState`, which also allows us to
remove it from the error types.

## Migration Guide

The types `bevy_asset::AssetLoadError` and `bevy_asset::LoadState` no
longer support equality comparisons. If you need to check for an asset's
load state, consider checking for a specific variant using
`LoadState::is_loaded` or the `matches!` macro. Similarly, consider
using the `matches!` macro to check for specific variants of the
`AssetLoadError` type if you need to inspect the value of an asset load
error in your code.

`DependencyLoadState` and `RecursiveDependencyLoadState` are not
released yet, so no migration needed,

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
2024-10-14 01:00:45 +00:00
Alice Cecile
a7e9330af9
Implement WorldQuery for MainWorld and RenderWorld components (#15745)
# Objective

#15320 is a particularly painful breaking change, and the new
`RenderEntity` in particular is very noisy, with a lot of `let entity =
entity.id()` spam.

## Solution

Implement `WorldQuery`, `QueryData` and `ReadOnlyQueryData` for
`RenderEntity` and `WorldEntity`.

These work the same as the `Entity` impls from a user-facing
perspective: they simply return an owned (copied) `Entity` identifier.
This dramatically reduces noise and eases migration.

Under the hood, these impls defer to the implementations for `&T` for
everything other than the "call .id() for the user" bit, as they involve
read-only access to component data. Doing it this way (as opposed to
implementing a custom fetch, as tried in the first commit) dramatically
reduces the maintenance risk of complex unsafe code outside of
`bevy_ecs`.

To make this easier (and encourage users to do this themselves!), I've
made `ReadFetch` and `WriteFetch` slightly more public: they're no
longer `doc(hidden)`. This is a good change, since trying to vendor the
logic is much worse than just deferring to the existing tested impls.

## Testing

I've run a handful of rendering examples (breakout, alien_cake_addict,
auto_exposure, fog_volumes, box_shadow) and nothing broke.

## Follow-up

We should lint for the uses of `&RenderEntity` and `&MainEntity` in
queries: this is just less nice for no reason.

---------

Co-authored-by: Trashtalk217 <trashtalk217@gmail.com>
2024-10-13 20:58:46 +00:00
Pablo Reinhardt
d96a9d15f6
Migrate from Query::single and friends to Single (#15872)
# Objective

- closes #15866

## Solution

- Simply migrate where possible.

## Testing

- Expect that CI will do most of the work. Examples is another way of
testing this, as most of the work is in that area.
---

## Notes
For now, this PR doesn't migrate `QueryState::single` and friends as for
now, this look like another issue. So for example, QueryBuilders that
used single or `World::query` that used single wasn't migrated. If there
is a easy way to migrate those, please let me know.

Most of the uses of `Query::single` were removed, the only other uses
that I found was related to tests of said methods, so will probably be
removed when we remove `Query::single`.
2024-10-13 20:32:06 +00:00
JaySpruce
3d6b24880e
Add insert_batch and variations (#15702)
# Objective

`insert_or_spawn_batch` exists, but a version for just inserting doesn't
- Closes #2693 
- Closes #8384 
- Adopts/supersedes #8600 

## Solution

Add `insert_batch`, along with the most common `insert` variations:
- `World::insert_batch`
- `World::insert_batch_if_new`
- `World::try_insert_batch`
- `World::try_insert_batch_if_new`
- `Commands::insert_batch`
- `Commands::insert_batch_if_new`
- `Commands::try_insert_batch`
- `Commands::try_insert_batch_if_new`

## Testing

Added tests, and added a benchmark for `insert_batch`.
Performance is slightly better than `insert_or_spawn_batch` when only
inserting:


![Code_HPnUN0QeWe](https://github.com/user-attachments/assets/53091e4f-6518-43f4-a63f-ae57d5470c66)

<details>
<summary>old benchmark</summary>

This was before reworking it to remove the `UnsafeWorldCell`:


![Code_QhXJb8sjlJ](https://github.com/user-attachments/assets/1061e2a7-a521-48e1-a799-1b6b8d1c0b93)
</details>

---

## Showcase

Usage is the same as `insert_or_spawn_batch`:
```
use bevy_ecs::{entity::Entity, world::World, component::Component};
#[derive(Component)]
struct A(&'static str);
#[derive(Component, PartialEq, Debug)]
struct B(f32);

let mut world = World::new();
let entity_a = world.spawn_empty().id();
let entity_b = world.spawn_empty().id();
world.insert_batch([
    (entity_a, (A("a"), B(0.0))),
    (entity_b, (A("b"), B(1.0))),
]);

assert_eq!(world.get::<B>(entity_a), Some(&B(0.0)));

```
2024-10-13 18:14:16 +00:00
NiseVoid
bdd0af6bfb
Deprecate SpatialBundle (#15830)
# Objective

- Required components replace bundles, but `SpatialBundle` is yet to be
deprecated

## Solution

- Deprecate `SpatialBundle`
- Insert `Transform` and `Visibility` instead in examples using it
- In `spawn` or `insert` inserting a default `Transform` or `Visibility`
with component already requiring either, remove those components from
the tuple

## Testing

- Did you test these changes? If so, how?
Yes, I ran the examples I changed and tests
- Are there any parts that need more testing?
The `gamepad_viewer` and and `custom_shader_instancing` examples don't
work as intended due to entirely unrelated code, didn't check main.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Run examples, or just check that all spawned values are identical
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Linux, wayland trough x11 (cause that's the default feature)

---

## Migration Guide

`SpatialBundle` is now deprecated, insert `Transform` and `Visibility`
instead which will automatically insert all other components that were
in the bundle. If you do not specify these values and any other
components in your `spawn`/`insert` call already requires either of
these components you can leave that one out.

before:
```rust
commands.spawn(SpatialBundle::default());
```

after:
```rust
commands.spawn((Transform::default(), Visibility::default());
```
2024-10-13 17:28:22 +00:00
Benjamin Brienen
0720e62f74
Time<Real> documentation improvement (#15874)
# Objective

Fixes #15445

## Solution

Add a note to the doc comment for `Real`.

## Testing

Viewed the built documentation.


## Showcase


![image](https://github.com/user-attachments/assets/815b8655-c632-4c92-b64e-28c06959c38b)
[*possible bug in rustdoc rendering the
footnote](https://github.com/rust-lang/rust/issues/131631)
2024-10-13 17:26:40 +00:00
Benjamin Brienen
37501e1c21
spirv_shader_passthrough must enable wgpu/spirv (#15873)
# Objective

Fixes #15515

## Solution

I went for the simplest solution because "format" in
`shader_format_spirv` didn't sound directly related.

## Testing

The command `cargo b -p bevy --no-default-features -F
spirv_shader_passthrough,x11` failed before, but works now.
2024-10-13 17:25:27 +00:00
Viktor Gustavsson
5989a845f0
Filter UI traversal to only Node and GhostNode (#15746)
# Objective

With the warning removed in
https://github.com/bevyengine/bevy/pull/15736, the rules for the UI tree
changes.
We no longer need to traverse non `Node`/`GhostNode` entities.

## Solution

- Added a filter `Or<(With<Node>, With<GhostNode>)>` to the child
traversal query so we don't unnecessarily traverse nodes that are not
part of the UI tree (like text nodes).
- Also moved the warning for NoUI->UI entities so it is actually
triggered (see comments)

## Testing

- Ran unit tests (still passing)
- Ran the ghost_nodes and ui examples, still works and looks fine 👍 
- Tested the warning by spawning a Node under an empty entity.

---

---------

Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-13 17:25:15 +00:00
Joona Aalto
0e30b68b20
Add mesh picking backend and MeshRayCast system parameter (#15800)
# Objective

Closes #15545.

`bevy_picking` supports UI and sprite picking, but not mesh picking.
Being able to pick meshes would be extremely useful for various games,
tools, and our own examples, as well as scene editors and inspectors.
So, we need a mesh picking backend!

Luckily,
[`bevy_mod_picking`](https://github.com/aevyrie/bevy_mod_picking) (which
`bevy_picking` is based on) by @aevyrie already has a [backend for
it](74f0c3c0fb/backends/bevy_picking_raycast/src/lib.rs)
using [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast).
As a side product of adding mesh picking, we also get support for
performing ray casts on meshes!

## Solution

Upstream a large chunk of the immediate-mode ray casting functionality
from `bevy_mod_raycast`, and add a mesh picking backend based on
`bevy_mod_picking`. Huge thanks to @aevyrie who did all the hard work on
these incredible crates!

All meshes are pickable by default. Picking can be disabled for
individual entities by adding `PickingBehavior::IGNORE`, like normal.
Or, if you want mesh picking to be entirely opt-in, you can set
`MeshPickingBackendSettings::require_markers` to `true` and add a
`RayCastPickable` component to the desired camera and target entities.

You can also use the new `MeshRayCast` system parameter to cast rays
into the world manually:

```rust
fn ray_cast_system(mut ray_cast: MeshRayCast, foo_query: Query<(), With<Foo>>) {
    let ray = Ray3d::new(Vec3::ZERO, Dir3::X);

    // Only ray cast against entities with the `Foo` component.
    let filter = |entity| foo_query.contains(entity);

    // Never early-exit. Note that you can change behavior per-entity.
    let early_exit_test = |_entity| false;

    // Ignore the visibility of entities. This allows ray casting hidden entities.
    let visibility = RayCastVisibility::Any;

    let settings = RayCastSettings::default()
        .with_filter(&filter)
        .with_early_exit_test(&early_exit_test)
        .with_visibility(visibility);

    // Cast the ray with the settings, returning a list of intersections.
    let hits = ray_cast.cast_ray(ray, &settings);
}
```

This is largely a direct port, but I did make several changes to match
our APIs better, remove things we don't need or that I think are
unnecessary, and do some general improvements to code quality and
documentation.

### Changes Relative to `bevy_mod_raycast` and `bevy_mod_picking`

- Every `Raycast` and "raycast" has been renamed to `RayCast` and "ray
cast" (similar reasoning as the "Naming" section in #15724)
- `Raycast` system param has been renamed to `MeshRayCast` to avoid
naming conflicts and to be explicit that it is not for colliders
- `RaycastBackend` has been renamed to `MeshPickingBackend`
- `RayCastVisibility` variants are now `Any`, `Visible`, and
`VisibleInView` instead of `Ignore`, `MustBeVisible`, and
`MustBeVisibleAndInView`
- `NoBackfaceCulling` has been renamed to `RayCastBackfaces`, to avoid
implying that it affects the rendering of backfaces for meshes (it
doesn't)
- `SimplifiedMesh` and `RayCastBackfaces` live near other ray casting
API types, not in their own 10 LoC module
- All intersection logic and types are in the same `intersections`
module, not split across several modules
- Some intersection types have been renamed to be clearer and more
consistent
	- `IntersectionData` -> `RayMeshHit` 
	- `RayHit` -> `RayTriangleHit`
- General documentation and code quality improvements

### Removed / Not Ported

- Removed unused ray helpers and types, like `PrimitiveIntersection`
- Removed getters on intersection types, and made their properties
public
- There is no `2d` feature, and `Raycast::mesh_query` and
`Raycast::mesh2d_query` have been merged into `MeshRayCast::mesh_query`,
which handles both 2D and 3D
- I assume this existed previously because `Mesh2dHandle` used to be in
`bevy_sprite`. Now both the 2D and 3D mesh are in `bevy_render`.
- There is no `debug` feature or ray debug rendering
- There is no deferred API (`RaycastSource`)
- There is no `CursorRayPlugin` (the picking backend handles this)

### Note for Reviewers

In case it's helpful, the [first
commit](281638ef10)
here is essentially a one-to-one port. The rest of the commits are
primarily refactoring and cleaning things up in the ways listed earlier,
as well as changes to the module structure.

It may also be useful to compare the original [picking
backend](74f0c3c0fb/backends/bevy_picking_raycast/src/lib.rs)
and [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast) to
this PR. Feel free to mention if there are any changes that I should
revert or something I should not include in this PR.

## Testing

I tested mesh picking and relevant components in some examples, for both
2D and 3D meshes, and added a new `mesh_picking` example. I also
~~stole~~ ported over the [ray-mesh intersection
benchmark](dbc5ef32fe/benches/ray_mesh_intersection.rs)
from `bevy_mod_raycast`.

---

## Showcase

Below is a version of the `2d_shapes` example modified to demonstrate 2D
mesh picking. This is not included in this PR.


https://github.com/user-attachments/assets/7742528c-8630-4c00-bacd-81576ac432bf

And below is the new `mesh_picking` example:


https://github.com/user-attachments/assets/b65c7a5a-fa3a-4c2d-8bbd-e7a2c772986e

There is also a really cool new `mesh_ray_cast` example ported over from
`bevy_mod_raycast`:


https://github.com/user-attachments/assets/3c5eb6c0-bd94-4fb0-bec6-8a85668a06c9

---------

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:24:19 +00:00
ickshonpe
6f7d0e5725
split up TextStyle (#15857)
# Objective

Currently text is recomputed unnecessarily on any changes to its color,
which is extremely expensive.

## Solution
Split up `TextStyle` into two separate components `TextFont` and
`TextColor`.

## Testing

I added this system to `many_buttons`:
```rust
fn set_text_colors_changed(mut colors: Query<&mut TextColor>) {
    for mut text_color in colors.iter_mut() {
        text_color.set_changed();
    }
}
```

reports ~4fps on main, ~50fps with this PR.

## Migration Guide
`TextStyle` has been renamed to `TextFont` and its `color` field has
been moved to a separate component named `TextColor` which newtypes
`Color`.
2024-10-13 17:06:22 +00:00
Matty
6521e759ea
Improve PhantomData held by curve adaptors (#15881)
# Objective

The previous `PhantomData` instances were written somewhat lazily, so
they were just things like `PhantomData<T>` for curves with an output
type of `T`. This looks innocuous, but it unnecessarily constrains
`Send/Sync` inference based on `T`. See
[here](https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns).

## Solution

Switch to `PhantomData` of the form `PhantomData<fn() -> T>` for most of
these adaptors. Since they only have a functional relationship to `T`
(i.e. it shows up in the return type of trait methods), this is more
accurate.

## Testing

Tested by compiling Bevy.

Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:06:21 +00:00
Liam Gallagher
813c75958d
Remove a dbg! statement left over from debugging (#15867)
I wonder who left that there...
2024-10-12 09:07:01 +00:00
aecsocket
992d17bc7f
Add bevy_window::Window options for MacOS (#15820)
# Objective

MacOS has some nice options for controlling the window and titlebar to
make the content appear much more "immersively" in the window. This PR
exposes options for controlling this.

## Solution

Adds new fields to `Window` to control these, with doc comments to
explain what they do and that they're MacOS only.

## Testing

Tested on a MacOS machine (not my own, I don't have one). That's where
the below screenshots were taken.

---

## Showcase

On MacOS, you now have more options for configuring the window titlebar.
You can, for example, make the title bar transparent and only show the
window controls. This provides a more "immersive" experience for your
rendered content.

Before, only this was possible:
<img width="1392" alt="image"
src="https://github.com/user-attachments/assets/abf03da2-d247-4202-a7e7-731c45d80d54">

Now, you can create windows like this:
<img width="1392" alt="image2"
src="https://github.com/user-attachments/assets/3239d0e3-4708-4798-8755-188541e14f93">

This uses the following `bevy_window::Window` settings:
```rs
fullsize_content_view: true,
titlebar_transparent: true,
titlebar_show_title: false,
```

## Migration Guide

`bevy_window::Window` now has extra fields for configuring MacOS window
settings:
```rs
    pub movable_by_window_background: bool,
    pub fullsize_content_view: bool,
    pub has_shadow: bool,
    pub titlebar_shown: bool,
    pub titlebar_transparent: bool,
    pub titlebar_show_title: bool,
    pub titlebar_show_buttons: bool,
```

Using `Window::default` keeps the same behaviour as before.
2024-10-11 21:11:21 +00:00
Matty
81b39464c0
Some animation doc improvements (#15860)
# Objective

Animation docs could use some clarification regarding:
- how exactly curves are evaluated
- how additive blend nodes actually work

## Solution

Add some documentation that explains how curve domains are used and how
additive blend nodes treat their children.

## Commentary

The way additive blend nodes work right now is a little bit weird, since
their first child's weight is ignored. Arguably this makes sense, since
additive animations are authored differently from ordinary animations,
but it also feels a bit strange. We could make the first node's weight
actually be applied, and the present behavior would be recovered when
the weight is set to 1.

The main disadvantage of how things are set up now is that combining a
bunch of additive animations without a base pose is pretty awkward (e.g.
to add them onto a base pose later in the graph). If we changed it, the
main downside would be that reusing the same animation on different
parts of the graph is harder; on the other hand, the weights can be
locally reassigned by using blend nodes with no other children, which
rectifies this shortfall.
2024-10-11 20:52:58 +00:00
andriyDev
60a9a81602
Fix potential deadlock in AssetServer on single-threaded modes. (#15808)
# Objective

Fixes #15807 

## Solution

We move the guard into this function.

## Testing

N/A, This is just reverting to the old behavior before #15509.
2024-10-11 16:42:07 +00:00
Andrew
6a39c33d49
Use oslog for ios (#13364)
# Objective

On mobile devices, it's best to use the OS's native logging due to the
difficulty of accessing the console. This is already done for Android.

This is an updated version of
https://github.com/bevyengine/bevy/pull/4462.

## Solution

This PR uses Absolucy's
[tracing-oslog](https://github.com/Absolucy/tracing-oslog) ([ZLib
license](https://github.com/Absolucy/tracing-oslog/blob/main/LICENSE.md))
for iOS in order to use Apple's `os_log`.

## Testing

I ran `examples/mobile` with the logging from `examples/app/logs.rs` on
an iOS device, I then checked the logs could be filtered in the MacOS
Console.app.

## Changelog

 - Change bevy_log to use Apple's os_log on iOS.

## Questions for Reviewers
It's worth noting that the dependency this adds hasn't had bug fixes
released in a few years, so we may want to consider one or more of:
 1. a feature flag to opt-in, and it would also allow `os_log` on MacOS
 2. merge as-is and have some (minor?) upstream bugs
 3. hold off on this PR until a suitable alternative dependency arises
 4. maintain our own implementation

## Future work

In a follow-up PR it might be good to make the `subsystem` field have a
better default value, like [this
one](https://github.com/bevyengine/bevy/blob/main/examples/mobile/bevy_mobile_example.xcodeproj/project.pbxproj#L363).
That value can be retrieved programmatically if we bind another system
API (For posterity in Swift this is `Bundle.main.bundleIdentifier`, but
the C/ObjC equivalent is likely easier to bind). This would almost
always be the correct value, while the current default is unlikely to
ever be correct.

---------

Co-authored-by: Dusty DeWeese <dustin.deweese@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-10-11 08:58:14 +00:00
Gino Valente
da4e7769ad
bevy_ecs: Special-case Entity::PLACEHOLDER formatting (#15839)
# Objective

Oftentimes, users will store an entity on a component or resource. To
make this component/resource `Default`-able, they might initialize it
with `Entity::PLACEHOLDER`. This is sometimes done to avoid the need for
an `Option<Entity>`, especially if it complicates other logic.

For example, it's used in this `Selection` resource to denote "no
selection":

```rust
#[derive(Resource, Debug)]
struct Selection(Entity);

impl Default for Selection {
    fn default() -> Self {
        Self(Entity::PLACEHOLDER)
    }
}
```

The problem is that if we try to `Debug` the current `Selection`, we get
back: `4294967295v1#8589934591`. It's not immediately obvious whether or
not the entity is an actual entity or the placeholder.

Now while it doesn't take long to realize that this is in fact just the
value of `Entity::PLACEHOLDER`, it would be a lot clearer if this was
made explicit, especially for these particular use cases.

## Solution

This PR makes the `Debug` and `Display` impls for `Entity` return
`PLACEHOLDER` for the `Entity::PLACEHOLDER` constant.

~~Feel free to bikeshed the actual value returned here. I think
`PLACEHOLDER` on its own could work too.~~ Swapped to `PLACEHOLDER` from
`Entity::PLACEHOLDER`.

## Testing

You can test locally by running:

```
cargo test --package bevy_ecs
```

---

## Migration Guide

The `Debug` and `Display` impls for `Entity` now return `PLACEHOLDER`
for the `Entity::PLACEHOLDER` constant. If you had any code relying on
these values, you may need to account for this change.
2024-10-11 03:12:01 +00:00
Tim
5def6f2a58
Fix gizmos (#15836)
# Objective

- Immediate mode gizmos don't have a main world entity but the phase
items require `MainEntity` since #15756

## Solution

- Add a dummy `MainEntity` component.

## Testing

Both the `3d_gizmos` and `2d_gizmos` examples show gizmos again
2024-10-10 22:04:04 +00:00
charlotte
da211ee314
Fix broken mesh2d (#15838)
Forgot to clean this up when I was still trying to figure out what was
broken.

Closes #15835.
2024-10-10 21:28:45 +00:00
Matty
a06802a66e
Make AnimatableCurve::curve public (#15831)
# Objective

The other `Curve -> AnimationCurve` wrappers allow public access to the
inner curve, so this one should as well.

## Solution

Made the field public. Instances will still need to be constructed using
the (more ergonomic) `from_curve` method, which infers the phantom type
for the user.
2024-10-10 18:51:17 +00:00
akimakinai
922a25d295
Picking: Filter out invisible sprites early (#15819)
# Objective

- We don't have to `collect` and `sort` invisible sprites in
`sprite_picking` system.

## Solution

- Filter by `ViewVisibility::get()` earlier

## Testing

- `sprite_picking` example still works.
2024-10-10 18:49:23 +00:00
charlotte
dd812b3e49
Type safe retained render world (#15756)
# Objective

In the Render World, there are a number of collections that are derived
from Main World entities and are used to drive rendering. The most
notable are:
- `VisibleEntities`, which is generated in the `check_visibility` system
and contains visible entities for a view.
- `ExtractedInstances`, which maps entity ids to asset ids.

In the old model, these collections were trivially kept in sync -- any
extracted phase item could look itself up because the render entity id
was guaranteed to always match the corresponding main world id.

After #15320, this became much more complicated, and was leading to a
number of subtle bugs in the Render World. The main rendering systems,
i.e. `queue_material_meshes` and `queue_material2d_meshes`, follow a
similar pattern:

```rust
for visible_entity in visible_entities.iter::<With<Mesh2d>>() {
    let Some(mesh_instance) = render_mesh_instances.get_mut(visible_entity) else {
        continue;
    };
            
    // Look some more stuff up and specialize the pipeline...
            
    let bin_key = Opaque2dBinKey {
        pipeline: pipeline_id,
        draw_function: draw_opaque_2d,
        asset_id: mesh_instance.mesh_asset_id.into(),
        material_bind_group_id: material_2d.get_bind_group_id().0,
    };
    opaque_phase.add(
        bin_key,
        *visible_entity,
        BinnedRenderPhaseType::mesh(mesh_instance.automatic_batching),
    );
}
```

In this case, `visible_entities` and `render_mesh_instances` are both
collections that are created and keyed by Main World entity ids, and so
this lookup happens to work by coincidence. However, there is a major
unintentional bug here: namely, because `visible_entities` is a
collection of Main World ids, the phase item being queued is created
with a Main World id rather than its correct Render World id.

This happens to not break mesh rendering because the render commands
used for drawing meshes do not access the `ItemQuery` parameter, but
demonstrates the confusion that is now possible: our UI phase items are
correctly being queued with Render World ids while our meshes aren't.

Additionally, this makes it very easy and error prone to use the wrong
entity id to look up things like assets. For example, if instead we
ignored visibility checks and queued our meshes via a query, we'd have
to be extra careful to use `&MainEntity` instead of the natural
`Entity`.

## Solution

Make all collections that are derived from Main World data use
`MainEntity` as their key, to ensure type safety and avoid accidentally
looking up data with the wrong entity id:

```rust
pub type MainEntityHashMap<V> = hashbrown::HashMap<MainEntity, V, EntityHash>;
```

Additionally, we make all `PhaseItem` be able to provide both their Main
and Render World ids, to allow render phase implementors maximum
flexibility as to what id should be used to look up data.

You can think of this like tracking at the type level whether something
in the Render World should use it's "primary key", i.e. entity id, or
needs to use a foreign key, i.e. `MainEntity`.

## Testing

##### TODO:

This will require extensive testing to make sure things didn't break!
Additionally, some extraction logic has become more complicated and
needs to be checked for regressions.

## Migration Guide

With the advent of the retained render world, collections that contain
references to `Entity` that are extracted into the render world have
been changed to contain `MainEntity` in order to prevent errors where a
render world entity id is used to look up an item by accident. Custom
rendering code may need to be changed to query for `&MainEntity` in
order to look up the correct item from such a collection. Additionally,
users who implement their own extraction logic for collections of main
world entity should strongly consider extracting into a different
collection that uses `MainEntity` as a key.

Additionally, render phases now require specifying both the `Entity` and
`MainEntity` for a given `PhaseItem`. Custom render phases should ensure
`MainEntity` is available when queuing a phase item.
2024-10-10 18:47:04 +00:00
akimakinai
11d1ebeed3
Fix OIT shaders error with DX12 backend (#15782)
# Objective

- Fixes #15781

## Solution

- DX12 backend seems to require functions with return types to return
value. [WebGPU spec also requires
this](https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules).

Upstream issue: https://github.com/gfx-rs/wgpu/issues/4458
https://github.com/gpuweb/gpuweb/issues/2523

## Testing

- Tested `order_independent_transparency` example with both dx12 and
vulkan backend on Windows
2024-10-10 14:17:09 +00:00
Emerson Coskey
f18be66a0c
Fix mesh flags (#15804)
Fixed incorrect mesh flags offsets

## Testing

Ran OIT example since that was the affected flag
2024-10-09 23:50:48 +00:00
ickshonpe
15072d7937
Dark text colors fix (#15794)
# Objective

Fix the text colors.

fixes #15788

## Solution

Add the missing corner flags.
2024-10-09 22:14:36 +00:00
Tim
3da0ef048e
Remove the Component trait implementation from Handle (#15796)
# Objective

- Closes #15716
- Closes #15718

## Solution

- Replace `Handle<MeshletMesh>` with a new `MeshletMesh3d` component
- As expected there were some random things that needed fixing:
- A couple tests were storing handles just to prevent them from being
dropped I believe, which seems to have been unnecessary in some.
- The `SpriteBundle` still had a `Handle<Image>` field. I've removed
this.
- Tests in `bevy_sprite` incorrectly added a `Handle<Image>` field
outside of the `Sprite` component.
- A few examples were still inserting `Handle`s, switched those to their
corresponding wrappers.
- 2 examples that were still querying for `Handle<Image>` were changed
to query `Sprite`

## Testing

- I've verified that the changed example work now

## Migration Guide

`Handle` can no longer be used as a `Component`. All existing Bevy types
using this pattern have been wrapped in their own semantically
meaningful type. You should do the same for any custom `Handle`
components your project needs.

The `Handle<MeshletMesh>` component is now `MeshletMesh3d`.

The `WithMeshletMesh` type alias has been removed. Use
`With<MeshletMesh3d>` instead.
2024-10-09 21:10:01 +00:00
UkoeHB
a6be9b4ccd
Rename TextBlock to TextLayout (#15797)
# Objective

- Improve clarity when spawning a text block. See [this
discussion](https://github.com/bevyengine/bevy/pull/15591/#discussion_r1787083571).

## Solution

- Rename `TextBlock` to `TextLayout`.
2024-10-09 20:58:27 +00:00
Christian Hughes
b4071ca370
Add World::get_resource_or_init as an alternative to World::get_resource_or_insert_with (#15758)
# Objective

If a `Resource` implements `FromWorld` or `Default`, it's nicer to be
able to write:

```rust
let foo = world.get_resource_or_init::<Foo>();
```

Rather than:

```rust
let foo = world.get_resource_or_insert_with(Foo::default);
```

The latter is also not possible if a type implements `FromWorld` only,
and not `Default`.

## Solution

Added:

```rust
impl World {
    pub fn get_resource_or_init<R: Resource + FromWorld>(&mut self) -> Mut<'_, R>;
}
```

Turns out all current in-engine uses of `get_resource_or_insert_with`
are exactly the above, so they've also been replaced.

## Testing

- Added a doc-test.
- Also added a doc-test for `World::get_resource_or_insert_with`.
2024-10-09 20:56:26 +00:00
Brandon Reinhart
88d9ead7f8
promote atlas sources texture_ids to pub visibility (#15795)
In order to create texture atlases from other systems (custom game
solutions) that are compatible with the ones generated by the bevy
builders, it would be nice to have the interface be fully public. This
field is pub(crate). Unless there's a good reason, can we promote this
to pub?

Alternatives:
- Don't do it.
2024-10-09 18:37:26 +00:00
UkoeHB
c2c19e5ae4
Text rework (#15591)
**Ready for review. Examples migration progress: 100%.**

# Objective

- Implement https://github.com/bevyengine/bevy/discussions/15014

## Solution

This implements [cart's
proposal](https://github.com/bevyengine/bevy/discussions/15014#discussioncomment-10574459)
faithfully except for one change. I separated `TextSpan` from
`TextSpan2d` because `TextSpan` needs to require the `GhostNode`
component, which is a `bevy_ui` component only usable by UI.

Extra changes:
- Added `EntityCommands::commands_mut` that returns a mutable reference.
This is a blocker for extension methods that return something other than
`self`. Note that `sickle_ui`'s `UiBuilder::commands` returns a mutable
reference for this reason.

## Testing

- [x] Text examples all work.

---

## Showcase

TODO: showcase-worthy

## Migration Guide

TODO: very breaking

### Accessing text spans by index

Text sections are now text sections on different entities in a
hierarchy, Use the new `TextReader` and `TextWriter` system parameters
to access spans by index.

Before:
```rust
fn refresh_text(mut query: Query<&mut Text, With<TimeText>>, time: Res<Time>) {
    let text = query.single_mut();
    text.sections[1].value = format_time(time.elapsed());
}
```

After:
```rust
fn refresh_text(
    query: Query<Entity, With<TimeText>>,
    mut writer: UiTextWriter,
    time: Res<Time>
) {
    let entity = query.single();
    *writer.text(entity, 1) = format_time(time.elapsed());
}
```

### Iterating text spans

Text spans are now entities in a hierarchy, so the new `UiTextReader`
and `UiTextWriter` system parameters provide ways to iterate that
hierarchy. The `UiTextReader::iter` method will give you a normal
iterator over spans, and `UiTextWriter::for_each` lets you visit each of
the spans.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-09 18:35:36 +00:00
Nathan Lilienthal
0b2e0cfaca
bevy_reflect: Add crate level functions feature docs (#15086)
Adds the missing section for the `functions` cargo feature of the
`bevy_reflect` crate.
2024-10-09 18:06:56 +00:00
Tim
e19c53ebbd
Remove Handle<T> trait implementations that are dependent on Component (#15749)
# Objective

- Another step towards #15716
- Remove trait implementations that are dependent on `Handle<T>` being a
`Component`

## Solution

- Remove unused `ExtractComponent` trait implementation for `Handle<T>`
- Remove unused `ExtractInstance` trait implementation for `AssetId`
- Although the `ExtractInstance` trait wasn't used, the `AssetId`s were
being stored inside of `ExtractedInstances` which has an
`ExtractInstance` trait bound on its contents.
I've upgraded the `RenderMaterialInstances` type alias to be its own
resource, identical to `ExtractedInstances<AssetId<M>>` to get around
that with minimal breakage.
## Testing

Tested `many_cubes`, rendering did not explode
2024-10-09 17:12:27 +00:00
Matty
123a19afa9
Put curve-related stuff behind a feature (#15790)
# Objective

A bunch of code is used only if you care about the `Curve` trait. Put it
behind a feature so it can be ignored if wanted.

## Solution

Added a default feature `curve` to `bevy_math` which feature-gates the
`curve` module and internal integrations.

## Testing

Tested compiling with the feature enabled and disabled.
2024-10-09 16:38:23 +00:00
Emerson Coskey
7d40e3ec87
Migrate bevy_sprite to required components (#15489)
# Objective

Continue migration of bevy APIs to required components, following
guidance of https://hackmd.io/@bevy/required_components/

## Solution

- Make `Sprite` require `Transform` and `Visibility` and
`SyncToRenderWorld`
- move image and texture atlas handles into `Sprite`
- deprecate `SpriteBundle`
- remove engine uses of `SpriteBundle`

## Testing

ran cargo tests on bevy_sprite and tested several sprite examples.

---

## Migration Guide

Replace all uses of `SpriteBundle` with `Sprite`. There are several new
convenience constructors: `Sprite::from_image`,
`Sprite::from_atlas_image`, `Sprite::from_color`.

WARNING: use of `Handle<Image>` and `TextureAtlas` as components on
sprite entities will NO LONGER WORK. Use the fields on `Sprite` instead.
I would have removed the `Component` impls from `TextureAtlas` and
`Handle<Image>` except it is still used within ui. We should fix this
moving forward with the migration.
2024-10-09 16:17:26 +00:00
Christian Hughes
219b5930f1
Rename App/World::observe to add_observer, EntityWorldMut::observe_entity to observe. (#15754)
# Objective

- Closes #15752

Calling the functions `App::observe` and `World::observe` doesn't make
sense because you're not "observing" the `App` or `World`, you're adding
an observer that listens for an event that occurs *within* the `World`.
We should rename them to better fit this.

## Solution

Renames:
- `App::observe` -> `App::add_observer`
- `World::observe` -> `World::add_observer`
- `Commands::observe` -> `Commands::add_observer`
- `EntityWorldMut::observe_entity` -> `EntityWorldMut::observe`

(Note this isn't a breaking change as the original rename was introduced
earlier this cycle.)

## Testing

Reusing current tests.
2024-10-09 15:39:29 +00:00
Joona Aalto
a2b53d46e7
Fix meshlet materials (#15755)
# Objective

After #15524, there are these bunny-shaped holes in rendering in the
meshlet example!


![broken](https://github.com/user-attachments/assets/9e9f20ec-b820-44df-b961-68a1dee44002)

This is because (1) they're using a raw asset handle instead of
`MeshMaterial3d`, and (2) the system that extracts mesh materials into
the render world has an unnecessary `With<Mesh3d>` filter, which makes
it not account for meshlets.

## Solution

Remove the redundant filter and use `MeshMaterial3d`. The bunnies got
some paint!


![fixed](https://github.com/user-attachments/assets/adb42556-fd4b-4000-8ca8-1356250dd532)
2024-10-09 15:39:10 +00:00
Zachary Harrold
35edb256ab
Remove thiserror from bevy_asset (#15778)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_asset`
2024-10-09 14:30:46 +00:00
Zachary Harrold
ecd04c1b72
Remove thiserror from bevy_sprite (#15763)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_sprite`
2024-10-09 14:29:26 +00:00
Zachary Harrold
b50f2ec334
Remove thiserror from bevy_scene (#15764)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_scene`
2024-10-09 14:29:10 +00:00
Zachary Harrold
c9e41ef552
Remove thiserror from bevy_ui (#15760)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_ui`
2024-10-09 14:27:53 +00:00
Zachary Harrold
bdc649a2d1
Remove thiserror from bevy_transform (#15761)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_transform`
2024-10-09 14:27:30 +00:00
Zachary Harrold
8fd3d54e48
Remove thiserror from bevy_text (#15762)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_text`
2024-10-09 14:27:09 +00:00
Zachary Harrold
8718adc74f
Remove thiserror from bevy_render (#15765)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_render`
2024-10-09 14:26:28 +00:00
Zachary Harrold
3cc1527e9e
Remove thiserror from bevy_reflect (#15766)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_reflect`
2024-10-09 14:25:41 +00:00
Zachary Harrold
46ad0b7513
Remove thiserror from bevy_pbr (#15767)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_pbr`
2024-10-09 14:25:16 +00:00
Zachary Harrold
80fe269349
Remove thiserror from bevy_mesh (#15768)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_mesh`
2024-10-09 14:24:54 +00:00
Zachary Harrold
1f4adec7df
Remove thiserror from bevy_image (#15771)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_image`
2024-10-09 14:23:53 +00:00
Zachary Harrold
9366b95006
Remove thiserror from bevy_math (#15769)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_math`
2024-10-09 14:23:23 +00:00
Zachary Harrold
5e89acacb4
Remove thiserror from bevy_input (#15770)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_input`
2024-10-09 14:23:01 +00:00
Zachary Harrold
f88c6820f0
Remove thiserror from bevy_gltf (#15772)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_gltf`
2024-10-09 14:22:00 +00:00
Zachary Harrold
c6a2411e90
Remove thiserror from bevy_gilrs (#15773)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_gilrs`
2024-10-09 14:21:25 +00:00
Zachary Harrold
0a61f04d9b
Remove thiserror from bevy_ecs (#15774)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_ecs`
2024-10-09 14:20:58 +00:00
Zachary Harrold
4c76ea7a5a
Remove thiserror from bevy_core_pipeline (#15775)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_core_pipeline`
2024-10-09 14:20:16 +00:00
Zachary Harrold
284e36af5e
Remove thiserror from bevy_color (#15777)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_color`
2024-10-09 14:18:41 +00:00
Zachary Harrold
1be0ed33fc
Remove thiserror from bevy_app (#15779)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_app`
2024-10-09 14:17:52 +00:00
Zachary Harrold
814f8ec039
Remove thiserror from bevy_animation (#15780)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_animation`
2024-10-09 14:16:21 +00:00
Zachary Harrold
6cc2322fa3
Remove thiserror from bevy_time (#15759)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_time`

## Notes

`thiserror` actually wasn't even used in this crate.
2024-10-09 14:13:28 +00:00
ickshonpe
a7ed13ad17
Add register_type for UiAntiAlias (#15783)
# Objective

Add `register_type` for `UiAntiAlias`
2024-10-09 14:04:26 +00:00
Tim
57c297becc
Add register_type for UiMaterialHandle and AnimationGraphHandle (#15784) 2024-10-09 14:04:06 +00:00
Gino Valente
05b0f28ebf
bevy_scene: Use FromReflect on extracted resources (#15753)
# Objective

Fixes #15726

The extraction logic for components makes use of `FromReflect` to try
and ensure we have a concrete type for serialization. However, we did
not do the same for resources.

The reason we're seeing this for the glam types is that #15174 also made
a change to rely on the glam type's `Serialize` and `Deserialize` impls,
which I don't think should have been merged (I'll put up a PR addressing
this specifically soon).

## Solution

Use `FromReflect` on extracted resources.

## Testing

You can test locally by running:

```
cargo test --package bevy_scene
```
2024-10-09 02:56:35 +00:00
Joona Aalto
bc352561c9
Migrate reflection probes to required components (#15737)
# Objective

Getting closer to the end! Another part of the required components
migration: reflection probes.

## Solution

As per the [proposal added by
Cart](https://hackmd.io/@bevy/required_components/%2FNmpIh0tGSiayGlswbfcEzw)
(Proposal 2), make `LightProbe` require `Transform` and `Visibility`,
and deprecate `ReflectionProbeBundle`.

Note that this proposal wasn't officially blessed yet, but it is the
only existing one that really works, so I implemented it here for
consideration.

## Testing

I ran the reflection probe example, and it appears to work.

---

## Migration Guide

`ReflectionProbeBundle` has been deprecated in favor of inserting the
`LightProbe` and `EnvironmentMapLight` components directly. Inserting
them will now automatically insert `Transform` and `Visibility`
components.

---------

Co-authored-by: Tim Blackbird <justthecooldude@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-08 23:59:27 +00:00
Shoyu Vanilla (Flint)
a89ae8e9d9
fix: Skip some rendering logics when the viewport width or height is zero (#15654)
# Objective

- Fixes #15285

## Solution

`winit` sends resized to zero events when the window is minimized only
on Windows OS(rust-windowing/winit#2015).
This makes updating window viewport size to `(0, 0)` and panicking when
calculating aspect ratio.

~~So, just skip these kinds of events - resizing to (0, 0) when the
window is minimized - on Windows OS~~

Idially, the camera extraction excludes the cameras whose target size
width or height is zero here;


25bfa80e60/crates/bevy_render/src/camera/camera.rs (L1060-L1074)

but it seems that winit event loop sends resize events after extraction
and before post update schedule, so they might panics before the
extraction filters them out.

Alternatively, it might be possible to change event loop evaluating
order or defer them to the right schedule but I'm afraid that it might
cause some breaking changes, so just skip rendering logics for such
windows and they will be all filtered out by the extractions on the next
frame and thereafter.

## Testing

Running the example in the original issue and minimizing causes panic,
or just running `tests/window/minimising.rs` with `cargo run --example
minimising` panics without this PR and doesn't panics with this PR.

I think that we should run it in CI on Windows OS btw
2024-10-08 22:52:19 +00:00
Antony
0837ade0fc
Ensure Bevy's rendering byte usage is little-endian (#15750)
# Objective

- Fixes (partially) #15701.

## Solution

- Use little-endian bytes over native-endian bytes where applicable.

## Testing

- Ran CI.

## Open Questions

- Should we config-gate these for big-endian targets? It looks like
there are [very few
targets](https://doc.rust-lang.org/nightly/rustc/platform-support.html)
that use big-endian.
2024-10-08 22:43:35 +00:00
Tim
700123ec64
Replace Handle<AnimationGraph> component with a wrapper (#15742)
# Objective

- Closes #15717 

## Solution

- Wrap the handle in a new wrapper component: `AnimationGraphHandle`.

## Testing

Searched for all instances of `AnimationGraph` in the examples and
updated and tested those

## Migration Guide

`Handle<AnimationGraph>` is no longer a component. Instead, use the
`AnimationGraphHandle` component which contains a
`Handle<AnimationGraph>`.
2024-10-08 22:41:24 +00:00
papow65
01b37d67fc
Fix failing cargo check with only the bevy_dev_tools feature (#15743)
# Objective
Fixes #15741

## Solution

- Copied the feature gates of a type to where the type is used.

## Testing

- `cargo check` works now using only the bevy_dev_tools feature
2024-10-08 22:41:04 +00:00
IceSentry
dec52a0c8f
Use shader_def for oit resolve layer count (#15747)
# Objective

- Size is currently hardcoded in the shader which means it will break if
a user uses anything higher than that.

## Solution

- Use a shader_def to define the size

## Testing

Tested with the OIT example
2024-10-08 22:40:17 +00:00
ickshonpe
675f8ad403
Improved text batching (#14848)
# Objective

The UI text rendering is really slow because it extracts each glyph as a
separate ui node even though all the glyphs in a text section have the
same texture, color and clipping rects.

## Solution

Store the glyphs in a seperate contiguous array, queue one transparent
ui item per text section which has indices into the glyph array.

## Testing

```cargo run --example many_glyphs --release```

Runs at about 22fps on main and 95fps with this PR on my computer.

I'll do some proper comparisons once I work out why tracy 11 is refusing to run.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-10-08 22:24:27 +00:00
Kristoffer Søholm
2d1b4939d2
Synchronize removed components with the render world (#15582)
# Objective

Fixes #15560
Fixes (most of) #15570

Currently a lot of examples (and presumably some user code) depend on
toggling certain render features by adding/removing a single component
to an entity, e.g. `SpotLight` to toggle a light. Because of the
retained render world this no longer works: Extract will add any new
components, but when it is removed the entity persists unchanged in the
render world.

## Solution

Add `SyncComponentPlugin<C: Component>` that registers
`SyncToRenderWorld` as a required component for `C`, and adds a
component hook that will clear all components from the render world
entity when `C` is removed. We add this plugin to
`ExtractComponentPlugin` which fixes most instances of the problem. For
custom extraction logic we can manually add `SyncComponentPlugin` for
that component.

We also rename `WorldSyncPlugin` to `SyncWorldPlugin` so we start a
naming convention like all the `Extract` plugins.

In this PR I also fixed a bunch of breakage related to the retained
render world, stemming from old code that assumed that `Entity` would be
the same in both worlds.

I found that using the `RenderEntity` wrapper instead of `Entity` in
data structures when referring to render world entities makes intent
much clearer, so I propose we make this an official pattern.

## Testing

Run examples like

```
cargo run --features pbr_multi_layer_material_textures --example clearcoat
cargo run --example volumetric_fog
```

and see that they work, and that toggles work correctly. But really we
should test every single example, as we might not even have caught all
the breakage yet.

---

## Migration Guide

The retained render world notes should be updated to explain this edge
case and `SyncComponentPlugin`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Trashtalk217 <trashtalk217@gmail.com>
2024-10-08 22:23:17 +00:00
François Mockers
45eff09213
remove the interpolation dependency from bevy_math (#15748)
# Objective

- `interpolation` crates provides all the curves functions, but some of
them were wrong
- We have a partial solution where some functions comes from the
external crate, some from bevy_math

## Solution

- Move them all to bevy_math
- Remove the dependency on `interpolation`

## Testing

Playing the `easing_functions` example

![easing-functions](https://github.com/user-attachments/assets/88832f34-4bb3-4dc2-85af-7b9e4fa23e52)
2024-10-08 22:18:25 +00:00
Alice Cecile
2f63ebc9c9
Remove warning for children in UI hierarchies without Style (#15736)
# Objective

As discussed in #15591, this warning prevents us from storing leaf nodes
without a `Style` component. Because text sections (as distinct
entities) should not be laid out using `taffy`, this warning is
incorrect.

Users may also have other uses for doing this, and this should generally
increase flexibility without posing particularly serious correctness
concerns.

## Solution

- removed warning about non-UI children with UI parents
- improved the warning about UI parents with non-UI parents
- this warning should stay, for now, as it results in a genuine failure
to perform `taffy` layout
- that said, we should be clearer about the cause and potentially
harmful results of this!
   
## Testing

I inserted an empty entity into the hierarchy in the `button` example as
a leaf node, and it ran with no warnings.
2024-10-08 19:51:47 +00:00
Matty
e563f86a1d
Simplified easing curves (#15711)
# Objective

Simplify the API surrounding easing curves. Broaden the base of types
that support easing.

## Solution

There is now a single library function, `easing_curve`, which constructs
a unit-parametrized easing curve between two values based on an
`EaseFunction`:
```rust
/// Given a `start` and `end` value, create a curve parametrized over [the unit interval]
/// that connects them, using the given [ease function] to determine the form of the
/// curve in between.
///
/// [the unit interval]: Interval::UNIT
/// [ease function]: EaseFunction
pub fn easing_curve<T: Ease>(start: T, end: T, ease_fn: EaseFunction) -> EasingCurve<T> { //... }
```

As this shows, the type of the output curve is generic only in `T`. In
particular, as long as `T` is `Reflect` (and `FromReflect` etc. — i.e.,
a standard "well-behaved" reflectable type), `EasingCurve<T>` is also
`Reflect`, and there is no special field handling nonsense. Therefore,
`EasingCurve` is the kind of thing that would be able to be easily
changed in an editor. This is made possible by storing the actual
`EaseFunction` on `EasingCurve<T>` instead of indirecting through some
kind of function type (which generally leads to issues with reflection).

The types that can be eased are those that implement a trait `Ease`:
```rust
/// A type whose values can be eased between.
///
/// This requires the construction of an interpolation curve that actually extends
/// beyond the curve segment that connects two values, because an easing curve may
/// extrapolate before the starting value and after the ending value. This is
/// especially common in easing functions that mimic elastic or springlike behavior.
pub trait Ease: Sized {
    /// Given `start` and `end` values, produce a curve with [unlimited domain]
    /// that:
    /// - takes a value equivalent to `start` at `t = 0`
    /// - takes a value equivalent to `end` at `t = 1`
    /// - has constant speed everywhere, including outside of `[0, 1]`
    ///
    /// [unlimited domain]: Interval::EVERYWHERE
    fn interpolating_curve_unbounded(start: &Self, end: &Self) -> impl Curve<Self>;
}
```

(I know, I know, yet *another* interpolation trait. See 'Future
direction'.)

The other existing easing functions from the previous version of this
module have also become new members of `EaseFunction`: `Linear`,
`Steps`, and `Elastic` (which maybe needs a different name). The latter
two are parametrized.

## Testing

Tested using the `easing_functions` example. I also axed the
`cubic_curve` example which was of questionable value and replaced it
with `eased_motion`, which uses this API in the context of animation:


https://github.com/user-attachments/assets/3c802992-6b9b-4b56-aeb1-a47501c29ce2


---

## Future direction

Morally speaking, `Ease` is incredibly similar to `StableInterpolate`.
Probably, we should just merge `StableInterpolate` into `Ease`, and then
make `SmoothNudge` an automatic extension trait of `Ease`. The reason I
didn't do that is that `StableInterpolate` is not implemented for
`VectorSpace` because of concerns about the `Color` types, and I wanted
to avoid controversy. I think that may be a good idea though.

As Alice mentioned before, we should also probably get rid of the
`interpolation` dependency.

The parametrized `Elastic` variant probably also needs some additional
work (e.g. renaming, in/out/in-out variants, etc.) if we want to keep
it.
2024-10-08 19:45:13 +00:00
Tim
9aef71bd9b
Replace Handle<M: UiMaterial> component with UiMaterialHandle wrapper (#15740)
# Objective

- Closes #15720

## Solution

Wrap the handle in a new wrapper component: `UiMaterialHandle`
It's not possible to match the naming convention of `MeshMaterial3d/2d`
here with the trait already being called `UiMaterial`

Should we consider renaming to `Material3d/2dHandle` and `Mesh3d/2d` to
`Mesh3d/2dHandle`?

- This shouldn't have any merge conflicts with #15591

## Testing

Tested the `ui_material` example

## Migration Guide

Let's defer the migration guide to the required component port. I just
want to yeet the `Component` impl on `Handle` in the meantime :)
2024-10-08 19:07:58 +00:00
JMS55
aa626e4f0b
Per-meshlet compressed vertex data (#15643)
# Objective
- Prepare for streaming by storing vertex data per-meshlet, rather than
per-mesh (this means duplicating vertices per-meshlet)
- Compress vertex data to reduce the cost of this

## Solution
The important parts are in from_mesh.rs, the changes to the Meshlet type
in asset.rs, and the changes in meshlet_bindings.wgsl. Everything else
is pretty secondary/boilerplate/straightforward changes.

- Positions are quantized in centimeters with a user-provided power of 2
factor (ideally auto-determined, but that's a TODO for the future),
encoded as an offset relative to the minimum value within the meshlet,
and then stored as a packed list of bits using the minimum number of
bits needed for each vertex position channel for that meshlet
- E.g. quantize positions (lossly, throws away precision that's not
needed leading to using less bits in the bitstream encoding)
- Get the min/max quantized value of each X/Y/Z channel of the quantized
positions within a meshlet
- Encode values relative to the min value of the meshlet. E.g. convert
from [min, max] to [0, max - min]
- The new max value in the meshlet is (max - min), which only takes N
bits, so we only need N bits to store each channel within the meshlet
(lossless)
- We can store the min value and that it takes N bits per channel in the
meshlet metadata, and reconstruct the position from the bitstream
- Normals are octahedral encoded and than snorm2x16 packed and stored as
a single u32.
- Would be better to implement the precise variant of octhedral encoding
for extra precision (no extra decode cost), but decided to keep it
simple for now and leave that as a followup
- Tried doing a quantizing and bitstream encoding scheme like I did for
positions, but struggled to get it smaller. Decided to go with this for
simplicity for now
- UVs are uncompressed and take a full 64bits per vertex which is
expensive
  - In the future this should be improved
- Tangents, as of the previous PR, are not explicitly stored and are
instead derived from screen space gradients
- While I'm here, split up MeshletMeshSaverLoader into two separate
types

Other future changes include implementing a smaller encoding of triangle
data (3 u8 indices = 24 bits per triangle currently), and more
disk-oriented compression schemes.

References:
* "A Deep Dive into UE5's Nanite Virtualized Geometry"
https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf#page=128
(also available on youtube)
* "Towards Practical Meshlet Compression"
https://arxiv.org/pdf/2404.06359
* "Vertex quantization in Omniforce Game Engine"
https://daniilvinn.github.io/2024/05/04/omniforce-vertex-quantization.html

## Testing

- Did you test these changes? If so, how?
- Converted the stanford bunny, and rendered it with a debug material
showing normals, and confirmed that it's identical to what's on main.
EDIT: See additional testing in the comments below.
- Are there any parts that need more testing?
- Could use some more size comparisons on various meshes, and testing
different quantization factors. Not sure if 4 is a good default. EDIT:
See additional testing in the comments below.
- Also did not test runtime performance of the shaders. EDIT: See
additional testing in the comments below.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Use my unholy script, replacing the meshlet example
https://paste.rs/7xQHk.rs (must make MeshletMesh fields pub instead of
pub crate, must add lz4_flex as a dev-dependency) (must compile with
meshlet and meshlet_processor features, mesh must have only positions,
normals, and UVs, no vertex colors or tangents)

---

## Migration Guide
- TBD by JMS55 at the end of the release
2024-10-08 18:42:55 +00:00
Joona Aalto
f6cd6a4874
Use Dir2/Dir3 instead of Vec2/Vec3 for Ray2d::new/Ray3d::new (#15735)
# Objective

The `new` constructors for our ray types currently take a `Vec2`/`Vec3`
instead of a `Dir2`/`Dir3`. This is confusing and footgunny for several
reasons.

- Which one of these is the direction? You can't see it from the type.

```rust
let ray = Ray2d::new(Vec2::X, Vec2::X);
```

- Many engines allow unnormalized rays, and this can affect ray cast
results by scaling the time of impact. However, in Bevy, rays are
*always* normalized despite what the input argument in this case
implies, and ray cast results are *not* scaled.

```rust
// The true ray direction is still normalized, unlike what you'd expect.
let ray = Ray2d::new(Vec2::X, Vec2::new(5.0, 0.0, 0.0)));
```

These cases are what the direction types are intended for, and we should
use them as such.

## Solution

Use `Dir2`/`Dir3` in the constructors.

```rust
let ray = Ray2d::new(Vec2::X, Dir2::X);
```

We *could* also use `impl TryInto<DirN>`, which would allow both vectors
and direction types, and then panic if the input is not normalized. This
could be fine for ergonomics in some cases, but especially for rays, I
think it's better to take an explicit direction type here.

---

## Migration Guide

`Ray2d::new` and `Ray3d::new` now take a `Dir2` and `Dir3` instead of
`Vec2` and `Vec3` respectively for the ray direction.
2024-10-08 16:45:03 +00:00
Isse
82aa2e3161
Add the functions start_drag_move and start_drag_resize to Window (#15674)
# Objective
Expose the `winit` functions
[drag_window](https://docs.rs/winit/latest/winit/window/struct.Window.html#method.drag_window)
and
[resize_window](https://docs.rs/winit/latest/winit/window/struct.Window.html#method.drag_resize_window).

Which allows implementing move & resize for windows without decorations.

## Solution

Add the functions `start_drag_move` and `start_drag_resize` to
`bevy_window::Window`, which are then assigned to fields in
`InternalWindowState`, and propagated to `winit` in the
`changed_windows` system.

## Testing

I've tested that both functions works on x11 and wayland. Not sure if
someone needs to test on windows/mac?

---

## Showcase

[Screencast from 2024-10-06 11-49-58
(trimmed).webm](https://github.com/user-attachments/assets/1cdee7b1-22bd-41d3-8a0a-6872a6ebf62c)

(The flickering in the video is some issue with resizing without
decorations on x11)

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

Not the same code used in the video, but simple way to test moving a
window without decorations.
```rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                decorations: false,
                ..default()
            }),
            ..default()
        }))
        .add_systems(Update, move_windows)
        .run();
}

fn move_windows(mut windows: Query<&mut Window>, input: Res<ButtonInput<MouseButton>>) {
    if input.pressed(MouseButton::Left) {
        for mut window in windows.iter_mut() {
            window.start_drag_move();
        }
    }
}
```

</details>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-08 16:32:07 +00:00
ickshonpe
99b9a2fcd7
box shadow (#15204)
# Objective

UI box shadow support

Adds a new component `BoxShadow`:

```rust
pub struct BoxShadow {
    /// The shadow's color
    pub color: Color,
    /// Horizontal offset
    pub x_offset: Val,
    /// Vertical offset
    pub y_offset: Val,
    /// Horizontal difference in size from the occluding uninode
    pub spread_radius: Val,
    /// Blurriness of the shadow
    pub blur_radius: Val,
}
```

To use `BoxShadow`, add the component to any Bevy UI node and a shadow
will be drawn beneath that node.
Also adds a resource `BoxShadowSamples` that can be used to adjust the
shadow quality.

#### Notes
* I'm not super happy with the field names. Maybe we need a `struct Size
{ width: Val, height: Val }` type or something.
* The shader isn't very optimised but I don't see that it's too
important for now as the number of shadows being rendered is not going
to be massive most of the time. I think it's more important to get the
API and geometry correct with this PR.
* I didn't implement an inset property, it's not essential and can
easily be added in a follow up.
* Shadows are only rendered for uinodes, not for images or text.
* Batching isn't supported, it would need out-of-the-scope-of-this-pr
changes to the way the UI handles z-ordering for it to be effective.

# Showcase

```cargo run --example box_shadow -- --samples 4```

<img width="391" alt="br" src="https://github.com/user-attachments/assets/4e8add96-dc93-46e0-9e35-d995eb0943ad">

```cargo run --example box_shadow -- --samples 10```

<img width="391" alt="s10"
src="https://github.com/user-attachments/assets/ecb384c9-4012-4cd6-9dea-5180904bf28e">
2024-10-08 16:26:17 +00:00
Liam Gallagher
f1fbb668f9
Watching versions of bevy/get and bevy/list with HTTP SSE (#15608)
## Objective

Add a way to stream BRP requests when the data changes.

## Solution

#### BRP Side (reusable for other transports)

Add a new method handler type that returns a optional value. This
handler is run in update and if a value is returned it will be sent on
the message channel. Custom watching handlers can be added with
`RemotePlugin::with_watching_method`.

#### HTTP Side

If a request comes in with `+watch` in the method, it will respond with
`text/event-stream` rather than a single response.

## Testing

I tested with the podman HTTP client. This client has good support for
SSE's if you want to test it too.

## Parts I want some opinions on

- For separating watching methods I chose to add a `+watch` suffix to
the end kind of like `content-type` headers. A get would be
`bevy/get+watch`.
- Should watching methods send an initial response with everything or
only respond when a change happens? Currently the later is what happens.

## Future work

- The `bevy/query` method would also benefit from this but that
condition will be quite complex so I will leave that to later.

---------

Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-10-08 16:21:46 +00:00
Joona Aalto
21b78b5990
Implement From translation and rotation for isometries (#15733)
# Objective

Several of our APIs (namely gizmos and bounding) use isometries on
current Bevy main. This is nicer than separate properties in a lot of
cases, but users have still expressed usability concerns.

One problem is that in a lot of cases, you only care about e.g.
translation, so you end up with this:

```rust
gizmos.cross_2d(
    Isometry2d::from_translation(Vec2::new(-160.0, 120.0)),
    12.0,
    FUCHSIA,
);
```

The isometry adds quite a lot of length and verbosity, and isn't really
that relevant since only the translation is important here.

It would be nice if you could use the translation directly, and only
supply an isometry if both translation and rotation are needed. This
would make the following possible:

```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```

removing a lot of verbosity.

## Solution

Implement `From<Vec2>` and `From<Rot2>` for `Isometry2d`, and
`From<Vec3>`, `From<Vec3A>`, and `From<Quat>` for `Isometry3d`. These
are lossless conversions that fit the semantics of `From`.

This makes the proposed API possible! The methods must now simply take
an `impl Into<IsometryNd>`, and this works:

```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```
2024-10-08 16:09:28 +00:00
Peter Hayman
1c3dee4a6c
fix: register_type::<ScrollPosition> (#15721)
# Objective

- register types that derive reflect.
2024-10-08 16:07:09 +00:00
Tomi Fontanilles
3d8e56f766
introduction of ConvexPolygon and ConvexPolygonMeshBuilder (#15544)
# Objective

- As discussed on
[Discord](https://discord.com/channels/691052431525675048/1203087353850364004/1285300659746246849),
implement a `ConvexPolygon` 2D math primitive and associated mesh
builder.
- The original goal was to have a mesh builder for the simplest (i.e.
convex) polygons.

## Solution

- The `ConvexPolygon` is created from its vertices.
- The convexity of the polygon is checked when created via `new()` by
verifying that the winding order of all the triangles formed with
adjacent vertices is the same.
- The `ConvexPolygonMeshBuilder` uses an anchor vertex and goes through
every adjacent pair of vertices in the polygon to form triangles that
fill up the polygon.

## Testing

- Tested locally with my own simple `ConvexPolygonMeshBuilder` usage.
2024-10-08 15:02:38 +00:00
charlotte
b48f9e2a4b
Fix oit webgl (#15728)
The previous fixes were breaking pretty much everything on main due to
naga-oil complaining about the OIT shader not being loaded, since
apparently webgl is a default feature. This fix is a bit messier, but
properly warns the user and is probably what we should have gone for in
the first place.
2024-10-08 14:50:35 +00:00
Patrick Walton
48e2027827
Add some missing features from the gamepads-as-entities change that were needed to update leafwing-input-manager. (#15685)
The gamepads-as-entities change caused several regressions. This patch
fixes each of them:

1. This PR introduces two new fields on `GamepadInfo`: `vendor_id`, and
`product_id`, as well as associated methods. These fields are simply
mirrored from the `gilrs` library.

2. That PR removed the methods that allowed iterating over all pressed
and released buttons, as well as the method that allowed iterating over
the axis values. (It was still technically possible to do so by using
reflection to access the private fields of `Gamepad`.)

3. The `Gamepad` component wasn't marked reflectable. This PR fixes that
problem.

These changes allowed me to forward port `leafwing-input-manager`.
2024-10-08 12:19:38 +00:00
IceSentry
4bf647ff3b
Add Order Independent Transparency (#14876)
# Objective

- Alpha blending can easily fail in many situations and requires sorting
on the cpu

## Solution

- Implement order independent transparency (OIT) as an alternative to
alpha blending
- The implementation uses 2 passes
- The first pass records all the fragments colors and position to a
buffer that is the size of N layers * the render target resolution.
- The second pass sorts the fragments, blends them and draws them to the
screen. It also currently does manual depth testing because early-z
fails in too many cases in the first pass.

## Testing

- We've been using this implementation at foresight in production for
many months now and we haven't had any issues related to OIT.

---

## Showcase


![image](https://github.com/user-attachments/assets/157f3e32-adaf-4782-b25b-c10313b9bc43)

![image](https://github.com/user-attachments/assets/bef23258-0c22-4b67-a0b8-48a9f571c44f)

## Future work

- Add an example showing how to use OIT for a custom material
- Next step would be to implement a per-pixel linked list to reduce
memory use
- I'd also like to investigate using a BinnedRenderPhase instead of a
SortedRenderPhase. If it works, it would make the transparent pass
significantly faster.

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Charlotte McElwain <charlotte.c.mcelwain@gmail.com>
2024-10-07 23:50:28 +00:00
notmd
cab00766d9
Serialize and deserialize tuple struct with one field as newtype struct (#15628)
# Objective

- fix https://github.com/bevyengine/bevy/issues/15623
## Solution

- Checking field length of tuple struct before ser/der

## Testing

- CI should pass

## Migration Guide

- Reflection now will serialize and deserialize tuple struct with single
field as newtype struct. Consider this code.
```rs
#[derive(Reflect, Serialize)]
struct Test(usize);
let reflect = Test(3);
let serializer = TypedReflectSerializer::new(reflect.as_partial_reflect(), &registry);
return serde_json::to_string(&serializer)
```
Old behavior will return `["3"]`. New behavior will return `"3"`. If you
were relying on old behavior you need to update your logic. Especially
with `serde_json`. `ron` doesn't affect from this.
2024-10-07 23:40:03 +00:00
Matty
9b863be2fb
Curves: FromReflect boogaloo part 2 (#15714)
# Objective

Allow curve adaptors to be reliably `Reflect` even if the curves they
hold are not `FromReflect`. This allows them, for example, to be used in
`bevy_animation`. I previously addressed this with the functional
adaptors, but I forgot to address this in the case of fields that hold
other curves and not arbitrary functions.

## Solution

Do the following on every curve adaptor that holds another curve:
```rust
// old:
#[derive(Reflect)]
```

```rust
// new:
#[derive(Reflect, FromReflect)]
#[reflect(from_reflect = false)]
```

This looks inane, but it's necessary because the default
`#[derive(Reflect)]` macro places `FromReflect` bounds on everything. To
avoid this, we opt out of deriving `FromReflect` with that macro by
adding `#[reflect(from_reflect = false)]`, then separately derive
`FromReflect`. (Of course, the latter still has the `FromReflect`
bounds, which is fine.)
2024-10-07 22:59:17 +00:00
Tim
bef44d7ac2
Stop using Handle<T> as a component in bevy_gizmos (#15713)
# Objective

- Another step towards removing the `Component` impl on `Handle<T>`

## Solution

- Yeet
2024-10-07 22:57:26 +00:00
François Mockers
1869e45c49
fix some of the ease functions from interpolation (#15706)
# Objective

- Followup to #15675
- Some of the functions are wrong, noticed in #15703: `Sine`, `Elastic`
and `Back`

## Solution

- Fix them and make them deterministic


![ease-fixed-functions](https://github.com/user-attachments/assets/8a4d5c0c-36fa-4a49-a189-5b832dc24721)
2024-10-07 19:08:32 +00:00
Tim
d454db8e58
Rename the Pickable component and fix incorrect documentation (#15707)
# Objective

- Rename `Pickable` to `PickingBehavior` to counter the easily-made
assumption that the component is required. It is optional
- Fix and clarify documentation
- The docs in `crates/bevy_ui/src/picking_backend.rs` were incorrect
about the necessity of `Pickable`
- Plus two minor code quality changes in this commit
(7c2e75f48d)

Closes #15632
2024-10-07 17:09:57 +00:00
Clar Fon
8adc9e9d6e
Feature-gate all image formats (#15586)
# Objective

Bevy supports feature gates for each format it supports, but several
formats that it loads via the `image` crate do not have feature gates.
Additionally, the QOI format is supported by the `image` crate and
wasn't available at all. This fixes that.

## Solution

The following feature gates are added:

* `avif`
* `ff` (Farbfeld)
* `gif`
* `ico`
* `qoi`
* `tiff`

None of these formats are enabled by default, despite the fact that all
these formats appeared to be enabled by default before. Since
`default-features` was disabled for the `image` crate, it's likely that
using any of these formats would have errored by default before this
change, although this probably needs additional testing.

## Testing

The changes seemed minimal enough that a compile test would be
sufficient.

## Migration guide

Image formats that previously weren't feature-gated are now
feature-gated, meaning they will have to be enabled if you use them:

* `avif`
* `ff` (Farbfeld)
* `gif`
* `ico`
* `tiff`

Additionally, the `qoi` feature has been added to support loading QOI
format images.

Previously, these formats appeared in the enum by default, but weren't
actually enabled via the `image` crate, potentially resulting in weird
bugs. Now, you should be able to add these features to your projects to
support them properly.
2024-10-07 16:37:45 +00:00
Patrick Walton
0a1d60f3b0
Fix a system ordering issue with motion blur for skinned meshes. (#15693)
Currently, it's possible for the `collect_meshes_for_gpu_building`
system to run after `set_mesh_motion_vector_flags`. This will cause
those motion vector flags to be overwritten, which will cause the shader
to ignore the motion vectors for skinned meshes, which will cause
graphical artifacts.

This patch corrects the issue by forcing `set_mesh_motion_vector_flags`
to run after `collect_meshes_for_gpu_building`.
2024-10-07 16:33:15 +00:00
Gino Valente
8039f34b0d
bevy_ecs: Replace panics in QueryData derive compile errors (#15691)
# Objective

The current `QueryData` derive panics when it encounters an error.
Additionally, it doesn't provide the clearest error message:

```rust
#[derive(QueryData)]
#[query_data(mut)]
struct Foo {
    // ...
}
```

```
error: proc-macro derive panicked
  --> src/foo.rs:16:10
   |
16 | #[derive(QueryData)]
   |          ^^^^^^^^^
   |
   = help: message: Invalid `query_data` attribute format
```

## Solution

Updated the derive logic to not panic and gave a bit more detail in the
error message.

This is makes the error message just a bit clearer and maintains the
correct span:

```
error: invalid attribute, expected `mutable` or `derive`
  --> src/foo.rs:17:14
   |
17 | #[query_data(mut)]
   |              ^^^
```

## Testing

You can test locally by running the following in
`crates/bevy_ecs/compile_fail`:

```
cargo test --target-dir ../../../target
```
2024-10-07 16:30:34 +00:00
Emerson Coskey
d1927736de
Migrate bevy picking (#15690)
# Objective

Migrate `bevy_picking` to the required components API

## Solution
- Made `PointerId` require `PointerLocation`, `PointerPress`, and
`PointerInteraction`
- Removed `PointerBundle`
- Removed all engine uses of `PointerBundle`

- Added convenience constructor `PointerLocation::new(location:
Location)`

## Testing

- ran unit tests
- ran `sprite_picking` example, everything seemed fine.

## Migration Guide

This API hasn't shipped yet, so I didn't bother with a deprecation.
However, for any crates tracking main the changes are as follows:

Previous api:
```rs
commands.insert(PointerBundle::new(PointerId::Mouse));
commands.insert(PointerBundle::new(PointerId::Mouse).with_location(location));
```

New api:
```rs
commands.insert(PointerId::Mouse);
commands.insert((PointerId::Mouse, PointerLocation::new(location)));
```
2024-10-07 16:26:37 +00:00
Trashtalk217
d1bd46d45e
Deprecate get_or_spawn (#15652)
# Objective

After merging retained rendering world #15320, we now have a good way of
creating a link between worlds (*HIYAA intensifies*). This means that
`get_or_spawn` is no longer necessary for that function. Entity should
be opaque as the warning above `get_or_spawn` says. This is also part of
#15459.

I'm deprecating `get_or_spawn_batch` in a different PR in order to keep
the PR small in size.

## Solution

Deprecate `get_or_spawn` and replace it with `get_entity` in most
contexts. If it's possible to query `&RenderEntity`, then the entity is
synced and `render_entity.id()` is initialized in the render world.

## Migration Guide

If you are given an `Entity` and you want to do something with it, use
`Commands.entity(...)` or `World.entity(...)`. If instead you want to
spawn something use `Commands.spawn(...)` or `World.spawn(...)`. If you
are not sure if an entity exists, you can always use `get_entity` and
match on the `Option<...>` that is returned.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-07 16:08:22 +00:00
charlotte
037464800e
Use global clear color for camera driver node. (#15688)
When no cameras are configured, the `ClearColor` resource has no effect
on the default window.

Fixes
https://discord.com/channels/691052431525675048/866787577687310356/1292601838075379796


![image](https://github.com/user-attachments/assets/f42479c0-b239-4660-acd0-daa859b1f815)

![image](https://github.com/user-attachments/assets/4d625960-f105-4a29-91a3-44f4baadac30)
2024-10-07 15:59:51 +00:00
François Mockers
4357539e06
Add most common interpolations (#15675)
# Objective

- Followup for #14788 
- Support most usual ease function

## Solution

- Use the crate
[`interpolation`](https://docs.rs/interpolation/0.3.0/interpolation/trait.Ease.html)
which has them all
- it's already used by bevy_easings, bevy_tweening, be_tween,
bevy_tweening_captured, bevy_enoki, kayak_ui in the Bevy ecosystem for
various easing/tweening/interpolation
2024-10-07 15:56:06 +00:00
Alice Cecile
0a150b0d22
Add more tools for traversing hierarchies (#15627)
# Objective

- Working with hierarchies in Bevy is far too tedious due to a lack of
helper functions.
- This is the first half of #15609. 

## Solution

Extend
[`HierarchyQueryExt`](https://docs.rs/bevy/latest/bevy/hierarchy/trait.HierarchyQueryExt)
with the following methods:

- `parent`
- `children`
- `root_parent`
- `iter_leaves`
- `iter_siblings`
- `iter_descendants_depth_first`

I've opted to make both `iter_leaves` and `iter_siblings` collect the
list of matching Entities for now, rather that operate by reference like
the existing `iter_descendants`. This was simpler, and in the case of
`iter_siblings` especially, the number of matching entities is likely to
be much smaller.

I've kept the generics in the type signature however, so we can go back
and optimize that freely without a breaking change whenever we want.

## Testing

I've added some basic testing, but they're currently failing. If you'd
like to help, I'd welcome suggestions or a PR to my PR over the weekend
<3

---------

Co-authored-by: Viktor Gustavsson <villor94@gmail.com>
Co-authored-by: poopy <gonesbird@gmail.com>
Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
2024-10-07 15:24:57 +00:00
Christian Hughes
584d14808a
Allow World::entity family of functions to take multiple entities and get multiple references back (#15614)
# Objective

Following the pattern established in #15593, we can reduce the API
surface of `World` by providing a single function to grab both a
singular entity reference, or multiple entity references.

## Solution

The following functions can now also take multiple entity IDs and will
return multiple entity references back:
- `World::entity`
- `World::get_entity`
- `World::entity_mut`
- `World::get_entity_mut`
- `DeferredWorld::entity_mut`
- `DeferredWorld::get_entity_mut`

If you pass in X, you receive Y:
- give a single `Entity`, receive a single `EntityRef`/`EntityWorldMut`
(matches current behavior)
- give a `[Entity; N]`/`&[Entity; N]` (array), receive an equally-sized
`[EntityRef; N]`/`[EntityMut; N]`
- give a `&[Entity]` (slice), receive a
`Vec<EntityRef>`/`Vec<EntityMut>`
- give a `&EntityHashSet`, receive a
`EntityHashMap<EntityRef>`/`EntityHashMap<EntityMut>`

Note that `EntityWorldMut` is only returned in the single-entity case,
because having multiple at the same time would lead to UB. Also,
`DeferredWorld` receives an `EntityMut` in the single-entity case
because it does not allow structural access.

## Testing

- Added doc-tests on `World::entity`, `World::entity_mut`, and
`DeferredWorld::entity_mut`
- Added tests for aliased mutability and entity existence

---

## Showcase

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

The APIs for fetching `EntityRef`s and `EntityMut`s from the `World`
have been unified.

```rust
// This code will be referred to by subsequent code blocks.
let world = World::new();
let e1 = world.spawn_empty().id();
let e2 = world.spawn_empty().id();
let e3 = world.spawn_empty().id();
```

Querying for a single entity remains mostly the same:

```rust
// 0.14
let eref: EntityRef = world.entity(e1);
let emut: EntityWorldMut = world.entity_mut(e1);
let eref: Option<EntityRef> = world.get_entity(e1);
let emut: Option<EntityWorldMut> = world.get_entity_mut(e1);

// 0.15
let eref: EntityRef = world.entity(e1);
let emut: EntityWorldMut = world.entity_mut(e1);
let eref: Result<EntityRef, Entity> = world.get_entity(e1);
let emut: Result<EntityWorldMut, Entity> = world.get_entity_mut(e1);
```

Querying for multiple entities with an array has changed:

```rust
// 0.14
let erefs: [EntityRef; 2] = world.many_entities([e1, e2]);
let emuts: [EntityMut; 2] = world.many_entities_mut([e1, e2]);
let erefs: Result<[EntityRef; 2], Entity> = world.get_many_entities([e1, e2]);
let emuts: Result<[EntityMut; 2], QueryEntityError> = world.get_many_entities_mut([e1, e2]);

// 0.15
let erefs: [EntityRef; 2] = world.entity([e1, e2]);
let emuts: [EntityMut; 2] = world.entity_mut([e1, e2]);
let erefs: Result<[EntityRef; 2], Entity> = world.get_entity([e1, e2]);
let emuts: Result<[EntityMut; 2], EntityFetchError> = world.get_entity_mut([e1, e2]);
```

Querying for multiple entities with a slice has changed:

```rust
let ids = vec![e1, e2, e3]);

// 0.14
let erefs: Result<Vec<EntityRef>, Entity> = world.get_many_entities_dynamic(&ids[..]);
let emuts: Result<Vec<EntityMut>, QueryEntityError> = world.get_many_entities_dynamic_mut(&ids[..]);

// 0.15
let erefs: Result<Vec<EntityRef>, Entity> = world.get_entity(&ids[..]);
let emuts: Result<Vec<EntityMut>, EntityFetchError> = world.get_entity_mut(&ids[..]);
let erefs: Vec<EntityRef> = world.entity(&ids[..]); // Newly possible!
let emuts: Vec<EntityMut> = world.entity_mut(&ids[..]); // Newly possible!
```

Querying for multiple entities with an `EntityHashSet` has changed:

```rust
let set = EntityHashSet::from_iter([e1, e2, e3]);

// 0.14
let emuts: Result<Vec<EntityMut>, QueryEntityError> = world.get_many_entities_from_set_mut(&set);

// 0.15
let emuts: Result<EntityHashMap<EntityMut>, EntityFetchError> = world.get_entity_mut(&set);
let erefs: Result<EntityHashMap<EntityRef>, EntityFetchError> = world.get_entity(&set); // Newly possible!
let emuts: EntityHashMap<EntityMut> = world.entity_mut(&set); // Newly possible!
let erefs: EntityHashMap<EntityRef> = world.entity(&set); // Newly possible!
```

</details>

## Migration Guide

- `World::get_entity` now returns `Result<_, Entity>` instead of
`Option<_>`.
- Use `world.get_entity(..).ok()` to return to the previous behavior.
- `World::get_entity_mut` and `DeferredWorld::get_entity_mut` now return
`Result<_, EntityFetchError>` instead of `Option<_>`.
- Use `world.get_entity_mut(..).ok()` to return to the previous
behavior.
- Type inference for `World::entity`, `World::entity_mut`,
`World::get_entity`, `World::get_entity_mut`,
`DeferredWorld::entity_mut`, and `DeferredWorld::get_entity_mut` has
changed, and might now require the input argument's type to be
explicitly written when inside closures.
- The following functions have been deprecated, and should be replaced
as such:
    - `World::many_entities` -> `World::entity::<[Entity; N]>`
    - `World::many_entities_mut` -> `World::entity_mut::<[Entity; N]>`
    - `World::get_many_entities` -> `World::get_entity::<[Entity; N]>`
- `World::get_many_entities_dynamic` -> `World::get_entity::<&[Entity]>`
- `World::get_many_entities_mut` -> `World::get_entity_mut::<[Entity;
N]>`
- The equivalent return type has changed from `Result<_,
QueryEntityError>` to `Result<_, EntityFetchError>`
- `World::get_many_entities_dynamic_mut` ->
`World::get_entity_mut::<&[Entity]>1
- The equivalent return type has changed from `Result<_,
QueryEntityError>` to `Result<_, EntityFetchError>`
- `World::get_many_entities_from_set_mut` ->
`World::get_entity_mut::<&EntityHashSet>`
- The equivalent return type has changed from `Result<Vec<EntityMut>,
QueryEntityError>` to `Result<EntityHashMap<EntityMut>,
EntityFetchError>`. If necessary, you can still convert the
`EntityHashMap` into a `Vec`.
2024-10-07 15:21:40 +00:00
Ida "Iyes
31409ebc61
Add Image methods for easy access to a pixel's color (#10392)
# Objective

If you want to draw / generate images from the CPU, such as:
 - to create procedurally-generated assets
- for games whose artstyle is best implemented by poking pixels directly
from the CPU, instead of using shaders

It is currently very unergonomic to do in Bevy, because you have to deal
with the raw bytes inside `image.data`, take care of the pixel format,
etc.

## Solution

This PR adds some helper methods to `Image` for pixel manipulation.
These methods allow you to use Bevy's user-friendly `Color` struct to
read and write the colors of pixels, at arbitrary coordinates (specified
as `UVec3` to support any texture dimension). They handle
encoding/decoding to the `Image`s `TextureFormat`, incl. any sRGB
conversion.

While we are at it, also add methods to help with direct access to the
raw bytes. It is now easy to compute the offset where the bytes of a
specific pixel coordinate are found, or to just get a Rust slice to
access them.

Caveat: `Color` roundtrips are obviously going to be lossy for non-float
`TextureFormat`s. Using `set_color_at` followed by `get_color_at` will
return a different value, due to the data conversions involved (such as
`f32` -> `u8` -> `f32` for the common `Rgba8UnormSrgb` texture format).
Be careful when comparing colors (such as checking for a color you wrote
before)!

Also adding a new example: `cpu_draw` (under `2d`), to showcase these
new APIs.

---

## Changelog

### Added

 - `Image` APIs for easy access to the colors of specific pixels.

---------

Co-authored-by: Pascal Hertleif <killercup@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: ltdk <usr@ltdk.xyz>
2024-10-07 14:38:41 +00:00
dependabot[bot]
aa56d4831a
Update sysinfo requirement from 0.31.0 to 0.32.0 (#15697)
Updates the requirements on
[sysinfo](https://github.com/GuillaumeGomez/sysinfo) to permit the
latest version.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md">sysinfo's
changelog</a>.</em></p>
<blockquote>
<h1>0.32.0</h1>
<ul>
<li>Add new <code>Disk::is_read_only</code> API.</li>
<li>Add new <code>remove_dead_processes</code> argument to
<code>System::refresh_processes</code> and
<code>System::refresh_processes_specifics</code>.</li>
<li>macOS: Fix memory leak in disk refresh.</li>
</ul>
<h1>0.31.4</h1>
<ul>
<li>macOS: Force memory cleanup in disk list retrieval.</li>
</ul>
<h1>0.31.3</h1>
<ul>
<li>Raspberry Pi: Fix temperature retrieval.</li>
</ul>
<h1>0.31.2</h1>
<ul>
<li>Remove <code>bstr</code> dependency (needed for rustc
development).</li>
</ul>
<h1>0.31.1</h1>
<ul>
<li>Downgrade version of <code>memchr</code> (needed for rustc
development).</li>
</ul>
<h1>0.31.0</h1>
<ul>
<li>Split crate in features to only enable what you need.</li>
<li>Remove <code>System::refresh_process</code>,
<code>System::refresh_process_specifics</code> and
<code>System::refresh_pids</code>
methods.</li>
<li>Add new argument of type <code>ProcessesToUpdate</code> to
<code>System::refresh_processes</code> and
<code>System::refresh_processes_specifics</code> methods.</li>
<li>Add new <code>NetworkData::ip_networks</code> method.</li>
<li>Add new <code>System::refresh_cpu_list</code> method.</li>
<li>Global CPU now only contains CPU usage.</li>
<li>Rename <code>TermalSensorType</code> to
<code>ThermalSensorType</code>.</li>
<li>Process names is now an <code>OsString</code>.</li>
<li>Remove <code>System::global_cpu_info</code>.</li>
<li>Add <code>System::global_cpu_usage</code>.</li>
<li>macOS: Fix invalid CPU computation when single processes are
refreshed one after the other.</li>
<li>Windows: Fix virtual memory computation.</li>
<li>Windows: Fix WoW64 parent process refresh.</li>
<li>Linux: Retrieve RSS (Resident Set Size) memory for cgroups.</li>
</ul>
<h1>0.30.13</h1>
<ul>
<li>macOS: Fix segfault when calling
<code>Components::refresh_list</code> multiple times.</li>
<li>Windows: Fix CPU arch retrieval.</li>
</ul>
<h1>0.30.12</h1>
<ul>
<li>FreeBSD: Fix network interfaces retrieval (one was always
missing).</li>
</ul>
<h1>0.30.11</h1>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e022ae4fd1"><code>e022ae4</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1354">#1354</a>
from GuillaumeGomez/update</li>
<li><a
href="0c5ca6af60"><code>0c5ca6a</code></a>
Update migration guide for 0.32</li>
<li><a
href="9f14cba660"><code>9f14cba</code></a>
Update crate version to 0.32.0</li>
<li><a
href="eb7f147b27"><code>eb7f147</code></a>
Update CHANGELOG for 0.32.0</li>
<li><a
href="9c86e253dd"><code>9c86e25</code></a>
Fix new clippy lints</li>
<li><a
href="2fb2903272"><code>2fb2903</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1353">#1353</a>
from GuillaumeGomez/rm-dead-processes</li>
<li><a
href="7452b8d828"><code>7452b8d</code></a>
Update <code>System::refresh_processes</code> API to give control over
when to remove de...</li>
<li><a
href="6f1d382276"><code>6f1d382</code></a>
Merge pull request <a
href="https://redirect.github.com/GuillaumeGomez/sysinfo/issues/1348">#1348</a>
from kevinbaker/master</li>
<li><a
href="6d5ea97ade"><code>6d5ea97</code></a>
add dependency on windows SystemServices for disk</li>
<li><a
href="1c87f50f1c"><code>1c87f50</code></a>
win: add correct location of FILE_READ_ONLY_VOLUME, correct call</li>
<li>Additional commits viewable in <a
href="https://github.com/GuillaumeGomez/sysinfo/compare/v0.31.0...v0.32.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 07:31:17 +00:00
Matty
d3657a04cd
Fixes to animation graph evaluation (#15689)
# Objective

Fix a couple of substantial errors found during the development of
#15665:
- `AnimationCurveEvaluator::add` was secretly unreachable. In other
words, additive blending never actually occurred.
- Weights from the animation graph nodes were ignored, and only
`ActiveAnimation`'s weights were used.

## Solution

Made additive blending reachable and included the graph node weight in
the weight of the stack elements appended in the curve application loop
of `animate_targets`.

## Testing

Tested on existing examples and on the new example added in #15665.
2024-10-07 07:30:00 +00:00
Liam Gallagher
d016e52843
Spelling (#15686)
Fix two spelling mistakes
2024-10-07 00:10:04 +00:00
poopy
b4ffb7ab7d
Don't trigger animation events when paused 2 (#15682)
# Objective

I completely forgot that animation events are triggered in two separate
systems (sorry). The issue ~~fixed~~ by #15677, can still happen if the
animation event is not targeting a specific bone.

## Solution

_Realy_ don't trigger animation events for paused animations.
2024-10-06 20:16:39 +00:00
Chang Guo
e7c1c997ac
simplify adding headers and improve consistency for RemoteHttpPlugin (#15680)
# Objective

- a follow up pr for #15651 

## Solution

- rename add to insert cuz insert make more sense when using a HashMap
and new value overrides previous value based on key (quote:
https://github.com/bevyengine/bevy/pull/15651#discussion_r1788851778)
- use `TryInto<>` for add(insert) as well when constructing `Headers`.
Doing so user won't need to interact with hyper APIs, and `with_headers`
will align better with `with_header` (quote:
https://github.com/bevyengine/bevy/pull/15651#discussion_r1788687251)
- move example usage of Headers to `with_headers` method (quote:
https://github.com/bevyengine/bevy/pull/15651#discussion_r1788989500)

## Testing

- the same as I tested my previous pr
2024-10-06 19:06:19 +00:00
Willem
5a0bd23106
Add scene summary (#15679)
# Objective

-- Fixes #14361
2024-10-06 19:03:56 +00:00
poopy
70269ef758
Don't trigger animation events when paused (#15677)
# Objective

Pausing the `animated_fox` example perfectly as one of the feet hits the
ground causes the event to be triggered every frame.

Context: #15538

## Solution

Don't trigger animation events if the animation is paused.

## Testing

Ran the example, I no longer see the issue.
2024-10-06 18:57:07 +00:00
Bude
6edb78a8c3
Inverse bevy_render bevy_winit dependency and move cursor to bevy_winit (#15649)
# Objective

- `bevy_render` should not depend on `bevy_winit`
- Fixes #15565

## Solution

- `bevy_render` no longer depends on `bevy_winit`
- The following is behind the `custom_cursor` feature
- Move custom cursor code from `bevy_render` to `bevy_winit` behind the
`custom_cursor` feature
- `bevy_winit` now depends on `bevy_render` (for `Image` and
`TextureFormat`)
- `bevy_winit` now depends on `bevy_asset` (for `Assets`, `Handle` and
`AssetId`)
  - `bevy_winit` now depends on `bytemuck` (already in tree)
- Custom cursor code in `bevy_winit` reworked to use `AssetId` (other
than that it is taken over 1:1)
- Rework `bevy_winit` custom cursor interface visibility now that the
logic is all contained in `bevy_winit`

## Testing

- I ran the screenshot and window_settings examples
- Tested on linux wayland so far

---

## Migration Guide

`CursorIcon` and `CustomCursor` previously provided by
`bevy::render::view::cursor` is now available from `bevy::winit`.
A new feature `custom_cursor` enables this functionality (default
feature).
2024-10-06 18:25:50 +00:00
vero
4a23dc4216
Split out bevy_mesh from bevy_render (#15666)
# Objective

- bevy_render is gargantuan

## Solution

- Split out bevy_mesh

## Testing

- Ran some examples, everything looks fine

## Migration Guide

`bevy_render::mesh::morph::inherit_weights` is now
`bevy_render::mesh::inherit_weights`

if you were using `Mesh::compute_aabb`, you will need to `use
bevy_render::mesh::MeshAabb;` now

---------

Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
2024-10-06 14:18:11 +00:00
Chang Guo
7c4a0683c7
Add with_headers() method to RemoteHttpPlugin (#15651)
# Objective

- fulfill the needs presented in this issue, which requires the ability
to set custom HTTP headers for responses in the Bevy Remote Protocol
server. #15551

## Solution

- Created a `Headers` struct to store custom HTTP headers as key-value
pairs.
- Added a `headers` field to the `RemoteHttpPlugin` struct.
- Implemented a `with_headers` method in `RemoteHttpPlugin` to allow
users to set custom headers.
- Passed the headers into the processing chain.

## Testing

- I added cors_headers in example/remote/server.rs and tested it with a
static html
[file](https://github.com/spacemen0/bevy/blob/test_file/test.html)

---
2024-10-06 13:21:21 +00:00
poopy
d9190e4ff6
Add Support for Triggering Events via AnimationEvents (#15538)
# Objective

Add support for events that can be triggered from animation clips. This
is useful when you need something to happen at a specific time in an
animation. For example, playing a sound every time a characters feet
hits the ground when walking.

Closes #15494 

## Solution

Added a new field to `AnimationClip`: `events`, which contains a list of
`AnimationEvent`s. These are automatically triggered in
`animate_targets` and `trigger_untargeted_animation_events`.

## Testing

Added a couple of tests and example (`animation_events.rs`) to make sure
events are triggered when expected.

---

## Showcase

`Events` need to also implement `AnimationEvent` and `Reflect` to be
used with animations.

```rust
#[derive(Event, AnimationEvent, Reflect)]
struct SomeEvent;
```

Events can be added to an `AnimationClip` by specifying a time and
event.

```rust
// trigger an event after 1.0 second
animation_clip.add_event(1.0, SomeEvent);
```

And optionally, providing a target id.

```rust
let id = AnimationTargetId::from_iter(["shoulder", "arm", "hand"]);
animation_clip.add_event_to_target(id, 1.0, HandEvent);
```

I modified the `animated_fox` example to show off the feature.

![CleanShot 2024-10-05 at 02 41
57](https://github.com/user-attachments/assets/0bb47db7-24f9-4504-88f1-40e375b89b1b)

---------

Co-authored-by: Matty <weatherleymatthew@gmail.com>
Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-10-06 10:03:05 +00:00
Vlady Veselinov
856cab56f9
Fix wrong link in error (#15672)
Hi y'all, I got an error that leads to a wrong link:
https://bevyengine.org/learn/errors/#b0002

It should be: https://bevyengine.org/learn/errors/b0002


![image](https://github.com/user-attachments/assets/863ae8cd-6a3b-4830-b125-2944a211a737)
2024-10-06 08:14:50 +00:00
Tom Frantz
0305f2edc0
Fix doc comment (#15673)
# Objective

I noticed a weird break in a doc comment, I assume it must be a typo.

## Solution

Put the missing doc comment in there.

## Testing

It looks better in my IDE now
2024-10-06 08:12:58 +00:00
UkoeHB
0b5a360585
Fix text measurement when multiple font sizes are present (#15669)
# Objective

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

## Solution

- Add up line heights to get text block height instead of using
`Metrics`, which only records the largest line height.

## Testing

- [x] Fixed issue shown in https://github.com/bevyengine/bevy/pull/15622
2024-10-05 22:46:37 +00:00
Matty
42e0771633
Fix additive blending of quaternions (#15662)
# Objective

Fixes #13832

## Solution

Additively blend quaternions like this:
```rust
rotation = Quat::slerp(Quat::IDENTITY, incoming_rotation, weight) * rotation;
```

## Testing

Ran `animation_masks`, which behaves the same as before. (In the context
of an animation being blended only onto the base pose, there is no
difference.)

We should create some examples that actually exercise more of the
capabilities of the `AnimationGraph` so that issues like this can become
more visible in general. (On the other hand, I'm quite certain this was
wrong before.)

## Migration Guide

This PR changes the implementation of `Quat: Animatable`, which was not
used internally by Bevy prior to this release version. If you relied on
the old behavior of additive quaternion blending in manual applications,
that code will have to be updated, as the old behavior was incorrect.
2024-10-05 20:03:10 +00:00
Joona Aalto
25bfa80e60
Migrate cameras to required components (#15641)
# Objective

Yet another PR for migrating stuff to required components. This time,
cameras!

## Solution

As per the [selected
proposal](https://hackmd.io/tsYID4CGRiWxzsgawzxG_g#Combined-Proposal-1-Selected),
deprecate `Camera2dBundle` and `Camera3dBundle` in favor of `Camera2d`
and `Camera3d`.

Adding a `Camera` without `Camera2d` or `Camera3d` now logs a warning,
as suggested by Cart [on
Discord](https://discord.com/channels/691052431525675048/1264881140007702558/1291506402832945273).
I would personally like cameras to work a bit differently and be split
into a few more components, to avoid some footguns and confusing
semantics, but that is more controversial, and shouldn't block this core
migration.

## Testing

I ran a few 2D and 3D examples, and tried cameras with and without
render graphs.

---

## Migration Guide

`Camera2dBundle` and `Camera3dBundle` have been deprecated in favor of
`Camera2d` and `Camera3d`. Inserting them will now also insert the other
components required by them automatically.
2024-10-05 01:59:52 +00:00
m-edlund
ac9b0c848c
fix: corrected projection calculation of camera sub view (#15646)
# Objective

- Fixes #15600

## Solution

- The projection calculations did not use the aspect ratio of
`full_size`, this was amended

## Testing

- I created a test example on [this
fork](https://github.com/m-edlund/bevy/tree/bug/main/subViewProjectionBroken)
to allow testing with different aspect ratios and offsets
- The sub view is bound to a view port that can move across the screen.
The image in the moving sub view should "match" the full image exactly

## Showcase

Current version:


https://github.com/user-attachments/assets/17ad1213-d5ae-4181-89c1-81146edede7d

Fixed version:


https://github.com/user-attachments/assets/398e0927-e1dd-4880-897d-8157aa4398e6
2024-10-05 01:36:47 +00:00
urben1680
2e89e98931
Deprecate Events::oldest_id (#15658)
# Objective

Fixes #15617 

## Solution

The original author confirmed it was not intentional that both these
methods exist.

They do the same, one has the better implementation and the other the
better name.

## Testing

I just ran the unit tests of the module.

---

## Migration Guide

- Change usages of `Events::oldest_id` to `Events::oldest_event_count`
- If `Events::oldest_id` was used to get the actual oldest
`EventId::id`, note that the deprecated method never reliably did that
in the first place as the buffers may contain no id currently.
2024-10-05 01:35:44 +00:00
Kristoffer Søholm
ddd4b4daf8
Fix deferred rendering (#15656)
# Objective

Fixes #15525

The deferred and mesh pipelines tonemapping LUT bindings were
accidentally out of sync, breaking deferred rendering.

As noted in the issue it's still broken on wasm due to hitting a texture
limit.

## Solution

Add constants for these instead of hardcoding them.

## Testing

Test with `cargo run --example deferred_rendering` and see it works, run
the same on main and see it crash.
2024-10-04 22:51:23 +00:00
Patrick Walton
0094bcbc07
Implement additive blending for animation graphs. (#15631)
*Additive blending* is an ubiquitous feature in game engines that allows
animations to be concatenated instead of blended. The canonical use case
is to allow a character to hold a weapon while performing arbitrary
poses. For example, if you had a character that needed to be able to
walk or run while attacking with a weapon, the typical workflow is to
have an additive blend node that combines walking and running animation
clips with an animation clip of one of the limbs performing a weapon
attack animation.

This commit adds support for additive blending to Bevy. It builds on top
of the flexible infrastructure in #15589 and introduces a new type of
node, the *add node*. Like blend nodes, add nodes combine the animations
of their children according to their weights. Unlike blend nodes,
however, add nodes don't normalize the weights to 1.0.

The `animation_masks` example has been overhauled to demonstrate the use
of additive blending in combination with masks. There are now controls
to choose an animation clip for every limb of the fox individually.

This patch also fixes a bug whereby masks were incorrectly accumulated
with `insert()` during the graph threading phase, which could cause
corruption of computed masks in some cases.

Note that the `clip` field has been replaced with an `AnimationNodeType`
enum, which breaks `animgraph.ron` files. The `Fox.animgraph.ron` asset
has been updated to the new format.

Closes #14395.

## Showcase


https://github.com/user-attachments/assets/52dfe05f-fdb3-477a-9462-ec150f93df33

## Migration Guide

* The `animgraph.ron` format has changed to accommodate the new
*additive blending* feature. You'll need to change `clip` fields to
instances of the new `AnimationNodeType` enum.
2024-10-04 22:13:22 +00:00
vero
7eadc1d467
Zero Copy Mesh (#15569)
# Objective

- Another step towards #15558

## Solution

- Instead of allocating a Vec and then having wgpu copy it into a
staging buffer, write directly into the staging buffer.
- gets rid of another hidden copy, in `pad_to_alignment`.

future work:
- why is there a gcd implementation in here (and its subpar, use
binary_gcd. its in the hot path, run twice for every mesh, every frame i
think?) make it better and put it in bevy_math
- zero-copy custom mesh api to avoid having to write out a Mesh from a
custom rep

## Testing

- lighting and many_cubes run fine (and slightly faster. havent
benchmarked though)

---

## Showcase

- look ma... no copies

at least when RenderAssetUsage is GPU only :3

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-10-04 21:24:44 +00:00
vero
8b0388c74a
Split off bevy_image from bevy_render (#15650)
# Objective

- bevy_render is gargantuan

## Solution

- Split off bevy_image

## Testing

- Ran some examples
2024-10-04 20:16:47 +00:00
Zachary Harrold
53adcd7667
Minor fixes for bevy_utils in no_std (#15463)
# Objective

- Contributes to #15460

## Solution

- Made `web-time` a `wasm32`-only dependency.
- Moved time-related exports to its own module for clarity.
- Feature-gated allocator requirements for `hashbrown` behind `alloc`.
- Enabled compile-time RNG for `ahash` (runtime RNG will preferentially
used in `std` environments)
- Made `thread_local` optional by feature-gating the `Parallel` type.

## Testing

- Ran CI locally.
- `cargo build -p bevy_utils --target "x86_64-unknown-none"
--no-default-features`
2024-10-04 19:25:49 +00:00
robtfm
e72b9625d7
drop info locks in single threaded (#15522)
# Objective

addresses half of issue #15508
avoid asset server deadlock when `multi_threaded` feature is not
enabled.

## Solution

drop the locks in the single-threaded case.

the lock is still held with the `multi-threaded` feature enabled to
avoid re-locking to insert the load task. i guess this might possibly
cause issues on single-core machines ... is that something we should
worry about?

---------

Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: Emerson Coskey <56370779+ecoskey@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Tim <JustTheCoolDude@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: s-puig <39652109+s-puig@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Liam Gallagher <liam@liamgallagher.dev>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
Co-authored-by: charlotte <charlotte.c.mcelwain@gmail.com>
Co-authored-by: akimakinai <105044389+akimakinai@users.noreply.github.com>
Co-authored-by: Antony <antony.m.3012@gmail.com>
Co-authored-by: JohnTheCoolingFan <43478602+JohnTheCoolingFan@users.noreply.github.com>
Co-authored-by: hshrimp <182684536+hooded-shrimp@users.noreply.github.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: Dokkae <90514461+Dokkae6949@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Co-authored-by: Sou1gh0st <xiuyutong1994@163.com>
Co-authored-by: Robert Walter <26892280+RobWalt@users.noreply.github.com>
Co-authored-by: eckz <567737+eckz@users.noreply.github.com>
Co-authored-by: Matty <2975848+mweatherley@users.noreply.github.com>
Co-authored-by: IQuick 143 <IQuick143cz@gmail.com>
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
Co-authored-by: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Co-authored-by: andriyDev <andriydzikh@gmail.com>
Co-authored-by: TheBigCheese <32036861+13ros27@users.noreply.github.com>
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: Josh Robson Chase <josh@robsonchase.com>
Co-authored-by: Erik Živković <erik@zivkovic.se>
Co-authored-by: ChosenName <69129796+ChosenName@users.noreply.github.com>
Co-authored-by: mgi388 <135186256+mgi388@users.noreply.github.com>
Co-authored-by: SpecificProtagonist <specificprotagonist@posteo.org>
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Gabriel Bourgeois <gabriel.bourgeoisv4si@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
Co-authored-by: Trashtalk217 <trashtalk217@gmail.com>
Co-authored-by: re0312 <re0312@outlook.com>
Co-authored-by: re0312 <45868716+re0312@users.noreply.github.com>
Co-authored-by: Periwink <charlesbour@gmail.com>
Co-authored-by: Anselmo Sampietro <ans.samp@gmail.com>
Co-authored-by: rudderbucky <anandkwork7@gmail.com>
Co-authored-by: aecsocket <43144841+aecsocket@users.noreply.github.com>
Co-authored-by: Andreas <34456840+nilsiker@users.noreply.github.com>
Co-authored-by: Ludwig DUBOS <ludwig.dubos@pm.me>
Co-authored-by: Ensar Sarajčić <dev@ensarsarajcic.com>
Co-authored-by: Kanabenki <lucien.menassol@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: m-edlund <me@fwegmann.com>
Co-authored-by: vero <rodol@rivalrebels.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
Co-authored-by: Litttle_fish <38809254+Litttlefish@users.noreply.github.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Rich Churcher <rich.churcher@gmail.com>
Co-authored-by: Viktor Gustavsson <villor94@gmail.com>
Co-authored-by: Dragoș Tiselice <dragostiselice@gmail.com>
Co-authored-by: Miles Silberling-Cook <NthTensor@users.noreply.github.com>
Co-authored-by: notmd <33456881+notmd@users.noreply.github.com>
Co-authored-by: Matt Tracy <matt.r.tracy@gmail.com>
Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
Co-authored-by: rewin <rewin1996@gmail.com>
Co-authored-by: a.yamaev <a.yamaev@smartengines.com>
Co-authored-by: fluffiac <f@ggot.wtf>
2024-10-04 12:28:57 +00:00
vero
2530f262f5
Remove bevy_animation dependency on bevy_text (#15642)
# Objective

- Fixes #15640

## Solution

- Do it

## Testing

- ran many_foxes
2024-10-04 12:22:15 +00:00
vero
0b9a461d5d
Invert the dependency between bevy_animation and bevy_ui (#15634)
# Objective

- Improve crate dependency graph

## Solution

- Invert a dependency

## Testing

- Tested ui and animation examples
2024-10-04 01:27:20 +00:00
Joona Aalto
61e11ea440
Fix audio not playing (#15638)
# Objective

Someone (let's not name names here) might've been a bit of a goofball,
and happened to forget that "playing audio" should cause this thing
called "sound" to be emitted! That someone might not have realized that
queries should be updated to account for audio using wrapper components
instead of raw asset handles after #15573.

## Solution

Update systems, and listen to the relaxing soundscapes of `Windless
Slopes.ogg` 🎵
2024-10-04 01:07:09 +00:00
Liam Gallagher
26808745cf
Fix bevy_window and bevy_winit readme badges (#15637)
## Objective

Fix the badges for `bevy_window` and `bevy_winit`.

## Solution

Replace the placeholder `bevy_name` wit the correct crate name.
2024-10-04 00:38:49 +00:00
fluffiac
f0704cffa4
Allow a closure to be used as a required component default (#15269)
# Objective

Allow required component default values to be provided in-line.

```rust
#[derive(Component)]
#[require(
    FocusPolicy(block_focus_policy)
)]
struct SomeComponent;

fn block_focus_policy() -> FocusPolicy {
    FocusPolicy::Block
}
```

May now be expressed as:

```rust
#[derive(Component)]
#[require(
    FocusPolicy(|| FocusPolicy::Block)
)]
struct SomeComponent;
```

## Solution

Modified the #[require] proc macro to accept a closure. 

## Testing

Tested using my branch as a dependency, and switching between the inline
closure syntax and function syntax for a bunch of different components.
2024-10-04 00:34:39 +00:00
Tim
20dbf790a6
Get rid of unnecessary mutable access in ui picking backend (#15630)
## Solution

Yeet

## Testing

Tested the `simple_picking` example
2024-10-03 21:30:52 +00:00
rewin
8bf5d99d86
Add method to remove component and all required components for removed component (#15026)
## Objective
The new Required Components feature (#14791) in Bevy allows spawning a
fixed set of components with a single method with cool require macro.
However, there's currently no corresponding method to remove all those
components together. This makes it challenging to keep insertion and
removal code in sync, especially for simple using cases.
```rust
#[derive(Component)]
#[require(Y)]
struct X;

#[derive(Component, Default)]
struct Y;

world.entity_mut(e).insert(X); // Spawns both X and Y
world.entity_mut(e).remove::<X>(); 
world.entity_mut(e).remove::<Y>(); // We need to manually remove dependencies without any sync with the `require` macro
```
## Solution
Simplifies component management by providing operations for removal
required components.
This PR introduces simple 'footgun' methods to removes all components of
this bundle and its required components.

Two new methods are introduced:
For Commands:
```rust
commands.entity(e).remove_with_requires::<B>();
```
For World:
```rust
world.entity_mut(e).remove_with_requires::<B>();
```

For performance I created new field in Bundels struct. This new field
"contributed_bundle_ids" contains cached ids for dynamic bundles
constructed from bundle_info.cintributed_components()

## Testing
The PR includes three test cases:

1. Removing a single component with requirements using World.
2. Removing a bundle with requirements using World.
3. Removing a single component with requirements using Commands.
4. Removing a single component with **runtime** requirements using
Commands

These tests ensure the feature works as expected across different
scenarios.

## Showcase
Example:
```rust
use bevy_ecs::prelude::*;

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

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

#[derive(Component, Default)]
struct Z;

#[derive(Component)]
struct W;

let mut world = World::new();

// Spawn an entity with X, Y, Z, and W components
let entity = world.spawn((X, W)).id();

assert!(world.entity(entity).contains::<X>());
assert!(world.entity(entity).contains::<Y>());
assert!(world.entity(entity).contains::<Z>());
assert!(world.entity(entity).contains::<W>());

// Remove X and required components Y, Z
world.entity_mut(entity).remove_with_requires::<X>();

assert!(!world.entity(entity).contains::<X>());
assert!(!world.entity(entity).contains::<Y>());
assert!(!world.entity(entity).contains::<Z>());

assert!(world.entity(entity).contains::<W>());
```

## Motivation for PR
#15580 

## Performance

I made simple benchmark
```rust
let mut world = World::default();
let entity = world.spawn_empty().id();

let steps = 100_000_000;

let start = std::time::Instant::now();
for _ in 0..steps {
    world.entity_mut(entity).insert(X);
    world.entity_mut(entity).remove::<(X, Y, Z, W)>();
}
let end = std::time::Instant::now();
println!("normal remove: {:?} ", (end - start).as_secs_f32());
println!("one remove: {:?} micros", (end - start).as_secs_f64() / steps as f64 * 1_000_000.0);

let start = std::time::Instant::now();
for _ in 0..steps {
    world.entity_mut(entity).insert(X);
    world.entity_mut(entity).remove_with_requires::<X>();
}
let end = std::time::Instant::now();
println!("remove_with_requires: {:?} ", (end - start).as_secs_f32());
println!("one remove_with_requires: {:?} micros", (end - start).as_secs_f64() / steps as f64 * 1_000_000.0);
```

Output:

CPU: Amd Ryzen 7 2700x

```bash
normal remove: 17.36135 
one remove: 0.17361348299999999 micros
remove_with_requires: 17.534006 
one remove_with_requires: 0.17534005400000002 micros
```

NOTE: I didn't find any tests or mechanism in the repository to update
BundleInfo after creating new runtime requirements with an existing
BundleInfo. So this PR also does not contain such logic.

## Future work (outside this PR)

Create cache system for fast removing components in "safe" mode, where
"safe" mode is remove only required components that will be no longer
required after removing root component.

---------

Co-authored-by: a.yamaev <a.yamaev@smartengines.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-03 20:35:08 +00:00
IceSentry
0628255c45
send_events is ambiguous_with_all (#15629)
# Objective

> Alice 🌹 — Today at 3:43 PM
bevy_dev_tools::ci_testing::systems::send_events
This system should be marked as ambiguous with everything I think

## Solution

- Mark it as `ambiguous_with_all`
2024-10-03 20:02:52 +00:00
Matty
528ca4f95e
Eliminate redundant clamping from sample-interpolated curves (#15620)
# Objective

Currently, sample-interpolated curves (such as those used by the glTF
loader for animations) do unnecessary extra work when `sample_clamped`
is called, since their implementations of `sample_unchecked` are already
clamped. Eliminating this redundant sampling is a small, easy
performance win which doesn't compromise on the animation system's
internal usage of `sample_clamped`, which guarantees that it never
samples curves out-of-bounds.

## Solution

For sample-interpolated curves, define `sample_clamped` in the way
`sample_unchecked` is currently defined, and then redirect
`sample_unchecked` to `sample_clamped`. This is arguably a more
idiomatic way of using the `cores` as well, which is nice.

## Testing

Ran `many_foxes` to make sure I didn't break anything.
2024-10-03 18:26:41 +00:00
Chris Russell
46180a75f8
System param for dynamic resources (#15189)
# Objective

Support accessing dynamic resources in a dynamic system, including
accessing them by component id. This is similar to how dynamic
components can be queried using `Query<FilteredEntityMut>`.

## Solution

Create `FilteredResources` and `FilteredResourcesMut` types that act
similar to `FilteredEntityRef` and `FilteredEntityMut` and that can be
used as system parameters.

## Example

```rust
// Use `FilteredResourcesParamBuilder` to declare access to resources.
let system = (FilteredResourcesParamBuilder::new(|builder| {
    builder.add_read::<B>().add_read::<C>();
}),)
    .build_state(&mut world)
    .build_system(resource_system);

world.init_resource::<A>();
world.init_resource::<C>();

fn resource_system(res: FilteredResources) {
    // The resource exists, but we have no access, so we can't read it.
    assert!(res.get::<A>().is_none());
    // The resource doesn't exist, so we can't read it.
    assert!(res.get::<B>().is_none());
    // The resource exists and we have access, so we can read it.
    let c = res.get::<C>().unwrap();
    // The type parameter can be left out if it can be determined from use.
    let c: Res<C> = res.get().unwrap();
}
```

## Future Work

As a follow-up PR, `ReflectResource` can be modified to take `impl
Into<FilteredResources>`, similar to how `ReflectComponent` takes `impl
Into<FilteredEntityRef>`. That will allow dynamic resources to be
accessed using reflection.
2024-10-03 18:20:34 +00:00
ickshonpe
1e61092604
Fix extract_text2d_sprite entity leak (#15625)
# Objective

`extract_2d_sprite` still uses `spawn_empty()`, replace with
`spawn(TemporaryRenderEntity)` .
2024-10-03 18:15:36 +00:00
ickshonpe
9bb27e97c5
Fix entity leak in extract_uinode_borders (#15626)
# Objective

Fix for another leak, this time when extracting outlines.
2024-10-03 18:15:32 +00:00
Kristoffer Søholm
336c23c1aa
Rename observe to observe_entity on EntityWorldMut (#15616)
# Objective

The current observers have some unfortunate footguns where you can end
up confused about what is actually being observed. For apps you can
chain observe like `app.observe(..).observe(..)` which works like you
would expect, but if you try the same with world the first `observe()`
will return the `EntityWorldMut` for the created observer, and the
second `observe()` will only observe on the observer entity. It took
several hours for multiple people on discord to figure this out, which
is not a great experience.

## Solution

Rename `observe` on entities to `observe_entity`. It's slightly more
verbose when you know you have an entity, but it feels right to me that
observers for specific things have more specific naming, and it prevents
this issue completely.

Another possible solution would be to unify `observe` on `App` and
`World` to have the same kind of return type, but I'm not sure exactly
what that would look like.

## Testing

Simple name change, so only concern is docs really.

---


## Migration Guide

The `observe()` method on entities has been renamed to
`observe_entity()` to prevent confusion about what is being observed in
some cases.
2024-10-03 17:05:26 +00:00
rudderbucky
2da8d17a44
Add try_despawn methods to World/Commands (#15480)
# Objective

Fixes #14511.

`despawn` allows you to remove entities from the world. However, if the
entity does not exist, it emits a warning. This may not be intended
behavior for many users who have use cases where they need to call
`despawn` regardless of if the entity actually exists (see the issue),
or don't care in general if the entity already doesn't exist.

(Also trying to gauge interest on if this feature makes sense, I'd
personally love to have it, but I could see arguments that this might be
a footgun. Just trying to help here 😄 If there's no contention I could
also implement this for `despawn_recursive` and `despawn_descendants` in
the same PR)

## Solution

Add `try_despawn`, `try_despawn_recursive` and
`try_despawn_descendants`.

Modify `World::despawn_with_caller` to also take in a `warn` boolean
argument, which is then considered when logging the warning. Set
`log_warning` to `true` in the case of `despawn`, and `false` in the
case of `try_despawn`.

## Testing

Ran `cargo run -p ci` on macOS, it seemed fine.
2024-10-03 16:21:05 +00:00
MiniaczQ
acea4e7e6f
Better warnings about invalid parameters (#15500)
# Objective

System param validation warnings should be configurable and default to
"warn once" (per system).

Fixes: #15391

## Solution

`SystemMeta` is given a new `ParamWarnPolicy` field.
The policy decides whether warnings will be emitted by each system param
when it fails validation.
The policy is updated by the system after param validation fails.

Example warning:
```
2024-09-30T18:10:04.740749Z  WARN bevy_ecs::system::function_system: System fallible_params::do_nothing_fail_validation will not run because it requested inaccessible system parameter Single<(), (With<Player>, With<Enemy>)>
```

Currently, only the first invalid parameter is displayed.

Warnings can be disabled on function systems using
`.param_never_warn()`.
(there is also `.with_param_warn_policy(policy)`)

## Testing

Ran `fallible_params` example.

---------

Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
2024-10-03 13:16:55 +00:00
Patrick Walton
ca8dd06146
Impose a more sensible ordering for animation graph evaluation. (#15589)
This is an updated version of #15530. Review comments were addressed.

This commit changes the animation graph evaluation to be operate in a
more sensible order and updates the semantics of blend nodes to conform
to [the animation composition RFC]. Prior to this patch, a node graph
like this:

```
	    ┌─────┐
	    │     │
	    │  1  │
	    │     │
	    └──┬──┘
	       │
       ┌───────┴───────┐
       │               │
       ▼               ▼
    ┌─────┐         ┌─────┐
    │     │         │     │
    │  2  │         │  3  │
    │     │         │     │
    └──┬──┘         └──┬──┘
       │               │
   ┌───┴───┐       ┌───┴───┐
   │       │       │       │
   ▼       ▼       ▼       ▼
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│     │ │     │ │     │ │     │
│  4  │ │  6  │ │  5  │ │  7  │
│     │ │     │ │     │ │     │
└─────┘ └─────┘ └─────┘ └─────┘
```

Would be evaluated as (((4 ⊕ 5) ⊕ 6) ⊕ 7), with the blend (lerp/slerp)
operation notated as ⊕. As quaternion multiplication isn't commutative,
this is very counterintuitive and will especially lead to trouble with
the forthcoming additive blending feature (#15198).

This patch fixes the issue by changing the evaluation order to
postorder, with children of a node evaluated in ascending order by node
index.

To do so, this patch revamps `AnimationCurve` to be based on an
*evaluation stack* and a *blend register*. During target evaluation, the
graph evaluator traverses the graph in postorder. When encountering a
clip node, the evaluator pushes the possibly-interpolated value onto the
evaluation stack. When encountering a blend node, the evaluator pops
values off the stack into the blend register, accumulating weights as
appropriate. When the graph is completely evaluated, the top element on
the stack is *committed* to the property of the component.

A new system, the *graph threading* system, is added in order to cache
the sorted postorder traversal to avoid the overhead of sorting children
at animation evaluation time. Mask evaluation has been moved to this
system so that the graph only has to be traversed at most once per
frame. Unlike the `ActiveAnimation` list, the *threaded graph* is cached
from frame to frame and only has to be regenerated when the animation
graph asset changes.

This patch currently regresses the `animate_target` performance in
`many_foxes` by around 50%, resulting in an FPS loss of about 2-3 FPS.
I'd argue that this is an acceptable price to pay for a much more
intuitive system. In the future, we can mitigate the regression with a
fast path that avoids consulting the graph if only one animation is
playing. However, in the interest of keeping this patch simple, I didn't
do so here.

[the animation composition RFC]:
https://github.com/bevyengine/rfcs/blob/main/rfcs/51-animation-composition.md

# Objective

- Describe the objective or issue this PR addresses.
- If you're fixing a specific issue, say "Fixes #X".

## Solution

- Describe the solution used to achieve the objective above.

## Testing

- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

---

## Showcase

> This section is optional. If this PR does not include a visual change
or does not add a new feature, you can delete this section.

- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR adds a new feature or public API, consider adding a brief
pseudo-code snippet of it in action
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
  - If you want, you could even include a before/after comparison!
- If the Migration Guide adequately covers the changes, you can delete
this section

While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:

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

```rust
println!("My super cool code.");
```

</details>

## Migration Guide

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

- If this PR is a breaking change (relative to the last release of
Bevy), describe how a user might need to migrate their code to support
these changes
- Simply adding new functionality is not a breaking change.
- Fixing behavior that was definitely a bug, rather than a questionable
design choice is not a breaking change.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-03 00:36:42 +00:00
IceSentry
67744bb011
Use circle gizmos for capsule (#15602)
# Objective

- The capsule gizmo uses straight lines for the upper and lower circle
which looks pretty ugly.

## Solution

- Use the circle gizmo instead

---

## Showcase

**BEFORE**

![3d_gizmos_sy3CmKUvKO](https://github.com/user-attachments/assets/be014de4-751e-4b40-b814-b5b97bb72031)

**AFTER**

![3d_gizmos_nyADBAUJHg](https://github.com/user-attachments/assets/539ff765-f9d8-4afe-9ac6-41fe83e94e94)

(the circles are red for demonstration purposes only)

# Notes

I also tried using 3d arcs instead of circles but it looks like arcs
need a lot more computation for an almost identical end result. Circles
seem much simpler. The only thing I'm unsure about is if the rotation
stuff is correct. It worked in my testing though.
2024-10-02 19:47:56 +00:00
Matt Tracy
8fb55dbf59
Implement SystemParam::queue() method for blanket implementation of ParamSet (#15599)
# Objective

The `queue()` method is an optional trait method which is necessary for
deferred operations (such as command queues) to work properly in the
context of an observer.

This method was omitted from the proc_macro blanket implementation of
`ParamSet` for tuples; as a result, SystemParams with deferred
application (such as Commands) would not work in observers if they were
part of a ParamSet.

This appears to have been a simple omission, as `queue()` was already
implemented for the separate blanket implementation of `ParamSet` for
`Vec<T>`. In both cases, it is a simple pass-through to the component
SystemParams.

## Solution

Add the `queue()` method implementation to the `impl_param_set` proco
macro.

## Testing

Added a unit test which clearly demonstrates the issue. It fails before
the fix, and passes afterwards.

---
2024-10-02 19:46:50 +00:00
Matty
587a508ef9
Remove TransformCurve (#15598)
# Objective

It is somewhat unlikely we will actually be able to support
`TransformCurve` (introduced in #15434) after the `AnimationGraph`
evaluation order changes in the immediate future. This is because
correctly blending overlapping animation properties is nontrivial, and
`Transform` overlaps with all of its own fields. We could still
potentially create something like this in the future, but it's likely to
require significant design and implementation work. By way of contrast,
the single-property wrappers `TranslationCurve`, `ScaleCurve`, and
`RotationCurve` should work perfectly fine, since they are
non-overlapping.

In this version release, creating `TransformCurve` in userspace is also
quite easy if desired (see the deletions from this PR).

## Solution

Delete `TransformCurve`. 

## Migration Guide

There is no released version that contains this, but we should make sure
that `TransformCurve` is excluded from the release notes for #15434 if
we merge this pull request.
2024-10-02 19:46:38 +00:00
notmd
453c0167b2
Allow access a method handler (#15601)
# Objective

- I'm building a streaming plugin for `bevy_remote` and accessing to
builtin method will be very valuable

## Solution

- Add a method to allow access a handler by method name.

## Testing

- CI should pass
2024-10-02 19:45:18 +00:00
Christian Hughes
7c6057bc69
Enable EntityRef::get_by_id and friends to take multiple ids and get multiple pointers back (#15593)
# Objective

- Closes #15577 

## Solution

The following functions can now also take multiple component IDs and
return multiple pointers back:
- `EntityRef::get_by_id`
- `EntityMut::get_by_id`
- `EntityMut::into_borrow_by_id`
- `EntityMut::get_mut_by_id`
- `EntityMut::into_mut_by_id`
- `EntityWorldMut::get_by_id`
- `EntityWorldMut::into_borrow_by_id`
- `EntityWorldMut::get_mut_by_id`
- `EntityWorldMut::into_mut_by_id`

If you pass in X, you receive Y:
- give a single `ComponentId`, receive a single `Ptr`/`MutUntyped`
- give a `[ComponentId; N]` (array), receive a `[Ptr; N]`/`[MutUntyped;
N]`
- give a `&[ComponentId; N]` (array), receive a `[Ptr; N]`/`[MutUntyped;
N]`
- give a `&[ComponentId]` (slice), receive a
`Vec<Ptr>`/`Vec<MutUntyped>`
- give a `&HashSet<ComponentId>`, receive a `HashMap<ComponentId,
Ptr>`/`HashMap<ComponentId, MutUntyped>`

## Testing

- Added 4 new tests.

---

## Migration Guide

- The following functions now return an `Result<_,
EntityComponentError>` instead of a `Option<_>`: `EntityRef::get_by_id`,
`EntityMut::get_by_id`, `EntityMut::into_borrow_by_id`,
`EntityMut::get_mut_by_id`, `EntityMut::into_mut_by_id`,
`EntityWorldMut::get_by_id`, `EntityWorldMut::into_borrow_by_id`,
`EntityWorldMut::get_mut_by_id`, `EntityWorldMut::into_mut_by_id`
2024-10-02 19:02:20 +00:00
Robert Walter
59db6f9cca
add curve utilities to create curves interpolating/easing between two values (#14788)
# Objective

Citing @mweatherley 

> There is a lot of shortfall for simple cases— e.g., we should have
library functions for making a curve connecting two points, eased
versions of that, and so on.

## Solution

This PR implements

- a simple `Easing` trait which is implemented for all `impl Curve<f32>`
types. We can't really guarantee that these curves have unit interval
domain, which some people would probably expect, but it is documented
that this isn't the case for these types and we redirect to
`EasingCurve` which is used for that purpose
- an `EasingCurve` struct, which is used to interpolate between two
values `start` and `end` using a `impl Easing` curve where the curve
will be guaranteed to be reparametrized
- a `LinearCurve` which linearly interpolates between two values `start`
and `end`
- a `CubicBezierCurve` which interpolates between `start` and `end`
values using a `CubicSegment`
- a `StepCurve` which interpolates between `start` and `end` with an
step-function with `n` steps
- an `ElasticCurve` which interpolates between `start` and `end` with
spring like behavior where the elasticity of the spring is configurable
- some `FunctionCurve` easing curves for different popular functions
including: `quadratic_ease_in`, `quadratic_ease_out`, `smoothstep`,
`identity`

## Testing

- there are a few new tests for all of these in the main module

---------

Co-authored-by: eckz <567737+eckz@users.noreply.github.com>
Co-authored-by: Miles Silberling-Cook <NthTensor@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-10-02 14:29:05 +00:00
Dragoș Tiselice
ba7907cae7
Added visibility bitmask as an alternative SSAO method (#13454)
Early implementation. I still have to fix the documentation and consider
writing a small migration guide.

Questions left to answer:

* [x] should thickness be an overridable constant?
* [x] is there a better way to implement `Eq`/`Hash` for `SSAOMethod`?
* [x] do we want to keep the linear sampler for the depth texture?
* [x] is there a better way to separate the logic than preprocessor
macros?


![vbao](https://github.com/bevyengine/bevy/assets/4136413/2a8a0389-2add-4c2e-be37-e208e52dcd25)

## Migration guide

SSAO algorithm was changed from GTAO to VBAO (visibility bitmasks). A
new field, `constant_object_thickness`, was added to
`ScreenSpaceAmbientOcclusion`. `ScreenSpaceAmbientOcclusion` also lost
its `Eq` and `Hash` implementations.

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2024-10-02 13:43:35 +00:00
Benjamin Brienen
c841dd92a1
Documentation for variadics (#15387)
# Objective

Relevant: #15208

## Solution

I went ahead and added the variadics documentation in all applicable
locations.

## Testing

- I built the documentation and inspected it to see whether the feature
is there.
2024-10-02 12:48:36 +00:00
Tim
461305b3d7
Revert "Have EntityCommands methods consume self for easier chaining" (#15523)
As discussed in #15521

- Partial revert of #14897, reverting the change to the methods to
consume `self`
- The `insert_if` method is kept

The migration guide of #14897 should be removed
Closes #15521

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-02 12:47:26 +00:00
François Mockers
23b0dd6ffd
move ANDROID_APP to bevy_window (#15585)
# Objective

- Remove dependency in bevy_asset to bevy_winit
- First step for #15565 

## Solution

- the static `ANDROID_APP` and the `android_activity` reexport are now
in `bevy_window`

## Migration Guide

If you use the `android_activity` reexport from
`bevy::winit::android_activity`, it is now in
`bevy:🪟:android_activity`. Same for the `ANDROID_APP` static
2024-10-02 03:01:06 +00:00
Liam Gallagher
85dfd72631
Include errors along side successful components in BRP bevy/get method (#15516)
## Objective

I am using BRP for a web inspector. To get components from a entity is
first do a `bevy/list` on the specific entity and then use the result in
a `bevy/get` request. The problem with this is `bevy/list` returns all
components even if they aren't reflect-able (which is what I expect) but
when I then do a `bevy/get` request even if all bar one of the
components are reflect-able the request will fail.

## Solution

Update the `bevy/get` response to include a map of components like it
did for successful request and a map of errors. This means if one or
more components are not present on the entity or cannot be reflected it
will not fail the entire request.

I also only did `bevy/get` as I don't think any of the other methods
would benefit from this.

## Testing

I tested this with my inspector and with a http client and it worked as
expected.

---------

Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
2024-10-02 02:26:01 +00:00
Gino Valente
eaa37f3b45
bevy_reflect: Add DeserializeWithRegistry and SerializeWithRegistry (#8611)
# Objective

### The Problem

Currently, the reflection deserializers give little control to users for
how a type is deserialized. The most control a user can have is to
register `ReflectDeserialize`, which will use a type's `Deserialize`
implementation.

However, there are times when a type may require slightly more control.

For example, let's say we want to make Bevy's `Mesh` easier to
deserialize via reflection (assume `Mesh` actually implemented
`Reflect`). Since we want this to be extensible, we'll make it so users
can use their own types so long as they satisfy `Into<Mesh>`. The end
result should allow users to define a RON file like:

```rust
{
  "my_game::meshes::Sphere": (
    radius: 2.5
  )
}
```

### The Current Solution

Since we don't know the types ahead of time, we'll need to use
reflection. Luckily, we can access type information dynamically via the
type registry. Let's make a custom type data struct that users can
register on their types:

```rust
pub struct ReflectIntoMesh {
  // ...
}

impl<T: FromReflect + Into<Mesh>> FromType<T> for ReflectIntoMesh {
  fn from_type() -> Self {
    // ...
  }
}
```

Now we'll need a way to use this type data during deserialization.
Unfortunately, we can't use `Deserialize` since we need access to the
registry. This is where `DeserializeSeed` comes in handy:

```rust
pub struct MeshDeserializer<'a> {
  pub registry: &'a TypeRegistry
}

impl<'a, 'de> DeserializeSeed<'de> for MeshDeserializer<'a> {
  type Value = Mesh;

  fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
  where
    D: serde::Deserializer<'de>,
  {
    struct MeshVisitor<'a> {
      registry: &'a TypeRegistry
    }

    impl<'a, 'de> Visitor<'de> for MeshVisitor<'a> {
      fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
        write!(formatter, "map containing mesh information")
      }

      fn visit_map<A>(self, mut map: A) -> Result<Self::Value, serde:🇩🇪:Error> where A: MapAccess<'de> {
        // Parse the type name
        let type_name = map.next_key::<String>()?.unwrap();

        // Deserialize the value based on the type name
        let registration = self.registry
          .get_with_name(&type_name)
          .expect("should be registered");
        let value = map.next_value_seed(TypedReflectDeserializer {
          registration,
          registry: self.registry,
        })?;

        // Convert the deserialized value into a `Mesh`
        let into_mesh = registration.data::<ReflectIntoMesh>().unwrap();
        Ok(into_mesh.into(value))
      }
    }
  }
}
```

### The Problem with the Current Solution

The solution above works great when all we need to do is deserialize
`Mesh` directly. But now, we want to be able to deserialize a struct
like this:

```rust
struct Fireball {
  damage: f32,
  mesh: Mesh,
}
```

This might look simple enough and should theoretically be no problem for
the reflection deserializer to handle, but this is where our
`MeshDeserializer` solution starts to break down.

In order to use `MeshDeserializer`, we need to have access to the
registry. The reflection deserializers have access to that, but we have
no way of borrowing it for our own deserialization since they have no
way of knowing about `MeshDeserializer`.

This means we need to implement _another_ `DeserializeSeed`— this time
for `Fireball`!
And if we decided to put `Fireball` inside another type, well now we
need one for that type as well.

As you can see, this solution does not scale well and results in a lot
of unnecessary boilerplate for the user.

## Solution

> [!note]
> This PR originally only included the addition of
`DeserializeWithRegistry`. Since then, a corresponding
`SerializeWithRegistry` trait has also been added. The reasoning and
usage is pretty much the same as the former so I didn't bother to update
the full PR description.

Created the `DeserializeWithRegistry` trait and
`ReflectDeserializeWithRegistry` type data.

The `DeserializeWithRegistry` trait works like a standard `Deserialize`
but provides access to the registry. And by registering the
`ReflectDeserializeWithRegistry` type data, the reflection deserializers
will automatically use the `DeserializeWithRegistry` implementation,
just like it does for `Deserialize`.

All we need to do is make the following changes:

```diff
#[derive(Reflect)]
+ #[reflect(DeserializeWithRegistry)]
struct Mesh {
  // ...
}

- impl<'a, 'de> DeserializeSeed<'de> for MeshDeserializer<'a> {
-   type Value = Mesh;
-   fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ impl<'de> DeserializeWithRegistry<'de> for Mesh {
+   fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
    where
      D: serde::Deserializer<'de>,
    {
      // ...
    }
}
```

Now, any time the reflection deserializer comes across `Mesh`, it will
opt to use its `DeserializeWithRegistry` implementation. And this means
we no longer need to create a whole slew of `DeserializeSeed` types just
to deserialize `Mesh`.

### Why not a trait like `DeserializeSeed`?

While this would allow for anyone to define a deserializer for `Mesh`,
the problem is that it means __anyone can define a deserializer for
`Mesh`.__ This has the unfortunate consequence that users can never be
certain that their registration of `ReflectDeserializeSeed` is the one
that will actually be used.

We could consider adding something like that in the future, but I think
this PR's solution is much safer and follows the example set by
`ReflectDeserialize`.

### What if we made the `TypeRegistry` globally available?

This is one potential solution and has been discussed before (#6101).
However, that change is much more controversial and comes with its own
set of disadvantages (can't have multiple registries such as with
multiple worlds, likely some added performance cost with each access,
etc.).

### Followup Work

Once this PR is merged, we should consider merging `ReflectDeserialize`
into `DeserializeWithRegistry`. ~~There is already a blanket
implementation to make this transition generally pretty
straightforward.~~ The blanket implementations were removed for the sake
of this PR and will need to be re-added in the followup. I would propose
that we first mark `ReflectDeserialize` as deprecated, though, before we
outright remove it in a future release.

---

## Changelog

- Added the `DeserializeReflect` trait and `ReflectDeserializeReflect`
type data
- Added the `SerializeReflect` trait and `ReflectSerializeReflect` type
data
- Added `TypedReflectDeserializer::of` convenience constructor

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: aecsocket <43144841+aecsocket@users.noreply.github.com>
2024-10-02 01:54:32 +00:00
Viktor Gustavsson
f86ee32576
Add UI GhostNode (#15341)
# Objective

- Fixes #14826 
- For context, see #15238

## Solution
Add a `GhostNode` component to `bevy_ui` and update all the relevant
systems to use it to traverse for UI children.

- [x] `ghost_hierarchy` module
  - [x] Add `GhostNode`
- [x] Add `UiRootNodes` system param for iterating (ghost-aware) UI root
nodes
- [x] Add `UiChildren` system param for iterating (ghost-aware) UI
children
- [x] Update `layout::ui_layout_system`
  - [x] Use ghost-aware root nodes for camera updates
  - [x] Update and remove children in taffy
    - [x] Initial spawn
    - [x] Detect changes on nested UI children
- [x] Use ghost-aware children traversal in
`update_uinode_geometry_recursive`
- [x] Update the rest of the UI systems to use the ghost hierarchy
  - [x] `stack::ui_stack_system`
  - [x] `update::`
    - [x] `update_clipping_system`
    - [x] `update_target_camera_system`
  - [x] `accessibility::calc_name`

## Testing
- [x] Added a new example `ghost_nodes` that can be used as a testbed.
- [x] Added unit tests for _some_ of the traversal utilities in
`ghost_hierarchy`
- [x] Ensure this fulfills the needs for currently known use cases
  - [x] Reactivity libraries (test with `bevy_reactor`)
- [ ] Text spans (mentioned by koe [on
discord](https://discord.com/channels/691052431525675048/1285371432460881991/1285377442998915246))
  
---
## Performance
[See comment
below](https://github.com/bevyengine/bevy/pull/15341#issuecomment-2385456820)

## Migration guide
Any code that previously relied on `Parent`/`Children` to iterate UI
children may now want to use `bevy_ui::UiChildren` to ensure ghost nodes
are skipped, and their first descendant Nodes included.

UI root nodes may now be children of ghost nodes, which means
`Without<Parent>` might not query all root nodes. Use
`bevy_ui::UiRootNodes` where needed to iterate root nodes instead.

## Potential future work
- Benchmarking/optimizations of hierarchies containing lots of ghost
nodes
- Further exploration of UI hierarchies and markers for root nodes/leaf
nodes to create better ergonomics for things like `UiLayer` (world-space
ui)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
2024-10-02 00:24:28 +00:00
UkoeHB
3df281ba7b
Refactor TextPipeline::update_buffer to accept an interator (#15581)
# Objective

- Prepare `TextPipeline` to work with multi-entity text blocks. See
https://github.com/bevyengine/bevy/discussions/15014

## Solution

- Refactor `TextPipeline::update_buffer` to accept an iterator instead
of slice. Adjust `update_buffer` implementation to only iterate spans
once instead of three times (which would require iterating a hierarchy
three times with multi-entity blocks).

## Testing

- Tested with `text_debug` example.
2024-10-01 23:44:59 +00:00
Liam Gallagher
d6cfafdfd4
Make SystemIdMarker reflect-able (#15556)
Make `SystemIdMarker` reflect-able.
2024-10-01 22:46:44 +00:00
Joona Aalto
22af24aacf
Migrate motion blur, TAA, SSAO, and SSR to required components (#15572)
# Objective

Again, a step forward in the migration to required components: a bunch
of camera rendering cormponents!

Note that this does not include the camera components themselves yet,
because the naming and API for `Camera` hasn't been fully decided yet.

## Solution

As per the [selected
proposals](https://hackmd.io/@bevy/required_components/%2FpiqD9GOdSFKZZGzzh3C7Uw):

- Deprecate `MotionBlurBundle` in favor of the `MotionBlur` component
- Deprecate `TemporalAntiAliasBundle` in favor of the
`TemporalAntiAliasing` component
- Deprecate `ScreenSpaceAmbientOcclusionBundle` in favor of the
`ScreenSpaceAmbientOcclusion` component
- Deprecate `ScreenSpaceReflectionsBundle` in favor of the
`ScreenSpaceReflections` component

---

## Migration Guide

`MotionBlurBundle`, `TemporalAntiAliasBundle`,
`ScreenSpaceAmbientOcclusionBundle`, and `ScreenSpaceReflectionsBundle`
have been deprecated in favor of the `MotionBlur`,
`TemporalAntiAliasing`, `ScreenSpaceAmbientOcclusion`, and
`ScreenSpaceReflections` components instead. Inserting them will now
also insert the other components required by them automatically.
2024-10-01 22:45:31 +00:00
Joona Aalto
ed151e756c
Migrate audio to required components (#15573)
# Objective

What's that? Another PR for the grand migration to required components?
This time, audio!

## Solution

Deprecate `AudioSourceBundle`, `AudioBundle`, and `PitchBundle`, as per
the [chosen
proposal](https://hackmd.io/@bevy/required_components/%2Fzxgp-zMMRUCdT7LY1ZDQwQ).

However, we cannot call the component `AudioSource`, because that's what
the stored asset is called. I deliberated on a few names, like
`AudioHandle`, or even just `Audio`, but landed on `AudioPlayer`, since
it's probably the most accurate and "nice" name for this. Open to
alternatives though.

---

## Migration Guide

Replace all insertions of `AudioSoucreBundle`, `AudioBundle`, and
`PitchBundle` with the `AudioPlayer` component. The other components
required by it will now be inserted automatically.

In cases where the generics cannot be inferred, you may need to specify
them explicitly. For example:

```rust
commands.spawn(AudioPlayer::<AudioSource>(asset_server.load("sounds/sick_beats.ogg")));
```
2024-10-01 22:43:29 +00:00
Tim
eb51b4c28e
Migrate scenes to required components (#15579)
# Objective

A step in the migration to required components: scenes!

## Solution

As per the [selected
proposal](https://hackmd.io/@bevy/required_components/%2FPJtNGVMMQhyM0zIvCJSkbA):
- Deprecate `SceneBundle` and `DynamicSceneBundle`.
- Add `SceneRoot` and `DynamicSceneRoot` components, which wrap a
`Handle<Scene>` and `Handle<DynamicScene>` respectively.

## Migration Guide
Asset handles for scenes and dynamic scenes must now be wrapped in the
`SceneRoot` and `DynamicSceneRoot` components. Raw handles as components
no longer spawn scenes.

Additionally, `SceneBundle` and `DynamicSceneBundle` have been
deprecated. Instead, use the scene components directly.

Previously:
```rust
let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf"));

commands.spawn(SceneBundle {
    scene: model_scene,
    transform: Transform::from_xyz(-4.0, 0.0, -3.0),
    ..default()
});
```
Now:
```rust
let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf"));

commands.spawn((
    SceneRoot(model_scene),
    Transform::from_xyz(-4.0, 0.0, -3.0),
));
```
2024-10-01 22:42:11 +00:00
UkoeHB
ead84e0e3d
Rename BreakLineOn to LineBreak (#15583)
# Objective

- Improve code quality in preparation for
https://github.com/bevyengine/bevy/discussions/15014

## Solution

- Rename BreakLineOn to LineBreak.

## Migration Guide

`BreakLineOn` was renamed to `LineBreak`, and paramters named
`linebreak_behavior` were renamed to `linebreak`.
2024-10-01 22:30:50 +00:00
Litttle_fish
e924df0e1a
Add features to switch NativeActivity and GameActivity usage (#12095)
# Objective

Add two features to switch bevy to use `NativeActivity` or
`GameActivity` on Android, use `GameActivity` by default.

Also close  #12058 and probably #12026 .

## Solution

Add two features to the corresponding crates so you can toggle it, like
what `winit` and `android-activity` crate did.

---

## Changelog

Removed default `NativeActivity` feature implementation for Android,
added two new features to enable `NativeActivity` and `GameActivity`,
and use `GameActivity` by default.

## Migration Guide

Because `cargo-apk` is not compatible with `GameActivity`,
building/running using `cargo apk build/run -p bevy_mobile_example` is
no longer possible.
Users should follow the new workflow described in document.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Rich Churcher <rich.churcher@gmail.com>
2024-10-01 22:23:48 +00:00
ickshonpe
f53af2846c
Update the UI texture slice pipeline to work with the retained render world changes (#15578)
# Objective

Update the UI's texture slice extraction to work with the changes from
the retained render world PR (#15320).
2024-10-01 22:02:02 +00:00
Joona Aalto
54006b107b
Migrate meshes and materials to required components (#15524)
# Objective

A big step in the migration to required components: meshes and
materials!

## Solution

As per the [selected
proposal](https://hackmd.io/@bevy/required_components/%2Fj9-PnF-2QKK0on1KQ29UWQ):

- Deprecate `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle`.
- Add `Mesh2d` and `Mesh3d` components, which wrap a `Handle<Mesh>`.
- Add `MeshMaterial2d<M: Material2d>` and `MeshMaterial3d<M: Material>`,
which wrap a `Handle<M>`.
- Meshes *without* a mesh material should be rendered with a default
material. The existence of a material is determined by
`HasMaterial2d`/`HasMaterial3d`, which is required by
`MeshMaterial2d`/`MeshMaterial3d`. This gets around problems with the
generics.

Previously:

```rust
commands.spawn(MaterialMesh2dBundle {
    mesh: meshes.add(Circle::new(100.0)).into(),
    material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
    transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
    ..default()
});
```

Now:

```rust
commands.spawn((
    Mesh2d(meshes.add(Circle::new(100.0))),
    MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
    Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```

If the mesh material is missing, previously nothing was rendered. Now,
it renders a white default `ColorMaterial` in 2D and a
`StandardMaterial` in 3D (this can be overridden). Below, only every
other entity has a material:

![Näyttökuva 2024-09-29
181746](https://github.com/user-attachments/assets/5c8be029-d2fe-4b8c-ae89-17a72ff82c9a)

![Näyttökuva 2024-09-29
181918](https://github.com/user-attachments/assets/58adbc55-5a1e-4c7d-a2c7-ed456227b909)

Why white? This is still open for discussion, but I think white makes
sense for a *default* material, while *invalid* asset handles pointing
to nothing should have something like a pink material to indicate that
something is broken (I don't handle that in this PR yet). This is kind
of a mix of Godot and Unity: Godot just renders a white material for
non-existent materials, while Unity renders nothing when no materials
exist, but renders pink for invalid materials. I can also change the
default material to pink if that is preferable though.

## Testing

I ran some 2D and 3D examples to test if anything changed visually. I
have not tested all examples or features yet however. If anyone wants to
test more extensively, it would be appreciated!

## Implementation Notes

- The relationship between `bevy_render` and `bevy_pbr` is weird here.
`bevy_render` needs `Mesh3d` for its own systems, but `bevy_pbr` has all
of the material logic, and `bevy_render` doesn't depend on it. I feel
like the two crates should be refactored in some way, but I think that's
out of scope for this PR.
- I didn't migrate meshlets to required components yet. That can
probably be done in a follow-up, as this is already a huge PR.
- It is becoming increasingly clear to me that we really, *really* want
to disallow raw asset handles as components. They caused me a *ton* of
headache here already, and it took me a long time to find every place
that queried for them or inserted them directly on entities, since there
were no compiler errors for it. If we don't remove the `Component`
derive, I expect raw asset handles to be a *huge* footgun for users as
we transition to wrapper components, especially as handles as components
have been the norm so far. I personally consider this to be a blocker
for 0.15: we need to migrate to wrapper components for asset handles
everywhere, and remove the `Component` derive. Also see
https://github.com/bevyengine/bevy/issues/14124.

---

## Migration Guide

Asset handles for meshes and mesh materials must now be wrapped in the
`Mesh2d` and `MeshMaterial2d` or `Mesh3d` and `MeshMaterial3d`
components for 2D and 3D respectively. Raw handles as components no
longer render meshes.

Additionally, `MaterialMesh2dBundle`, `MaterialMeshBundle`, and
`PbrBundle` have been deprecated. Instead, use the mesh and material
components directly.

Previously:

```rust
commands.spawn(MaterialMesh2dBundle {
    mesh: meshes.add(Circle::new(100.0)).into(),
    material: materials.add(Color::srgb(7.5, 0.0, 7.5)),
    transform: Transform::from_translation(Vec3::new(-200., 0., 0.)),
    ..default()
});
```

Now:

```rust
commands.spawn((
    Mesh2d(meshes.add(Circle::new(100.0))),
    MeshMaterial2d(materials.add(Color::srgb(7.5, 0.0, 7.5))),
    Transform::from_translation(Vec3::new(-200., 0., 0.)),
));
```

If the mesh material is missing, a white default material is now used.
Previously, nothing was rendered if the material was missing.

The `WithMesh2d` and `WithMesh3d` query filter type aliases have also
been removed. Simply use `With<Mesh2d>` or `With<Mesh3d>`.

---------

Co-authored-by: Tim Blackbird <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-01 21:33:17 +00:00
Joona Aalto
0fe17b8b30
Migrate fog volumes to required components (#15568)
# Objective

Another part of the migration to required components: fog volumes!

## Solution

Deprecate `FogVolumeBundle` and make `FogVolume` require `Transform` and
`Visibility`, as per the [chosen
proposal](https://hackmd.io/@bevy/required_components/%2FcO7JPSAQR5G0J_j5wNwtOQ).

---

## Migration Guide

Replace all insertions of `FogVolumeBundle` with the `Visibility`
component. The other components required by it will now be inserted
automatically.
2024-10-01 19:51:22 +00:00
Josh Robson Chase
40e88dceff
Change ReflectMapEntities to operate on components before insertion (#15422)
Previous PR https://github.com/bevyengine/bevy/pull/14549 was closed in
error and couldn't be reopened since I had updated the branch
😿

# Objective

Fixes #14465

## Solution

`ReflectMapEntities` now works similarly to `MapEntities` in that it
works on the reflected value itself rather than the component in the
world after insertion. This makes it so that observers see the remapped
entities on insertion rather than the entity IDs from the scene.

`ReflectMapEntities` now works for both components and resources, so we
only need the one.

## Testing

* New unit test for `Observer`s + `DynamicScene`s
* New unit test for `Observer`s + `Scene`s
* Open to suggestions for other tests!

---

## Migration Guide

- Consumers of `ReflectMapEntities` will need to call `map_entities` on
values prior to inserting them into the world.
- Implementors of `MapEntities` will need to remove the `mappings`
method, which is no longer needed for `ReflectMapEntities` and has been
removed from the trait.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
2024-10-01 18:34:09 +00:00
vero
6465e3bd9f
Fix Mesh allocator bug and reduce Mesh data copies by two (#15566)
# Objective

- First step towards #15558

## Solution

- Rename `get_vertex_buffer_data` to `create_packed_vertex_buffer_data`
to make it clear that it is not "free" and actually allocates
- Compute length analytically for preallocation instead of creating the
buffer to get its length and immediately discard it
- Use existing vertex attribute size calculation method to reduce code
duplication
- Fix a bug where mesh index data was being replaced by unnecessarily
newly created mesh vertex data in some cases
- Overall reduces mesh copies by two. We still have plenty to go, but
these were the easy ones.

## Testing

- I ran 3d_scene, lighting, and many_cubes, they look fine.
- Benchmarks would be nice, but this is very obviously a win in perf and
correctness.

---

## Migration Guide

- `Mesh::create_packed_vertex_buffer_data` has been renamed
`Mesh::create_packed_vertex_buffer_data` to reflect the fact that it
copies data and allocates.

## Showcase

- look mom, less copies
2024-10-01 17:15:57 +00:00
aecsocket
1df8238e8d
bevy_asset: Improve NestedLoader API (#15509)
# Objective

The `NestedLoader` API as it stands right now is somewhat lacking:

- It consists of several types `NestedLoader`, `UntypedNestedLoader`,
`DirectNestedLoader`, and `UntypedDirectNestedLoader`, where a typestate
pattern on `NestedLoader` would be make it more obvious what it does,
and allow centralising the documentation
- The term "untyped" in the asset loader code is overloaded. It can mean
either:
- we have literally no idea what the type of this asset will be when we
load it (I dub this "unknown type")
- we know what type of asset it will be, but we don't know it statically
- we only have a TypeId (I dub this "dynamic type" / "erased")
- There is no way to get an `UntypedHandle` (erased) given a `TypeId`

## Solution

Changes `NestedLoader` into a type-state pattern, adding two type
params:
- `T` determines the typing
- `StaticTyped`, the default, where you pass in `A` statically into `fn
load<A>() -> ..`
- `DynamicTyped`, where you give a `TypeId`, giving you a
`UntypedHandle`
- `UnknownTyped`, where you have literally no idea what type of asset
you're loading, giving you a `Handle<LoadedUntypedAsset>`
- `M` determines the "mode" (bikeshedding TBD, I couldn't come up with a
better name)
- `Deferred`, the default, won't load the asset when you call `load`,
but it does give you a `Handle` to it (this is nice since it can be a
sync fn)
- `Immediate` will load the asset as soon as you call it, and give you
access to it, but you must be in an async context to call it

Changes some naming of internals in `AssetServer` to fit the new
definitions of "dynamic type" and "unknown type". Note that I didn't do
a full pass over this code to keep the diff small. That can probably be
done in a new PR - I think the definiton I laid out of unknown type vs.
erased makes it pretty clear where each one applies.

<details>
<summary>Old issue</summary>

The only real problem I have with this PR is the requirement to pass in
`type_name` (from `core::any::type_name`) into Erased. Users might not
have that type name, only the ID, and it just seems sort of weird to
*have* to give an asset type name. However, the reason we need it is
because of this:
```rs
    pub(crate) fn get_or_create_path_handle_erased(
        &mut self,
        path: AssetPath<'static>,
        type_id: TypeId,
        type_name: &str,
        loading_mode: HandleLoadingMode,
        meta_transform: Option<MetaTransform>,
    ) -> (UntypedHandle, bool) {
        let result = self.get_or_create_path_handle_internal(
            path,
            Some(type_id),
            loading_mode,
            meta_transform,
        );
        // it is ok to unwrap because TypeId was specified above
        unwrap_with_context(result, type_name).unwrap()
    }

pub(crate) fn unwrap_with_context<T>(
    result: Result<T, GetOrCreateHandleInternalError>,
    type_name: &str,
) -> Option<T> {
    match result {
        Ok(value) => Some(value),
        Err(GetOrCreateHandleInternalError::HandleMissingButTypeIdNotSpecified) => None,
        Err(GetOrCreateHandleInternalError::MissingHandleProviderError(_)) => {
            panic!("Cannot allocate an Asset Handle of type '{type_name}' because the asset type has not been initialized. \
                    Make sure you have called app.init_asset::<{type_name}>()")
        }
    }
}
```
This `unwrap_with_context` is literally the only reason we need the
`type_name`. Potentially, this can be turned into an `impl
Into<Option<&str>>`, and output a different error message if the type
name is missing. Since if we are loading an asset where we only know the
type ID, by definition we can't output that error message, since we
don't have the type name. I'm open to suggestions on this.

</details>

## Testing

Not sure how to test this, since I kept most of the actual NestedLoader
logic the same. The only new API is loading an `UntypedHandle` when in
the `DynamicTyped, Immediate` state.

## Migration Guide

Code which uses `bevy_asset`'s `LoadContext::loader` / `NestedLoader`
will see some naming changes:
- `untyped` is replaced by `with_unknown_type`
- `with_asset_type` is replaced by `with_static_type`
- `with_asset_type_id` is replaced by `with_dynamic_type`
- `direct` is replaced by `immediate` (the opposite of "immediate" is
"deferred")
2024-10-01 14:14:04 +00:00
m-edlund
c323db02e0
Add sub_camera_view, enabling sheared projection (#15537)
# Objective

- This PR fixes #12488

## Solution

- This PR adds a new property to `Camera` that emulates the
functionality of the
[setViewOffset()](https://threejs.org/docs/#api/en/cameras/PerspectiveCamera.setViewOffset)
API in three.js.
- When set, the perspective and orthographic projections will restrict
the visible area of the camera to a part of the view frustum defined by
`offset` and `size`.

## Testing

- In the new `camera_sub_view` example, a fixed, moving and control sub
view is created for both perspective and orthographic projection
- Run the example with `cargo run --example camera_sub_view`
- The code can be tested by adding a `SubCameraView` to a camera

---

## Showcase


![image](https://github.com/user-attachments/assets/75ac45fc-d75d-4664-8ef6-ff7865297c25)

- Left Half: Perspective Projection
- Right Half: Orthographic Projection
- Small boxes in order:
  - Sub view of the left half of the full image
- Sub view moving from the top left to the bottom right of the full
image
  - Sub view of the full image (acting as a control)
- Large box: No sub view

<details>
  <summary>Shortened camera setup of `camera_sub_view` example</summary>

```rust
    // Main perspective Camera
    commands.spawn(Camera3dBundle {
        transform,
        ..default()
    });

    // Perspective camera left half
    commands.spawn(Camera3dBundle {
        camera: Camera {
            sub_camera_view: Some(SubCameraView {
                // Set the sub view camera to the left half of the full image
                full_size: uvec2(500, 500),
                offset: ivec2(0, 0),
                size: uvec2(250, 500),
            }),
            order: 1,
            ..default()
        },
        transform,
        ..default()
    });

    // Perspective camera moving
    commands.spawn((
        Camera3dBundle {
            camera: Camera {
                sub_camera_view: Some(SubCameraView {
                    // Set the sub view camera to a fifth of the full view and
                    // move it in another system
                    full_size: uvec2(500, 500),
                    offset: ivec2(0, 0),
                    size: uvec2(100, 100),
                }),
                order: 2,
                ..default()
            },
            transform,
            ..default()
        },
        MovingCameraMarker,
    ));

    // Perspective camera control
    commands.spawn(Camera3dBundle {
        camera: Camera {
            sub_camera_view: Some(SubCameraView {
                // Set the sub view to the full image, to ensure that it matches
                // the projection without sub view
                full_size: uvec2(450, 450),
                offset: ivec2(0, 0),
                size: uvec2(450, 450),
            }),
            order: 3,
            ..default()
        },
        transform,
        ..default()
    });

    // Main orthographic camera
    commands.spawn(Camera3dBundle {
        projection: OrthographicProjection {
          ...
        }
        .into(),
        camera: Camera {
            order: 4,
            ..default()
        },
        transform,
        ..default()
    });

    // Orthographic camera left half
    commands.spawn(Camera3dBundle {
        projection: OrthographicProjection {
          ...
        }
        .into(),
        camera: Camera {
            sub_camera_view: Some(SubCameraView {
                // Set the sub view camera to the left half of the full image
                full_size: uvec2(500, 500),
                offset: ivec2(0, 0),
                size: uvec2(250, 500),
            }),
            order: 5,
            ..default()
        },
        transform,
        ..default()
    });

    // Orthographic camera moving
    commands.spawn((
        Camera3dBundle {
            projection: OrthographicProjection {
              ...
            }
            .into(),
            camera: Camera {
                sub_camera_view: Some(SubCameraView {
                    // Set the sub view camera to a fifth of the full view and
                    // move it in another system
                    full_size: uvec2(500, 500),
                    offset: ivec2(0, 0),
                    size: uvec2(100, 100),
                }),
                order: 6,
                ..default()
            },
            transform,
            ..default()
        },
        MovingCameraMarker,
    ));

    // Orthographic camera control
    commands.spawn(Camera3dBundle {
        projection: OrthographicProjection {
          ...
        }
        .into(),
        camera: Camera {
            sub_camera_view: Some(SubCameraView {
                // Set the sub view to the full image, to ensure that it matches
                // the projection without sub view
                full_size: uvec2(450, 450),
                offset: ivec2(0, 0),
                size: uvec2(450, 450),
            }),
            order: 7,
            ..default()
        },
        transform,
        ..default()
    });
```

</details>
2024-10-01 14:11:24 +00:00
Ensar Sarajčić
956d9ccbb1
Add directory related functions to AndroidAssetReader (#11495)
# Objective

- Fixes #9968

## Solution

- Uses
[open_dir](https://docs.rs/ndk/latest/ndk/asset/struct.AssetManager.html#method.open_dir)
to read directories and collects child list, since it can't be shared
across threads.
- For `is_directory`, uses result of
[open](https://docs.rs/ndk/latest/ndk/asset/struct.AssetManager.html#method.open),
which will fail for directories. I tried using the result of `open_dir`
for this, but it was successful for files too, which made loading
folders return empty lists, since `open_dir` was successful and treated
all files as empty directories.
- Ignoring `meta` files was copied from filesystem implementation

---

## Changelog

- Fixed: Android's AssetReader implementation now supports
read_directory and is_directory.

## Notes

I noticed late that there was the #9968 issue (I only noticed #9591), so
I have also missed that a PR was already open (#9969). Feel free to copy
over the fixes from this one over there.
The only difference I notice between these 2, is that I have used `open`
instead of `open_dir` for `is_directory` implementation. I have tried
with `open_dir` too, but unfortunately that didn't work. I tested this
on an actual device, using the mobile example, by making some minor
changes:

```rust
#[derive(Resource)]
struct FolderAssets(Handle<LoadedFolder>);

// the `bevy_main` proc_macro generates the required boilerplate for iOS and Android
#[bevy_main]
fn main() {
    // ...
    .add_systems(Startup, (setup_scene, load_music_files))
    .add_systems(
        Update,
        // Removed the handle_lifetime since AudioBundle is added later
        (touch_camera, button_handler, setup_music),
    );
   // ...
}

fn load_music_files(asset_server: Res<AssetServer>, mut commands: Commands) {
    let sounds = asset_server.load_folder("sounds");
    commands.insert_resource(FolderAssets(sounds));
}

fn setup_music(
    mut commands: Commands,
    folders: Res<Assets<LoadedFolder>>,
    mut loaded_event: EventReader<AssetEvent<LoadedFolder>>,
) {
    for event in loaded_event.read() {
        if let AssetEvent::LoadedWithDependencies { id } = event {
            if let Some(folder) = folders.get(*id) {
                warn!("Folder items: {:?}", folder.handles);
                if let Some(source) = folder.handles.first() {
                    commands.spawn(AudioBundle {
                        source: source.clone().typed::<AudioSource>(),
                        settings: PlaybackSettings::LOOP,
                    });
                }
            }
        }
    }
}
```

---------

Co-authored-by: Kanabenki <lucien.menassol@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-10-01 12:23:24 +00:00
Ludwig DUBOS
f08f07785b
Replace AsyncSeek trait by AsyncSeekForward for Reader to address #12880 (#14194)
# Objective

The primary motivation behind this PR is to (partially?) address the
limitations imposed by the recently added `AsyncSeek` trait bound
discussed in issue #12880. While the `AsyncSeek` trait add some
flexibility to the reader, it inadvertently restricts the ability to
write asset readers that can truly stream bytes, particularly in
scenarios like HTTP requests where backward seeking is not supported. It
is also challenging in contexts where assets are stored in compressed
formats or require other kinds of transformations.

The logic behind this change is that currently, with `AsyncSeek`, an
asset Reader based on streamed data will either 1) fail silently, 2)
return an error, or 3) use a buffer to satisfy the trait constraint. I
believe that being able to advance in the file without having to "read"
it is a good thing. The only issue here is the ability to seek backward.
It is highly likely that in this context, we only need to seek forward
in the file because we would have already read an entry table upstream
and just want to access one or more resources further in the file. I
understand that in some cases, this may not be applicable, but I think
it is more beneficial not to constrain `Reader`s that want to stream
than to allow "Assets" to read files in a completely arbitrary order.

## Solution

Replace the current `AsyncSeek` trait with `AsyncSeekForward` on asset
`Reader`

## Changelog

- Introduced a new custom trait, `AsyncSeekForward`, for the asset
Reader.
- Replaced the current `AsyncSeek` trait with `AsyncSeekForward` for all
asset `Reader` implementations.

## Migration Guide

Replace all instances of `AsyncSeek` with `AsyncSeekForward` in your
asset reader implementations.
2024-10-01 03:33:45 +00:00
Joona Aalto
de888a373d
Migrate lights to required components (#15554)
# Objective

Another step in the migration to required components: lights!

Note that this does not include `EnvironmentMapLight` or reflection
probes yet, because their API hasn't been fully chosen yet.

## Solution

As per the [selected
proposals](https://hackmd.io/@bevy/required_components/%2FLLnzwz9XTxiD7i2jiUXkJg):

- Deprecate `PointLightBundle` in favor of the `PointLight` component
- Deprecate `SpotLightBundle` in favor of the `PointLight` component
- Deprecate `DirectionalLightBundle` in favor of the `DirectionalLight`
component

## Testing

I ran some examples with lights.

---

## Migration Guide

`PointLightBundle`, `SpotLightBundle`, and `DirectionalLightBundle` have
been deprecated. Use the `PointLight`, `SpotLight`, and
`DirectionalLight` components instead. Adding them will now insert the
other components required by them automatically.
2024-10-01 03:20:43 +00:00
Andreas
383c2e5bd7
15540 Make World::flush_commands private (#15553)
# Objective

Fixes #15540 

End-users risk using `World::flush_commands` instead of `World::flush`,
which panics if any queued commands are `spawn`. Hiding
`World::flush_commands` would help avoid calling a potentially panicky
function, and helps alleviate end-user API confusion.

## Solution

This PR updates the function visibility to crate-level, like
`World::flush_entities`, hiding it from the end-user while still making
it accessible for the tests that are currently set up.

## Testing

The change was tested by executing the available tests for `bevy_ecs`.
From what I've gathered, `World::flush_commands` is not used in any
other bevy crate. If further testing is recommended, please inform me!

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-30 22:07:09 +00:00
Kristoffer Søholm
73af2b7d29
Cleanup unneeded lifetimes in bevy_asset (#15546)
# Objective

Fixes #15541

A bunch of lifetimes were added during the Assets V2 rework, but after
moving to async traits in #12550 they can be elided. That PR mentions
that this might be the case, but apparently it wasn't followed up on at
the time.

~~I ended up grepping for `<'a` and finding a similar case in
`bevy_reflect` which I also fixed.~~ (edit: that one was needed
apparently)

Note that elided lifetimes are unstable in `impl Trait`. If that gets
stabilized then we can elide even more.

## Solution

Remove the extra lifetimes.

## Testing

Everything still compiles. If I have messed something up there is a
small risk that some user code stops compiling, but all the examples
still work at least.

---

## Migration Guide

The traits `AssetLoader`, `AssetSaver` and `Process` traits from
`bevy_asset` now use elided lifetimes. If you implement these then
remove the named lifetime.
2024-09-30 21:54:59 +00:00
Liam Gallagher
10068f4a26
Add content-type header to BRP HTTP responses (#15552)
This makes HTTP clients like httpie format the response as JSON rather
than text for a much nicer experience testing things.
2024-09-30 21:23:55 +00:00
Matty
429987ebf8
Curve-based animation (#15434)
# Objective

This PR extends and reworks the material from #15282 by allowing
arbitrary curves to be used by the animation system to animate arbitrary
properties. The goals of this work are to:
- Allow far greater flexibility in how animations are allowed to be
defined in order to be used with `bevy_animation`.
- Delegate responsibility over keyframe interpolation to `bevy_math` and
the `Curve` libraries and reduce reliance on keyframes in animation
definitions generally.
- Move away from allowing the glTF spec to completely define animations
on a mechanical level.

## Solution

### Overview

At a high level, curves have been incorporated into the animation system
using the `AnimationCurve` trait (closely related to what was
`Keyframes`). From the top down:

1. In `animate_targets`, animations are driven by `VariableCurve`, which
is now a thin wrapper around a `Box<dyn AnimationCurve>`.
2. `AnimationCurve` is something built out of a `Curve`, and it tells
the animation system how to use the curve's output to actually mutate
component properties. The trait looks like this:
```rust
/// A low-level trait that provides control over how curves are actually applied to entities
/// by the animation system.
///
/// Typically, this will not need to be implemented manually, since it is automatically
/// implemented by [`AnimatableCurve`] and other curves used by the animation system
/// (e.g. those that animate parts of transforms or morph weights). However, this can be
/// implemented manually when `AnimatableCurve` is not sufficiently expressive.
///
/// In many respects, this behaves like a type-erased form of [`Curve`], where the output
/// type of the curve is remembered only in the components that are mutated in the
/// implementation of [`apply`].
///
/// [`apply`]: AnimationCurve::apply
pub trait AnimationCurve: Reflect + Debug + Send + Sync {
    /// Returns a boxed clone of this value.
    fn clone_value(&self) -> Box<dyn AnimationCurve>;

    /// The range of times for which this animation is defined.
    fn domain(&self) -> Interval;

    /// Write the value of sampling this curve at time `t` into `transform` or `entity`,
    /// as appropriate, interpolating between the existing value and the sampled value
    /// using the given `weight`.
    fn apply<'a>(
        &self,
        t: f32,
        transform: Option<Mut<'a, Transform>>,
        entity: EntityMutExcept<'a, (Transform, AnimationPlayer, Handle<AnimationGraph>)>,
        weight: f32,
    ) -> Result<(), AnimationEvaluationError>;
}
```
3. The conversion process from a `Curve` to an `AnimationCurve` involves
using wrappers which communicate the intent to animate a particular
property. For example, here is `TranslationCurve`, which wraps a
`Curve<Vec3>` and uses it to animate `Transform::translation`:
```rust
/// This type allows a curve valued in `Vec3` to become an [`AnimationCurve`] that animates
/// the translation component of a transform.
pub struct TranslationCurve<C>(pub C);
```

### Animatable Properties

The `AnimatableProperty` trait survives in the transition, and it can be
used to allow curves to animate arbitrary component properties. The
updated documentation for `AnimatableProperty` explains this process:
<details>
  <summary>Expand AnimatableProperty example</summary

An `AnimatableProperty` is a value on a component that Bevy can animate.

You can implement this trait on a unit struct in order to support
animating
custom components other than transforms and morph weights. Use that type
in
conjunction with `AnimatableCurve` (and perhaps
`AnimatableKeyframeCurve`
to define the animation itself). For example, in order to animate font
size of a
text section from 24 pt. to 80 pt., you might use:

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

impl AnimatableProperty for FontSizeProperty {
    type Component = Text;
    type Property = f32;
    fn get_mut(component: &mut Self::Component) -> Option<&mut Self::Property> {
        Some(&mut component.sections.get_mut(0)?.style.font_size)
    }
}
```

You can then create an `AnimationClip` to animate this property like so:

```rust
let mut animation_clip = AnimationClip::default();
animation_clip.add_curve_to_target(
    animation_target_id,
    AnimatableKeyframeCurve::new(
        [
            (0.0, 24.0),
            (1.0, 80.0),
        ]
    )
    .map(AnimatableCurve::<FontSizeProperty, _>::from_curve)
    .expect("Failed to create font size curve")
);
```

Here, the use of `AnimatableKeyframeCurve` creates a curve out of the
given keyframe time-value
pairs, using the `Animatable` implementation of `f32` to interpolate
between them. The
invocation of `AnimatableCurve::from_curve` with `FontSizeProperty`
indicates that the `f32`
output from that curve is to be used to animate the font size of a
`Text` component (as
configured above).


</details>

### glTF Loading

glTF animations are now loaded into `Curve` types of various kinds,
depending on what is being animated and what interpolation mode is being
used. Those types get wrapped into and converted into `Box<dyn
AnimationCurve>` and shoved inside of a `VariableCurve` just like
everybody else.

### Morph Weights

There is an `IterableCurve` abstraction which allows sampling these from
a contiguous buffer without allocating. Its only reason for existing is
that Rust disallows you from naming function types, otherwise we would
just use `Curve` with an iterator output type. (The iterator involves
`Map`, and the name of the function type would have to be able to be
named, but it is not.)

A `WeightsCurve` adaptor turns an `IterableCurve` into an
`AnimationCurve`, so it behaves like everything else in that regard.

## Testing

Tested by running existing animation examples. Interpolation logic has
had additional tests added within the `Curve` API to replace the tests
in `bevy_animation`. Some kinds of out-of-bounds errors have become
impossible.

Performance testing on `many_foxes` (`animate_targets`) suggests that
performance is very similar to the existing implementation. Here are a
couple trace histograms across different runs (yellow is this branch,
red is main).
<img width="669" alt="Screenshot 2024-09-27 at 9 41 50 AM"
src="https://github.com/user-attachments/assets/5ba4e9ac-3aea-452e-aaf8-1492acc2d7fc">
<img width="673" alt="Screenshot 2024-09-27 at 9 45 18 AM"
src="https://github.com/user-attachments/assets/8982538b-04cf-46b5-97b2-164c6bc8162e">

---

## Migration Guide

Most user code that does not directly deal with `AnimationClip` and
`VariableCurve` will not need to be changed. On the other hand,
`VariableCurve` has been completely overhauled. If you were previously
defining animation curves in code using keyframes, you will need to
migrate that code to use curve constructors instead. For example, a
rotation animation defined using keyframes and added to an animation
clip like this:
```rust
animation_clip.add_curve_to_target(
    animation_target_id,
    VariableCurve {
        keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0],
        keyframes: Keyframes::Rotation(vec![
            Quat::IDENTITY,
            Quat::from_axis_angle(Vec3::Y, PI / 2.),
            Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
            Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
            Quat::IDENTITY,
        ]),
        interpolation: Interpolation::Linear,
    },
);
```

would now be added like this:
```rust
animation_clip.add_curve_to_target(
    animation_target_id,
    AnimatableKeyframeCurve::new([0.0, 1.0, 2.0, 3.0, 4.0].into_iter().zip([
        Quat::IDENTITY,
        Quat::from_axis_angle(Vec3::Y, PI / 2.),
        Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.),
        Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.),
        Quat::IDENTITY,
    ]))
    .map(RotationCurve)
    .expect("Failed to build rotation curve"),
);
```

Note that the interface of `AnimationClip::add_curve_to_target` has also
changed (as this example shows, if subtly), and now takes its curve
input as an `impl AnimationCurve`. If you need to add a `VariableCurve`
directly, a new method `add_variable_curve_to_target` accommodates that
(and serves as a one-to-one migration in this regard).

### For reviewers

The diff is pretty big, and the structure of some of the changes might
not be super-obvious:
- `keyframes.rs` became `animation_curves.rs`, and `AnimationCurve` is
based heavily on `Keyframes`, with the adaptors also largely following
suite.
- The Curve API adaptor structs were moved from `bevy_math::curve::mod`
into their own module `adaptors`. There are no functional changes to how
these adaptors work; this is just to make room for the specialized
reflection implementations since `mod.rs` was getting kind of cramped.
- The new module `gltf_curves` holds the additional curve constructions
that are needed by the glTF loader. Note that the loader uses a mix of
these and off-the-shelf `bevy_math` curve stuff.
- `animatable.rs` no longer holds logic related to keyframe
interpolation, which is now delegated to the existing abstractions in
`bevy_math::curve::cores`.

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
Co-authored-by: aecsocket <43144841+aecsocket@users.noreply.github.com>
2024-09-30 19:56:55 +00:00
Joona Aalto
f3e8ae03cd
Runtime required components (#15458)
# Objective

Fixes #15367.

Currently, required components can only be defined through the `require`
macro attribute. While this should be used in most cases, there are also
several instances where you may want to define requirements at runtime,
commonly in plugins.

Example use cases:

- Require components only if the relevant optional plugins are enabled.
For example, a `SleepTimer` component (for physics) is only relevant if
the `SleepPlugin` is enabled.
- Third party crates can define their own requirements for first party
types. For example, "each `Handle<Mesh>` should require my custom
rendering data components". This also gets around the orphan rule.
- Generic plugins that add marker components based on the existence of
other components, like a generic `ColliderPlugin<C: AnyCollider>` that
wants to add a `ColliderMarker` component for all types of colliders.
- This is currently relevant for the retained render world in #15320.
The `ExtractComponentPlugin<C>` should add `SyncToRenderWorld` to all
components that should be extracted. This is currently done with
observers, which is more expensive than required components, and causes
archetype moves.
- Replace some built-in components with custom versions. For example, if
`GlobalTransform` required `Transform` through `TransformPlugin`, but we
wanted to use a `CustomTransform` type, we could replace
`TransformPlugin` with our own plugin. (This specific example isn't
good, but there are likely better use cases where this may be useful)

See #15367 for more in-depth reasoning.

## Solution

Add `register_required_components::<T, R>` and
`register_required_components_with::<T, R>` methods for `Default` and
custom constructors respectively. These methods exist on `App` and
`World`.

```rust
struct BirdPlugin;

impl Plugin for BirdPlugin {
    fn plugin(app: &mut App) {
        // Make `Bird` require `Wings` with a `Default` constructor.
        app.register_required_components::<Bird, Wings>();

        // Make `Wings` require `FlapSpeed` with a custom constructor.
        // Fun fact: Some hummingbirds can flutter their wings 80 times per second!
        app.register_required_components_with::<Wings, FlapSpeed>(|| FlapSpeed::from_duration(1.0 / 80.0));
    }
}
```

The custom constructor is a function pointer to match the `require` API,
though it could take a raw value too.

Requirement inheritance works similarly as with the `require` attribute.
If `Bird` required `FlapSpeed` directly, it would take precedence over
indirectly requiring it through `Wings`. The same logic applies to all
levels of the inheritance tree.

Note that registering the same component requirement more than once will
panic, similarly to trying to add multiple component hooks of the same
type to the same component. This avoids constructor conflicts and
confusing ordering issues.

### Implementation

Runtime requirements have two additional challenges in comparison to the
`require` attribute.

1. The `require` attribute uses recursion and macros with clever
ordering to populate hash maps of required components for each component
type. The expected semantics are that "more specific" requirements
override ones deeper in the inheritance tree. However, at runtime, there
is no representation of how "specific" each requirement is.
2. If you first register the requirement `X -> Y`, and later register `Y
-> Z`, then `X` should also indirectly require `Z`. However, `Y` itself
doesn't know that it is required by `X`, so it's not aware that it
should update the list of required components for `X`.

My solutions to these problems are:

1. Store the depth in the inheritance tree for each entry of a given
component's `RequiredComponents`. This is used to determine how
"specific" each requirement is. For `require`-based registration, these
depths are computed as part of the recursion.
2. Store and maintain a `required_by` list in each component's
`ComponentInfo`, next to `required_components`. For `require`-based
registration, these are also added after each registration, as part of
the recursion.

When calling `register_required_components`, it works as follows:

1. Get the required components of `Foo`, and check that `Bar` isn't
already a *direct* requirement.
3. Register `Bar` as a required component for `Foo`, and add `Foo` to
the `required_by` list for `Bar`.
4. Find and register all indirect requirements inherited from `Bar`,
adding `Foo` to the `required_by` list for each component.
5. Iterate through components that require `Foo`, registering the new
inherited requires for them as indirect requirements.

The runtime registration is likely slightly more expensive than the
`require` version, but it is a one-time cost, and quite negligible in
practice, unless projects have hundreds or thousands of runtime
requirements. I have not benchmarked this however.

This does also add a small amount of extra cost to the `require`
attribute for updating `required_by` lists, but I expect it to be very
minor.

## Testing

I added some tests that are copies of the `require` versions, as well as
some tests that are more specific to the runtime implementation. I might
add a few more tests though.

## Discussion

- Is `register_required_components` a good name? Originally I went for
`register_component_requirement` to be consistent with
`register_component_hooks`, but the general feature is often referred to
as "required components", which is why I changed it to
`register_required_components`.
- Should we *not* panic for duplicate requirements? If so, should they
just be ignored, or should the latest registration overwrite earlier
ones?
- If we do want to panic for duplicate, conflicting registrations,
should we at least not panic if the registrations are *exactly* the
same, i.e. same component and same constructor? The current
implementation panics for all duplicate direct registrations regardless
of the constructor.

## Next Steps

- Allow `register_required_components` to take a `Bundle` instead of a
single required component.
    - I could also try to do it in this PR if that would be preferable.
- Not directly related, but archetype invariants?
2024-09-30 19:20:16 +00:00