# Objective
Both the shedule and winit runners use/reimplement `app_exit_manual`
even tough they can use `app_exit`
## Solution
Nuke `app_exit_manual` from orbit.
# Objective
- Be able to edit animation inside the editor and save them once
modified. This will allow bevy to modify animation assets with code.
- Fixes#13052
## Solution
- Expose the previously const getters of the Animation curves
---
# Objective
Follow up to #13062. As of async-executor 1.11, the crate reexports
FallibleTask, which is the only reason bevy_tasks has a direct
dependency on async-task. This should avoid the two dependencies getting
out of sync in the future and causing spurious compilation failures.
## Solution
Bump async-executor to 1.11, use the reexport, remove the dependency on
async-task.
# Objective
- bevy usually use `Parallel::scope` to collect items from `par_iter`,
but `scope` will be called with every satifified items. it will cause a
lot of unnecessary lookup.
## Solution
- similar to Rayon ,we introduce `for_each_init` for `par_iter` which
only be invoked when spawn a task for a group of items.
---
## Changelog
- added `for_each_init`
## Performance
`check_visibility ` in `many_foxes `
![image](https://github.com/bevyengine/bevy/assets/45868716/030c41cf-0d2f-4a36-a071-35097d93e494)
~40% performance gain in `check_visibility`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
Allow `Gizmos` to work in `FixedUpdate` without any changes needed. This
changes `Gizmos` from being a purely immediate mode api, but allows the
user to use it as if it were an immediate mode API regardless of
schedule context.
Also allows for extending by other custom schedules by adding their own
`GizmoStorage<Clear>` and the requisite systems:
- `propagate_gizmos::<Clear>` before `update_gizmo_meshes`
- `stash_default_gizmos` when starting a clear context
- `pop_default_gizmos` when ending a clear context
- `collect_default_gizmos` when grabbing the requested gizmos
- `clear_gizmos` for clearing the context's gizmos
## Solution
Adds a generic to `Gizmos` that defaults to `Update` (the current way
gizmos works). When entering a new clear context the default `Gizmos`
gets swapped out for that context's duration so the context can collect
the gizmos requested.
Prior work: https://github.com/bevyengine/bevy/pull/9153
## To do
- [x] `FixedUpdate` should probably get its own First, Pre, Update,
Post, Last system sets for this. Otherwise users will need to make sure
to order their systems before `clear_gizmos`. This could alternatively
be fixed by moving the setup of this to `bevy_time::fixed`?
PR to fix this issue: https://github.com/bevyengine/bevy/pull/10977
- [x] use mem::take internally for the swaps?
- [x] Better name for the `Context` generic on gizmos? `Clear`?
---
## Changelog
- Gizmos drawn in `FixedMain` now last until the next `FixedMain`
iteration runs.
Bumps `async-task` to 4.7.0 , note this is what Cargo.lock has as well.
Building as a dependency gives the following:
```
Compiling async-channel v1.8.0
Compiling futures-lite v1.12.0
error[E0432]: unresolved import `async_task::Builder`
--> /Users/daniel/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.8.0/src/lib.rs:46:18
|
46 | use async_task::{Builder, Runnable};
| ^^^^^^^ no `Builder` in the root
|
= help: consider importing this struct instead:
std:🧵:Builder
For more information about this error, try `rustc --explain E0432`.
error: could not compile `async-executor` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
```
With this change, builds correctly
# Objective
Adds a few extra `#[doc(alias)]` entries to the
`bevy_math::primitives::WindingOrder` enum and its variants to improve
searchability.
## Solution
- Add "Orientation" for `WindingOrder` itself
- Add "AntiClockwise" for `CounterClockwise` variant
- Add "Collinear" for `Invalid` variant
These alternate terms seem to be quite common, especially in the
contexts of rendering and collision-detection.
Signed-off-by: Nullicorn <git@nullicorn.me>
# Objective
Fixes#12470
This adds a examples for `ButtonInput` with `KeyCode`, `MouseButton`,
and `GamepadButton`.
It also includes an example of checking a multi-key combination, and
checking multiple keys to mean roughly the same thing.
# Objective
Closes#13017.
## Solution
- Make `AppExit` a enum with a `Success` and `Error` variant.
- Make `App::run()` return a `AppExit` if it ever returns.
- Make app runners return a `AppExit` to signal if they encountered a
error.
---
## Changelog
### Added
- [`App::should_exit`](https://example.org/)
- [`AppExit`](https://docs.rs/bevy/latest/bevy/app/struct.AppExit.html)
to the `bevy` and `bevy_app` preludes,
### Changed
- [`AppExit`](https://docs.rs/bevy/latest/bevy/app/struct.AppExit.html)
is now a enum with 2 variants (`Success` and `Error`).
- The app's [runner
function](https://docs.rs/bevy/latest/bevy/app/struct.App.html#method.set_runner)
now has to return a `AppExit`.
-
[`App::run()`](https://docs.rs/bevy/latest/bevy/app/struct.App.html#method.run)
now also returns the `AppExit` produced by the runner function.
## Migration Guide
- Replace all usages of
[`AppExit`](https://docs.rs/bevy/latest/bevy/app/struct.AppExit.html)
with `AppExit::Success` or `AppExit::Failure`.
- Any custom app runners now need to return a `AppExit`. We suggest you
return a `AppExit::Error` if any `AppExit` raised was a Error. You can
use the new [`App::should_exit`](https://example.org/) method.
- If not exiting from `main` any other way. You should return the
`AppExit` from `App::run()` so the app correctly returns a error code if
anything fails e.g.
```rust
fn main() -> AppExit {
App::new()
//Your setup here...
.run()
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- https://github.com/rust-lang/rust/pull/123905 has been merged, so the
workaround introduced in #12913 is no longer necessary.
- Closes#12968
## Solution
- Remove unecessary `allow` attribute
- This is currently blocked until Rust beta updates.
- Last tested with `rustc 1.78.0-beta.7 (6fd191292 2024-04-12)`.
# Objective
Add support so bevy_ui can correctly handle an UI hierarchy without a
camera present.
- Fixes#12184
## Solution
As there was no default behavior for what should happen when a camera is
not present in a UI hierarchy, the solution
was based in defining that default behavior and improving the overall
handling of this "exception".
## Changelog
- Create default values to be used in upsert_node
- Add flag to control warnings about no camera present
- Create unit test no_camera_ui (to test if ui handles no camera
present)
# Objective
Allow parallel iteration over events, resolve#10766
## Solution
- Add `EventParIter` which works similarly to `QueryParIter`,
implementing a `for_each{_with_id}` operator.
I chose to not mirror `EventIteratorWithId` and instead implement both
operations on a single struct.
- Reuse `BatchingStrategy` from `QueryParIter`
## Changelog
- `EventReader` now supports parallel event iteration using
`par_read().for_each(|event| ...)`.
---------
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
# Objective
Makes crate module docs render correctly in the docs for the monolithic
library. Fixes https://github.com/bevyengine/bevy/issues/13055.
## Solution
Swap from
```rust
pub mod foo {
pub use bevy_foo::*;
}
```
to
```rust
pub use bevy_foo as foo;
```
Adjusted the documentation to better describe the performance cost of
`ButtonInput::any_just_pressed|any_just_released|any_pressed`.
Each function iterates the full input, but each check is expected
constant cost. It was described previously as a full input check, and a
full internal list iteration, which I believe is incorrect.
# Objective
- `MeshPipelineKey` use some bits for two things
- First commit in this PR adds an assertion that doesn't work currently
on main
- This leads to some mesh topology not working anymore, for example
`LineStrip`
- With examples `lines`, there should be two groups of lines, the blue
one doesn't display currently
## Solution
- Change the `MeshPipelineKey` to be backed by a `u64` instead, to have
enough bits
# Objective
Fix#2128. Both `Query::new_archetype` and `SystemParam::new_archetype`
do not check if the `Archetype` comes from the same World the state is
initialized from. This could result in unsoundness via invalid accesses
if called incorrectly.
## Solution
Make them `unsafe` functions and lift the invariant to the caller. This
also caught one instance of us not validating the World in
`SystemState::update_archetypes_unsafe_world_cell`'s implementation.
---
## Changelog
Changed: `QueryState::new_archetype` is now an unsafe function.
Changed: `SystemParam::new_archetype` is now an unsafe function.
## Migration Guide
`QueryState::new_archetype` and `SystemParam::new_archetype` are now an
unsafe functions that must be sure that the provided `Archetype` is from
the same `World` that the state was initialized from. Callers may need
to add additional assertions or propagate the safety invariant upwards
through the callstack to ensure safety.
# Objective
- The docs says the WireframeColor is supposed to override the default
global color but it doesn't.
## Solution
- Use WireframeColor to override global color like docs said it was
supposed to do.
- Updated the example to document this feature
- I also took the opportunity to clean up the code a bit
Fixes#13032
# Objective
- Fixes#13024.
## Solution
- Run `cargo clippy --target wasm32-unknown-unknown` until there are no
more errors.
- I recommend reviewing one commit at a time :)
---
## Changelog
- Fixed Clippy lints for `wasm32-unknown-unknown` target.
- Updated `bevy_transform`'s `README.md`.
# Objective
- Closes#12930.
## Solution
- Add a corresponding optional field on `Window` and `ExtractedWindow`
---
## Changelog
### Added
- `wgpu`'s `desired_maximum_frame_latency` is exposed through window
creation. This can be used to override the default maximum number of
queued frames on the GPU (currently 2).
## Migration Guide
- The `desired_maximum_frame_latency` field must be added to instances
of `Window` and `ExtractedWindow` where all fields are explicitly
specified.
# Objective
Sometimes when despawning a ui node in the PostUpdate schedule it
panics. This is because both a despawn command and insert command are
being run on the same entity.
See this example code:
```rs
use bevy::{prelude::*, ui::UiSystem};
#[derive(Resource)]
struct SliceSquare(Handle<Image>);
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, create_ui)
.add_systems(PostUpdate, despawn_nine_slice.after(UiSystem::Layout))
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.insert_resource(SliceSquare(asset_server.load("textures/slice_square.png")));
}
fn create_ui(mut commands: Commands, slice_square: Res<SliceSquare>) {
commands.spawn((
NodeBundle {
style: Style {
width: Val::Px(200.),
height: Val::Px(200.),
..default()
},
background_color: Color::WHITE.into(),
..default()
},
UiImage::new(slice_square.0.clone()),
ImageScaleMode::Sliced(TextureSlicer {
border: BorderRect::square(220.),
center_scale_mode: SliceScaleMode::Stretch,
sides_scale_mode: SliceScaleMode::Stretch,
max_corner_scale: 1.,
}),
));
}
fn despawn_nine_slice(mut commands: Commands, mut slices: Query<Entity, With<ImageScaleMode>>) {
for entity in slices.iter_mut() {
commands.entity(entity).despawn_recursive();
}
}
```
This code spawns a UiNode with a sliced image scale mode, and despawns
it in the same frame. The
bevy_ui::texture_slice::compute_slices_on_image_change system tries to
insert the ComputedTextureSlices component on that node, but that entity
is already despawned causing this error:
```md
error[B0003]: Could not insert a bundle (of type `bevy_ui::texture_slice::ComputedTextureSlices`) for entity Entity { index: 2, generation: 3 } because it doesn't
exist in this World. See: https://bevyengine.org/learn/errors/#b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_ui::texture_slice::compute_slices_on_image_change`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```
Note that you might have to run the code a few times before this error
appears.
## Solution
Use try_insert instead of insert for non critical inserts in the bevy_ui
crate.
## Some notes
In a lot of cases it does not makes much sense to despawn ui nodes after
the layout system has finished. Except maybe if you delete the root ui
node of a tree. I personally encountered this issue in bevy `0.13.2`
with a system that was running before the layout system. And in `0.13.2`
the `compute_slices_on_image_change` system was also running before the
layout system. But now it runs after the layout system. So the only way
that this bug appears now is if you despawn ui nodes after the layout
system. So I am not 100% sure if using try_insert in this system is the
best option. But personally I still think it is better then the program
panicking.
However the `update_children_target_camera` system does still run before
the layout system. So I do think it might still be able to panic when ui
nodes are despawned before the layout system. Though I haven't been able
to verify that.
# Objective
- General clenup of the primitives in `bevy_math`
- Add `eccentricity()` to `Ellipse`
## Solution
- Moved `Bounded3d` implementation for `Triangle3d` to the `bounded`
module
- Added `eccentricity()` to `Ellipse`
- `Ellipse::semi_major()` and `::semi_minor()` now accept `&self`
instead of `self`
- `Triangle3d::is_degenerate()` actually uses `f32::EPSILON` as
documented
- Added tests for `Triangle3d`-maths
---------
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
Co-authored-by: Miles Silberling-Cook <nth.tensor@gmail.com>
# Objective
Make visibility system ordering explicit. Fixes#12953.
## Solution
Specify `CheckVisibility` happens after all other `VisibilitySystems`
sets have happened.
---------
Co-authored-by: Elabajaba <Elabajaba@users.noreply.github.com>
# Objective
Missing docs
## Solution
Add docs paraphrased from the Cart's mouth:
https://discord.com/channels/691052431525675048/691052431974465548/1172305792154738759
> It follows the natural "results" of right handed y-up. The default
camera will face "forward" in -Z, with +X being "right". The RH y-up
setup is reasonably common. Thats why I asked for existing examples.I
think we should appeal to the masses here / see how other RH Y-up 3D
packages / engines handle this
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
# Objective
When trying to be generic over `Material + Default`, the lack of a
`Default` impl for `ExtendedMaterial`, even when both of its components
implement `Default`, is problematic. I think was probably just
overlooked.
## Solution
Impl `Default` if the material and extension both impl `Default`.
---
## Changelog
## Migration Guide
# Objective
Related to #12981
Presently, there is a footgun where we allow non-normalized vectors to
be passed in the `axis` parameters of `Transform::rotate_axis` and
`Transform::rotate_local_axis`. These methods invoke
`Quat::from_axis_angle` which expects the vector to be normalized. This
PR aims to address this.
## Solution
Require `Dir3`-valued `axis` parameters for these functions so that the
vector's normalization can be enforced at type-level.
---
## Migration Guide
All calls to `Transform::rotate_axis` and `Transform::rotate_local_axis`
will need to be updated to use a `Dir3` for the `axis` parameter rather
than a `Vec3`. For a general input, this means calling `Dir3::new` and
handling the `Result`, but if the previous vector is already known to be
normalized, `Dir3::new_unchecked` can be called instead. Note that
literals like `Vec3::X` also have corresponding `Dir3` literals; e.g.
`Dir3::X`, `Dir3::NEG_Y` and so on.
---
## Discussion
This axis input is unambigiously a direction instead of a vector, and
that should probably be reflected and enforced by the function
signature. In previous cases where we used, e.g., `impl TryInto<Dir3>`,
the associated methods already implemented (and required!) additional
fall-back logic, since the input is conceptually more complicated than
merely specifying an axis. In this case, I think it's fairly
cut-and-dry, and I'm pretty sure these methods just predate our
direction types.
# Objective
As described in #12467, Bevy does not have any spans for any of the
tasks scheduled onto the IO and async compute task pools.
## Solution
Instrument all asset loads and asset processing. Since this change is
restricted to asset tasks, it does not completely solve #12467, but it
does mean we can record the asset path in the trace.
![image](https://github.com/bevyengine/bevy/assets/8494645/59faee63-1f69-40af-bf47-312c4d67d1e2)
---
## Changelog
Tracing will now include spans for asset loading and asset processing.
glTF files that contain lights currently panic when loaded into Bevy,
because Bevy tries to reflect on `Cascades`, which accidentally wasn't
registered.
`EntityHashSet` doesn't seem to implement `Reflect` which seems weird!
Especially since `EntityHashMap` implements `Reflect`.
This PR just added an extra `impl_reflect_value!` for `EntityHashSet`
and this seems to do the trick.
I left out doing the same for `StableHashSet` since it's marked as
deprecated.
---
I'm really wondering what was the issue here. If anyone can explain why
`EntityHashSet` can't use the `Reflect` impl of `bevy_utils::HashSet`
similar to how it's the case with the `...HashMap`s I'd be interested!
# Objective
- Fixes#12976
## Solution
This one is a doozy.
- Run `cargo +beta clippy --workspace --all-targets --all-features` and
fix all issues
- This includes:
- Moving inner attributes to be outer attributes, when the item in
question has both inner and outer attributes
- Use `ptr::from_ref` in more scenarios
- Extend the valid idents list used by `clippy:doc_markdown` with more
names
- Use `Clone::clone_from` when possible
- Remove redundant `ron` import
- Add backticks to **so many** identifiers and items
- I'm sorry whoever has to review this
---
## Changelog
- Added links to more identifiers in documentation.
# Objective
Improve the code quality of the multithreaded executor.
## Solution
* Remove some unused variables.
* Use `Mutex::get_mut` where applicable instead of locking.
* Use a `startup_systems` FixedBitset to pre-compute the starting
systems instead of building it bit-by-bit on startup.
* Instead of using `FixedBitset::clear` and `FixedBitset::union_with`,
use `FixedBitset::clone_from` instead, which does only a single copy and
will not allocate if the target bitset has a large enough allocation.
* Replace the `Mutex` around `Conditions` with `SyncUnsafeCell`, and add
a `Context::try_lock` that forces it to be synchronized fetched
alongside the executor lock.
This might produce minimal performance gains, but the focus here is on
the code quality improvements.
# Objective
Fixes#12408 .
Fixes#12680.
## Solution
- Recaclulated anchor from dimensions of sprite to dimension of each
part of it (each part contains its own anchor)
[Alpha to coverage] (A2C) replaces alpha blending with a
hardware-specific multisample coverage mask when multisample
antialiasing is in use. It's a simple form of [order-independent
transparency] that relies on MSAA. ["Anti-aliased Alpha Test: The
Esoteric Alpha To Coverage"] is a good summary of the motivation for and
best practices relating to A2C.
This commit implements alpha to coverage support as a new variant for
`AlphaMode`. You can supply `AlphaMode::AlphaToCoverage` as the
`alpha_mode` field in `StandardMaterial` to use it. When in use, the
standard material shader automatically applies the texture filtering
method from ["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"].
Objects with alpha-to-coverage materials are binned in the opaque pass,
as they're fully order-independent.
The `transparency_3d` example has been updated to feature an object with
alpha to coverage. Happily, the example was already using MSAA.
This is part of #2223, as far as I can tell.
[Alpha to coverage]: https://en.wikipedia.org/wiki/Alpha_to_coverage
[order-independent transparency]:
https://en.wikipedia.org/wiki/Order-independent_transparency
["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"]:
https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f
---
## Changelog
### Added
* The `AlphaMode` enum now supports `AlphaToCoverage`, to provide
limited order-independent transparency when multisample antialiasing is
in use.
# Objective
- ~~This PR adds more flexible versions of `set_if_neq` and
`replace_if_neq` to only compare and update certain fields of a
components which is not just a newtype~~
- https://github.com/bevyengine/bevy/pull/12919#issuecomment-2048049786
gave a good solution to the original problem, so let's update the docs
so that this is easier to find
## Solution
- ~~Add `set_if_neq_with` and `replace_if_neq_with` which take an
accessor closure to access the relevant field~~
---
In a recent project, a scenario emerged that required careful
consideration regarding change detection without compromising
performance. The context involves a component that maintains a
collection of `Vec<Vec2>` representing a horizontal surface, alongside a
height field. When the height is updated, there are a few approaches to
consider:
1. Clone the collection of points to utilize the existing `set_if_neq`
method.
2. Inline and adjust the `set_if_neq` code specifically for this
scenario.
3. (Consider splitting the component into more granular components.)
It's worth noting that the third option might be the most suitable in
most cases.
A similar situation arises with the Bevy internal Transform component,
which includes fields for translation, rotation, and scale. These fields
are relatively small (`Vec3` or `Quat` with 3 or 4 `f32` values), but
the creation of a single pointer (`usize`) might be more efficient than
copying the data of the other fields. This is speculative, and insights
from others could be valuable.
Questions remain:
- Is it feasible to develop a more flexible API, and what might that
entail?
- Is there general interest in this change?
There's no hard feelings if this idea or the PR is ultimately rejected.
I just wanted to put this idea out there and hope that this might be
beneficial to others and that feedback could be valuable before
abandoning the idea.
# Objective
- `cargo run --release --example bevymark -- --benchmark --waves 160
--per-wave 1000 --mode mesh2d` runs slower and slower over time due to
`no_gpu_preprocessing::write_batched_instance_buffer<bevy_sprite::mesh2d::mesh::Mesh2dPipeline>`
taking longer and longer because the `BatchedInstanceBuffer` is not
cleared
## Solution
- Split the `clear_batched_instance_buffers` system into CPU and GPU
versions
- Use the CPU version for 2D meshes
# Objective
Fixes a crash when transcoding one- or two-channel KTX2 textures
## Solution
transcoded array has been pre-allocated up to levels.len using a macros.
Rgb8 transcoding already uses that and addresses transcoded array by an
index. R8UnormSrgb and Rg8UnormSrgb were pushing on top of the
transcoded vec, resulting in first levels.len() vectors to stay empty,
and second levels.len() levels actually being transcoded, which then
resulted in out of bounds read when copying levels to gpu
# Objective
- `cargo check --workspace` appears to merge features and dependencies
together, so it does not catch some issues where dependencies are not
properly feature-gated.
- The issues **are** caught, though, by running `cd $crate && cargo
check`.
## Solution
- Manually check each crate for issues.
```shell
# Script used
for i in crates/bevy_* do
pushd $i
cargo check
popd
done
```
- `bevy_color` had an issue where it used `#[derive(Pod, Zeroable)]`
without using `bytemuck`'s `derive` feature.
- The `FpsOverlayPlugin` in `bevy_dev_tools` uses `bevy_ui`'s
`bevy_text` integration without properly enabling `bevy_text` as a
feature.
- `bevy_gizmos`'s `light` module was not properly feature-gated behind
`bevy_pbr`.
- ~~Lights appear to only be implemented in `bevy_pbr` and not
`bevy_sprite`, so I think this is the right call. Can I get a
confirmation by a gizmos person?~~ Confirmed :)
- `bevy_gltf` imported `SmallVec`, but only used it if `bevy_animation`
was enabled.
- There was another issue, but it was more challenging to solve than the
`smallvec` one. Run `cargo check -p bevy_gltf` and it will raise an
issue about `animation_roots`.
<details>
<summary><code>bevy_gltf</code> errors</summary>
```shell
error[E0425]: cannot find value `animation_roots` in this scope
--> crates/bevy_gltf/src/loader.rs:608:26
|
608 | &animation_roots,
| ^^^^^^^^^^^^^^^ not found in this scope
warning: variable does not need to be mutable
--> crates/bevy_gltf/src/loader.rs:1015:5
|
1015 | mut animation_context: Option<AnimationContext>,
| ----^^^^^^^^^^^^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
For more information about this error, try `rustc --explain E0425`.
warning: `bevy_gltf` (lib) generated 1 warning
error: could not compile `bevy_gltf` (lib) due to 1 previous error; 1 warning emitted
```
</details>
---
## Changelog
- Fixed `bevy_color`, `bevy_dev_tools`, and `bevy_gizmos` so they can
now compile by themselves.
# Objective
i downloaded a random model from sketchfab
(https://sketchfab.com/3d-models/dragon-glass-fe00cb0ecaca4e4595874b70de7e116b)
to fiddle with bevy and encountered a panic when attempted to play
animations:
```
thread 'Compute Task Pool (3)' panicked at /home/username/code/bevy/crates/bevy_animation/src/lib.rs:848:58:
index out of bounds: the len is 40 but the index is 40
```
"Animation / Animated Fox"
(5caf085dac/examples/animation/animated_fox.rs)
example can be used for reproduction. to reproduce download a model from
sketchfab (link above) and load it instead of loading fox.glb, keep only
`dragon_glass.glb#Animation0` and remove `1` and `2` -> run and wait 1-2
seconds for crash to happen.
## Solution
correct keyframe indexing, i guess
`ExtractComponentPlugin` doesn't check to make sure the component is
actually present unless it's in the `QueryFilter`. This meant we placed
it everywhere. This regressed performance on many examples, such as
`many_cubes`.
Fixes#12956.