bevy/crates
Patrick Walton 3c41586154
Add EntityRefExcept and EntityMutExcept world queries, in preparation for generalized animation. (#15207)
This commit adds two new `WorldQuery` types: `EntityRefExcept` and
`EntityMutExcept`. These types work just like `EntityRef` and
`EntityMut`, but they prevent access to a statically-specified list of
components. For example, `EntityMutExcept<(AnimationPlayer,
Handle<AnimationGraph>)>` provides mutable access to all components
except for `AnimationPlayer` and `Handle<AnimationGraph>`. These types
are useful when you need to be able to process arbitrary queries while
iterating over the results of another `EntityMut` query.

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

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

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

## Testing

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

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

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

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

![Screenshot 2024-09-14
205831](https://github.com/user-attachments/assets/4241015e-0c5d-44ef-835b-43f78a24e604)
2024-09-17 14:53:39 +00:00
..
bevy_a11y Reflected traits for resources and components: bevy_a11y (#15192) 2024-09-14 01:43:16 +00:00
bevy_animation Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_app Unify crate-level preludes (#15080) 2024-09-08 17:10:57 +00:00
bevy_asset Reccomend using AssetPlugin.file_path instead of CARGO_MANIFEST_DIR (#15176) 2024-09-13 16:16:23 +00:00
bevy_audio Reflect derived traits on all components and resources: bevy_audio (#15211) 2024-09-15 14:24:00 +00:00
bevy_color Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_core Unify crate-level preludes (#15080) 2024-09-08 17:10:57 +00:00
bevy_core_pipeline Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_derive Remove deprecated bevy_dynamic_plugin (#14534) 2024-07-30 15:31:08 +00:00
bevy_dev_tools Split OrthographicProjection::default into 2d & 3d (Adopted) (#15073) 2024-09-09 15:51:28 +00:00
bevy_diagnostic Apply unused_qualifications lint (#14828) 2024-08-21 12:29:33 +00:00
bevy_dylib Generate links to definition in source code pages on docs.rs and dev-docs.bevyengine.org (#12965) 2024-07-29 23:10:16 +00:00
bevy_ecs Add EntityRefExcept and EntityMutExcept world queries, in preparation for generalized animation. (#15207) 2024-09-17 14:53:39 +00:00
bevy_encase_derive Generate links to definition in source code pages on docs.rs and dev-docs.bevyengine.org (#12965) 2024-07-29 23:10:16 +00:00
bevy_gilrs Update gilrs requirement from 0.10.1 to 0.11.0 (#15245) 2024-09-16 23:34:04 +00:00
bevy_gizmos Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_gltf Reflect derived traits on all components and resources: bevy_gltf (#15218) 2024-09-15 14:47:43 +00:00
bevy_hierarchy Rename Add to Queue for methods with deferred semantics (#15234) 2024-09-17 00:17:49 +00:00
bevy_input Use of deprecated function in example for ButtonInput (#15221) 2024-09-15 15:22:39 +00:00
bevy_internal Remove all existing system order ambiguities in DefaultPlugins (#15031) 2024-09-03 20:24:34 +00:00
bevy_log Unify crate-level preludes (#15080) 2024-09-08 17:10:57 +00:00
bevy_macro_utils Generate links to definition in source code pages on docs.rs and dev-docs.bevyengine.org (#12965) 2024-07-29 23:10:16 +00:00
bevy_math Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_mikktspace Fix underflow panic in InitTriInfo (#14893) 2024-08-25 14:13:23 +00:00
bevy_pbr Rename Add to Queue for methods with deferred semantics (#15234) 2024-09-17 00:17:49 +00:00
bevy_picking Reflect derived traits on all components and resources: bevy_picking (#15225) 2024-09-15 16:17:39 +00:00
bevy_ptr Remove redundent information and optimize dynamic allocations in Table (#12929) 2024-09-16 22:52:05 +00:00
bevy_reflect Use FromReflect when extracting entities in dynamic scenes (#15174) 2024-09-15 14:33:39 +00:00
bevy_render Fix floating point math (#15239) 2024-09-16 23:28:12 +00:00
bevy_scene Rename push children to add children (#15196) 2024-09-16 23:16:04 +00:00
bevy_sprite Reflect derived traits on all components and resources: bevy_sprite (#15227) 2024-09-15 17:10:53 +00:00
bevy_state Rename Add to Queue for methods with deferred semantics (#15234) 2024-09-17 00:17:49 +00:00
bevy_tasks Unify crate-level preludes (#15080) 2024-09-08 17:10:57 +00:00
bevy_text Reflect derived traits on all components and resources: bevy_text (#15229) 2024-09-15 17:21:02 +00:00
bevy_time Unify crate-level preludes (#15080) 2024-09-08 17:10:57 +00:00
bevy_transform Rename Add to Queue for methods with deferred semantics (#15234) 2024-09-17 00:17:49 +00:00
bevy_ui Enable/disable UI anti-aliasing (#15170) 2024-09-16 23:06:23 +00:00
bevy_utils Remove remnant EntityHash and related types from bevy_utils (#15039) 2024-09-09 15:24:17 +00:00
bevy_window Reflect derived traits on all components and resources: bevy_window (#15233) 2024-09-15 17:49:00 +00:00
bevy_winit Remove ReceivedCharacter (#15126) 2024-09-10 00:22:06 +00:00