# 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`
# 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`.
# 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.
# 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>
# Objective
Add a `Populated` system parameter that acts like `Query`, but prevents
system from running if there are no matching entities.
Fixes: #15302
## Solution
Implement the system param which newtypes the `Query`.
The only change is new validation, which fails if query is empty.
The new system param is used in `fallible_params` example.
## Testing
Ran `fallible_params` example.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Improve the documentation of `SystemParamBuilder`. Not all builder types
have documentation, and the documentation is spread around and not
linked together well.
## Solution
Reorganize `SystemParamBuilder` docs and examples. All builder types now
have their own examples, and the list of builder types is linked from
the `SystemParamBuilder` trait. Add some examples to `FilteredEntityRef`
and `FilteredEntityMut` so that `QueryParamBuilder` can reference them.
# Objective
Add the following system params:
- `QuerySingle<D, F>` - Valid if only one matching entity exists,
- `Option<QuerySingle<D, F>>` - Valid if zero or one matching entity
exists.
As @chescock pointed out, we don't need `Mut` variants.
Fixes: #15264
## Solution
Implement the type and both variants of system params.
Also implement `ReadOnlySystemParam` for readonly queries.
Added a new ECS example `fallible_params` which showcases `SingleQuery`
usage.
In the future we might want to add `NonEmptyQuery`,
`NonEmptyEventReader` and `Res` to it (or maybe just stop at mentioning
it).
## Testing
Tested with the example.
There is a lot of warning spam so we might want to implement #15391.
# Objective
- Fixes#6370
- Closes#6581
## Solution
- Added the following lints to the workspace:
- `std_instead_of_core`
- `std_instead_of_alloc`
- `alloc_instead_of_core`
- Used `cargo +nightly fmt` with [item level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Item%5C%3A)
to split all `use` statements into single items.
- Used `cargo clippy --workspace --all-targets --all-features --fix
--allow-dirty` to _attempt_ to resolve the new linting issues, and
intervened where the lint was unable to resolve the issue automatically
(usually due to needing an `extern crate alloc;` statement in a crate
root).
- Manually removed certain uses of `std` where negative feature gating
prevented `--all-features` from finding the offending uses.
- Used `cargo +nightly fmt` with [crate level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Crate%5C%3A)
to re-merge all `use` statements matching Bevy's previous styling.
- Manually fixed cases where the `fmt` tool could not re-merge `use`
statements due to conditional compilation attributes.
## Testing
- Ran CI locally
## Migration Guide
The MSRV is now 1.81. Please update to this version or higher.
## Notes
- This is a _massive_ change to try and push through, which is why I've
outlined the semi-automatic steps I used to create this PR, in case this
fails and someone else tries again in the future.
- Making this change has no impact on user code, but does mean Bevy
contributors will be warned to use `core` and `alloc` instead of `std`
where possible.
- This lint is a critical first step towards investigating `no_std`
options for Bevy.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
- Fixes#15451
## Migration Guide
- `World::init_component` has been renamed to `register_component`.
- `World::init_component_with_descriptor` has been renamed to
`register_component_with_descriptor`.
- `World::init_bundle` has been renamed to `register_bundle`.
- `Components::init_component` has been renamed to `register_component`.
- `Components::init_component_with_descriptor` has been renamed to
`register_component_with_descriptor`.
- `Components::init_resource` has been renamed to `register_resource`.
- `Components::init_non_send` had been renamed to `register_non_send`.
# Objective
- Fixes#14924
- Closes#9584
## Solution
- We introduce a new trait, `SystemInput`, that serves as a type
function from the `'static` form of the input, to its lifetime'd
version, similarly to `SystemParam` or `WorldQuery`.
- System functions now take the lifetime'd wrapped version,
`SystemInput::Param<'_>`, which prevents the issue presented in #14924
(i.e. `InRef<T>`).
- Functions for running systems now take the lifetime'd unwrapped
version, `SystemInput::Inner<'_>` (i.e. `&T`).
- Due to the above change, system piping had to be re-implemented as a
standalone type, rather than `CombinatorSystem` as it was previously.
- Removes the `Trigger<'static, E, B>` transmute in observer runner
code.
## Testing
- All current tests pass.
- Added additional tests and doc-tests.
---
## Showcase
```rust
let mut world = World::new();
let mut value = 2;
// Currently possible:
fn square(In(input): In<usize>) -> usize {
input * input
}
value = world.run_system_once_with(value, square);
// Now possible:
fn square_mut(InMut(input): InMut<usize>) {
*input *= *input;
}
world.run_system_once_with(&mut value, square_mut);
// Or:
fn square_ref(InRef(input): InRef<usize>) -> usize {
*input * *input
}
value = world.run_system_once_with(&value, square_ref);
```
## Migration Guide
- All current explicit usages of the following types must be changed in
the way specified:
- `SystemId<I, O>` to `SystemId<In<I>, O>`
- `System<In = T>` to `System<In = In<T>>`
- `IntoSystem<I, O, M>` to `IntoSystem<In<I>, O, M>`
- `Condition<M, T>` to `Condition<M, In<T>>`
- `In<Trigger<E, B>>` is no longer a valid input parameter type. Use
`Trigger<E, B>` directly, instead.
---------
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
# Objective
The goal of this PR is to introduce `SystemParam` validation in order to
reduce runtime panics.
Fixes#15265
## Solution
`SystemParam` now has a new method `validate_param(...) -> bool`, which
takes immutable variants of `get_param` arguments. The returned value
indicates whether the parameter can be acquired from the world. If
parameters cannot be acquired for a system, it won't be executed,
similarly to run conditions. This reduces panics when using params like
`Res`, `ResMut`, etc. as well as allows for new, ergonomic params like
#15264 or #15302.
Param validation happens at the level of executors. All validation
happens directly before executing a system, in case of normal systems
they are skipped, in case of conditions they return false.
Warning about system skipping is primitive and subject to change in
subsequent PRs.
## Testing
Two executor tests check that all executors:
- skip systems which have invalid parameters:
- piped systems get skipped together,
- dependent systems still run correctly,
- skip systems with invalid run conditions:
- system conditions have invalid parameters,
- system set conditions have invalid parameters.
Enabled `check-private-items` in `clippy.toml` and then fixed the
resulting errors. Most of these were simply misformatted and of the
remaining:
- ~Added `#[allow(clippy::missing_safety_doc)]` to~ Removed unsafe from
a pair of functions in `bevy_utils/futures` which are only unsafe so
that they can be passed to a function which requires `unsafe fn`
- Removed `unsafe` from `UnsafeWorldCell::observers` as from what I can
tell it is always safe like `components`, `bundles` etc. (this should be
checked)
- Added safety docs to:
- `Bundles::get_storage_unchecked`: Based on the function that writes to
`dynamic_component_storages`
- `Bundles::get_storages_unchecked`: Based on the function that writes
to `dynamic_bundle_storages`
- `QueryIterationCursor::init_empty`: Duplicated from `init`
- `QueryIterationCursor::peek_last`: Thanks Giooschi (also added
internal unsafe blocks)
- `tests::drop_ptr`: Moved safety comment out to the doc string
This lint would also apply to `missing_errors_doc`, `missing_panics_doc`
and `unnecessary_safety_doc` if we chose to enable any of those at some
point, although there is an open
[issue](https://github.com/rust-lang/rust-clippy/issues/13074) to
separate these options.
# Objective
Right now, `DynSystemParam::downcast()` always requires the type
parameter to be specified with a turbofish. Make it so that it can be
inferred from the use of the return value, like:
```rust
fn expects_res_a(mut param: DynSystemParam) {
let res: Res<A> = param.downcast().unwrap();
}
```
## Solution
The reason this doesn't currently work is that the type parameter is a
`'static` version of the `SystemParam` so that it can be used with
`Any::downcast_mut()`. Change the method signature so that the type
parameter matches the return type, and use `T::Item<'static, 'static>`
to get the `'static` version. That means we wind up returning a
`T::Item<'static, 'static>::Item<'w, 's>`, so constrain that to be equal
to `T`. That works with every `SystemParam` implementation, since they
have `T::Item == T` up to lifetimes.
# Objective
Allow `SystemParamBuilder` implementations for custom system parameters
created using `#[derive(SystemParam)]`.
## Solution
Extend the derive macro to accept a `#[system_param(builder)]`
attribute. When present, emit a builder type with a field corresponding
to each field of the param.
## Example
```rust
#[derive(SystemParam)]
#[system_param(builder)]
struct CustomParam<'w, 's> {
query: Query<'w, 's, ()>,
local: Local<'s, usize>,
}
let system = (CustomParamBuilder {
local: LocalBuilder(100),
query: QueryParamBuilder::new(|builder| {
builder.with::<A>();
}),
},)
.build_state(&mut world)
.build_system(|param: CustomParam| *param.local + param.query.iter().count());
```
# Objective
Allow dynamic systems to take lists of system parameters whose length is
not known at compile time.
This can be used for building a system that runs a script defined at
runtime, where the script needs a variable number of query parameters.
It can also be used for building a system that collects a list of
plugins at runtime, and provides a parameter to each one.
This is most useful today with `Vec<Query<FilteredEntityMut>>`. It will
be even more useful with `Vec<DynSystemParam>` if #14817 is merged,
since the parameters in the list can then be of different types.
## Solution
Implement `SystemParam` and `SystemParamBuilder` for `Vec` and
`ParamSet<Vec>`.
## Example
```rust
let system = (vec![
QueryParamBuilder::new_box(|builder| {
builder.with::<B>().without::<C>();
}),
QueryParamBuilder::new_box(|builder| {
builder.with::<C>().without::<B>();
}),
],)
.build_state(&mut world)
.build_system(|params: Vec<Query<&mut A>>| {
let mut count: usize = 0;
params
.into_iter()
.for_each(|mut query| count += query.iter_mut().count());
count
});
```
# Objective
Support building systems with parameters whose types can be determined
at runtime.
## Solution
Create a `DynSystemParam` type that can be built using a
`SystemParamBuilder` of any type and then downcast to the appropriate
type dynamically.
## Example
```rust
let system = (
DynParamBuilder::new(LocalBuilder(3_usize)),
DynParamBuilder:🆕:<Query<()>>(QueryParamBuilder::new(|builder| {
builder.with::<A>();
})),
DynParamBuilder:🆕:<&Entities>(ParamBuilder),
)
.build_state(&mut world)
.build_system(
|mut p0: DynSystemParam, mut p1: DynSystemParam, mut p2: DynSystemParam| {
let local = p0.downcast_mut::<Local<usize>>().unwrap();
let query_count = p1.downcast_mut::<Query<()>>().unwrap();
let entities = p2.downcast_mut::<&Entities>().unwrap();
},
);
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Periwink <charlesbour@gmail.com>
# Objective
`ParamSetBuilder` is supposed to be used as a tuple constructor, but the
field was not marked `pub` so it's not actually usable outside of its
module.
## Solution
Mark the field `pub`.
Realize one advantage of doc tests over unit tests is that they test the
public API.
Add a doc test example that uses the field so that this would have been
caught.
# Objective
`Res` and `ResMut` perform redundant lookups of the resource storage,
first to initialize the `ArchetypeComponentId` and then to retrieve it.
## Solution
Use the `archetype_component_id` returned from
`initialize_resource_internal` to avoid an extra lookup and `unwrap()`.
# Objective
- Fixes#14697
## Solution
This PR modifies the existing `all_tuples!` macro to optionally accept a
`#[doc(fake_variadic)]` attribute in its input. If the attribute is
present, each invocation of the impl macro gets the correct attributes
(i.e. the first impl receives `#[doc(fake_variadic)]` while the other
impls are hidden using `#[doc(hidden)]`.
Impls for the empty tuple (unit type) are left untouched (that's what
the [standard
library](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq-for-())
and
[serde](https://docs.rs/serde/latest/serde/trait.Serialize.html#impl-Serialize-for-())
do).
To work around https://github.com/rust-lang/cargo/issues/8811 and to get
impls on re-exports to correctly show up as variadic, `--cfg docsrs_dep`
is passed when building the docs for the toplevel `bevy` crate.
`#[doc(fake_variadic)]` only works on tuples and fn pointers, so impls
for structs like `AnyOf<(T1, T2, ..., Tn)>` are unchanged.
## Testing
I built the docs locally using `RUSTDOCFLAGS='--cfg docsrs'
RUSTFLAGS='--cfg docsrs_dep' cargo +nightly doc --no-deps --workspace`
and checked the documentation page of a trait both in its original crate
and the re-exported version in `bevy`.
The description should correctly mention for how many tuple items the
trait is implemented.
I added `rustc-args` for docs.rs to the `bevy` crate, I hope there
aren't any other notable crates that re-export `#[doc(fake_variadic)]`
traits.
---
## Showcase
`bevy_ecs::query::QueryData`:
<img width="1015" alt="Screenshot 2024-08-12 at 16 41 28"
src="https://github.com/user-attachments/assets/d40136ed-6731-475f-91a0-9df255cd24e3">
`bevy::ecs::query::QueryData` (re-export):
<img width="1005" alt="Screenshot 2024-08-12 at 16 42 57"
src="https://github.com/user-attachments/assets/71d44cf0-0ab0-48b0-9a51-5ce332594e12">
## Original Description
<details>
Resolves#14697
Submitting as a draft for now, very WIP.
Unfortunately, the docs don't show the variadics nicely when looking at
reexported items.
For example:
`bevy_ecs::bundle::Bundle` correctly shows the variadic impl:

while `bevy::ecs::bundle::Bundle` (the reexport) shows all the impls
(not good):

Built using `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --workspace
--no-deps` (`--no-deps` because of wgpu-core).
Maybe I missed something or this is a limitation in the *totally not
private* `#[doc(fake_variadic)]` thingy. In any case I desperately need
some sleep now :))
</details>
# Objective
Support more kinds of system params in buildable systems, such as a
`ParamSet` or `Vec` containing buildable params or tuples of buildable
params.
## Solution
Replace the `BuildableSystemParam` trait with `SystemParamBuilder` to
make it easier to compose builders. Provide implementations for existing
buildable params, plus tuples, `ParamSet`, and `Vec`.
## Examples
```rust
// ParamSet of tuple:
let system = (ParamSetBuilder((
QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
QueryParamBuilder::new(|builder| { builder.with::<C>(); }),
)),)
.build_state(&mut world)
.build_system(|mut params: ParamSet<(Query<&mut A>, Query<&mut A>)>| {
params.p0().iter().count() + params.p1().iter().count()
});
// ParamSet of Vec:
let system = (ParamSetBuilder(vec![
QueryParamBuilder::new_box(|builder| { builder.with::<B>(); }),
QueryParamBuilder::new_box(|builder| { builder.with::<C>(); }),
]),)
.build_state(&mut world)
.build_system(|mut params: ParamSet<Vec<Query<&mut A>>>| {
let mut count = 0;
params.for_each(|mut query| count += query.iter_mut().count());
count
});
```
## Migration Guide
The API for `SystemBuilder` has changed. Instead of constructing a
builder with a world and then adding params, you first create a tuple of
param builders and then supply the world.
```rust
// Before
let system = SystemBuilder::<()>::new(&mut world)
.local::<u64>()
.builder::<Local<u64>>(|x| *x = 10)
.builder::<Query<&A>>(|builder| { builder.with::<B>(); })
.build(system);
// After
let system = (
ParamBuilder,
LocalBuilder(10),
QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
)
.build_state(&mut world)
.build_system(system);
```
## Possible Future Work
Here are a few possible follow-up changes. I coded them up to prove that
this API can support them, but they aren't necessary for this PR.
* chescock/bevy#1
* chescock/bevy#2
* chescock/bevy#3
# Objective
- Fixes https://github.com/bevyengine/bevy/issues/14575
- There is a soundness issue because we use `conflicts()` to check for
system ambiguities + soundness issues. However since the current
conflicts is a `Vec<T>`, we cannot express conflicts where there is no
specific `ComponentId` at fault. For example `q1: Query<EntityMut>, q2:
Query<EntityMut>`
There was a TODO to handle the `write_all` case but it was never
resolved
## Solution
- Introduce an `AccessConflict` enum that is either a list of specific
ids that are conflicting or `All` if all component ids are conflicting
## Testing
- Introduced a new unit test to check for the `EntityMut` case
## Migration guide
The `get_conflicts` method of `Access` now returns an `AccessConflict`
enum instead of simply a `Vec` of `ComponentId`s that are causing the
access conflict. This can be useful in cases where there are no
particular `ComponentId`s conflicting, but instead **all** of them are;
for example `fn system(q1: Query<EntityMut>, q2: Query<EntityRef>)`
# Objective
- Make it possible to know *what* changed your component or resource.
- Common need when debugging, when you want to know the last code
location that mutated a value in the ECS.
- This feature would be very useful for the editor alongside system
stepping.
## Solution
- Adds the caller location to column data.
- Mutations now `track_caller` all the way up to the public API.
- Commands that invoke these functions immediately call
`Location::caller`, and pass this into the functions, instead of the
functions themselves attempting to get the caller. This would not work
for commands which are deferred, as the commands are executed by the
scheduler, not the user's code.
## Testing
- The `component_change_detection` example now shows where the component
was mutated:
```
2024-07-28T06:57:48.946022Z INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(0.0)
2024-07-28T06:57:49.004371Z INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(1.0)
2024-07-28T06:57:49.012738Z WARN component_change_detection: Change detected!
-> value: Ref(MyComponent(1.0))
-> added: false
-> changed: true
-> changed by: examples/ecs/component_change_detection.rs:36:23
```
- It's also possible to inspect change location from a debugger:
<img width="608" alt="image"
src="https://github.com/user-attachments/assets/c90ecc7a-0462-457a-80ae-42e7f5d346b4">
---
## Changelog
- Added source locations to ECS change detection behind the
`track_change_detection` flag.
## Migration Guide
- Added `changed_by` field to many internal ECS functions used with
change detection when the `track_change_detection` feature flag is
enabled. Use Location::caller() to provide the source of the function
call.
---------
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
Fixes#14248 and other URL issues.
## Solution
- Describe the solution used to achieve the objective above.
Removed the random #s in the URL. Led users to the wrong page. For
example, https://bevyengine.org/learn/errors/#b0003 takes users to
https://bevyengine.org/learn/errors/introduction, which is not the right
page. Removing the #s fixes it.
## Testing
- Did you test these changes? If so, how?
I pasted the URL into my address bar and it took me to the right place.
- Are there any parts that need more testing?
No
# Objective
`StaticSystemParam` should delegate all `SystemParam` methods to the
inner param, but it looks like it was missed when the new `queue()`
method was added in #10839.
## Solution
Implement `StaticSystemParam::queue()` to delegate to the inner param.
# Objective
- Provide an expressive way to register dynamic behavior in response to
ECS changes that is consistent with existing bevy types and traits as to
provide a smooth user experience.
- Provide a mechanism for immediate changes in response to events during
command application in order to facilitate improved query caching on the
path to relations.
## Solution
- A new fundamental ECS construct, the `Observer`; inspired by flec's
observers but adapted to better fit bevy's access patterns and rust's
type system.
---
## Examples
There are 3 main ways to register observers. The first is a "component
observer" that looks like this:
```rust
world.observe(|trigger: Trigger<OnAdd, Transform>, query: Query<&Transform>| {
let transform = query.get(trigger.entity()).unwrap();
});
```
The above code will spawn a new entity representing the observer that
will run it's callback whenever the `Transform` component is added to an
entity. This is a system-like function that supports dependency
injection for all the standard bevy types: `Query`, `Res`, `Commands`
etc. It also has a `Trigger` parameter that provides information about
the trigger such as the target entity, and the event being triggered.
Importantly these systems run during command application which is key
for their future use to keep ECS internals up to date. There are similar
events for `OnInsert` and `OnRemove`, and this will be expanded with
things such as `ArchetypeCreated`, `TableEmpty` etc. in follow up PRs.
Another way to register an observer is an "entity observer" that looks
like this:
```rust
world.entity_mut(entity).observe(|trigger: Trigger<Resize>| {
// ...
});
```
Entity observers run whenever an event of their type is triggered
targeting that specific entity. This type of observer will de-spawn
itself if the entity (or entities) it is observing is ever de-spawned so
as to not leave dangling observers.
Entity observers can also be spawned from deferred contexts such as
other observers, systems, or hooks using commands:
```rust
commands.entity(entity).observe(|trigger: Trigger<Resize>| {
// ...
});
```
Observers are not limited to in built event types, they can be used with
any type that implements `Event` (which has been extended to implement
Component). This means events can also carry data:
```rust
#[derive(Event)]
struct Resize { x: u32, y: u32 }
commands.entity(entity).observe(|trigger: Trigger<Resize>, query: Query<&mut Size>| {
let event = trigger.event();
// ...
});
// Will trigger the observer when commands are applied.
commands.trigger_targets(Resize { x: 10, y: 10 }, entity);
```
You can also trigger events that target more than one entity at a time:
```rust
commands.trigger_targets(Resize { x: 10, y: 10 }, [e1, e2]);
```
Additionally, Observers don't _need_ entity targets:
```rust
app.observe(|trigger: Trigger<Quit>| {
})
commands.trigger(Quit);
```
In these cases, `trigger.entity()` will be a placeholder.
Observers are actually just normal entities with an `ObserverState` and
`Observer` component! The `observe()` functions above are just shorthand
for:
```rust
world.spawn(Observer::new(|trigger: Trigger<Resize>| {});
```
This will spawn the `Observer` system and use an `on_add` hook to add
the `ObserverState` component.
Dynamic components and trigger types are also fully supported allowing
for runtime defined trigger types.
## Possible Follow-ups
1. Deprecate `RemovedComponents`, observers should fulfill all use cases
while being more flexible and performant.
2. Queries as entities: Swap queries to entities and begin using
observers listening to archetype creation triggers to keep their caches
in sync, this allows unification of `ObserverState` and `QueryState` as
well as unlocking several API improvements for `Query` and the
management of `QueryState`.
3. Trigger bubbling: For some UI use cases in particular users are
likely to want some form of bubbling for entity observers, this is
trivial to implement naively but ideally this includes an acceleration
structure to cache hierarchy traversals.
4. All kinds of other in-built trigger types.
5. Optimization; in order to not bloat the complexity of the PR I have
kept the implementation straightforward, there are several areas where
performance can be improved. The focus for this PR is to get the
behavior implemented and not incur a performance cost for users who
don't use observers.
I am leaving each of these to follow up PR's in order to keep each of
them reviewable as this already includes significant changes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Implement a general purpose mechanism for building `SystemParam`.
- Unblock the usage of dynamic queries in regular systems.
## Solution
- Implement a `SystemBuilder` type.
## Examples
Here are some simple test cases for the builder:
```rust
fn local_system(local: Local<u64>) -> u64 {
*local
}
fn query_system(query: Query<()>) -> usize {
query.iter().count()
}
fn multi_param_system(a: Local<u64>, b: Local<u64>) -> u64 {
*a + *b + 1
}
#[test]
fn local_builder() {
let mut world = World::new();
let system = SystemBuilder::<()>::new(&mut world)
.builder::<Local<u64>>(|x| *x = 10)
.build(local_system);
let result = world.run_system_once(system);
assert_eq!(result, 10);
}
#[test]
fn query_builder() {
let mut world = World::new();
world.spawn(A);
world.spawn_empty();
let system = SystemBuilder::<()>::new(&mut world)
.builder::<Query<()>>(|query| {
query.with::<A>();
})
.build(query_system);
let result = world.run_system_once(system);
assert_eq!(result, 1);
}
#[test]
fn multi_param_builder() {
let mut world = World::new();
world.spawn(A);
world.spawn_empty();
let system = SystemBuilder::<()>::new(&mut world)
.param::<Local<u64>>()
.param::<Local<u64>>()
.build(multi_param_system);
let result = world.run_system_once(system);
assert_eq!(result, 1);
}
```
This will be expanded as this PR is iterated.
# Objective
- Fixes#12377
## Solution
Added simple `#[diagnostic::on_unimplemented(...)]` attributes to some
critical public traits providing a more approachable initial error
message. Where appropriate, a `note` is added indicating that a `derive`
macro is available.
## Examples
<details>
<summary>Examples hidden for brevity</summary>
Below is a collection of examples showing the new error messages
produced by this change. In general, messages will start with a more
Bevy-centric error message (e.g., _`MyComponent` is not a `Component`_),
and a note directing the user to an available derive macro where
appropriate.
### Missing `#[derive(Resource)]`
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
struct MyResource;
fn main() {
App::new()
.insert_resource(MyResource)
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `MyResource` is not a `Resource`
--> examples/app/empty.rs:7:26
|
7 | .insert_resource(MyResource)
| --------------- ^^^^^^^^^^ invalid `Resource`
| |
| required by a bound introduced by this call
|
= help: the trait `Resource` is not implemented for `MyResource`
= note: consider annotating `MyResource` with `#[derive(Resource)]`
= help: the following other types implement trait `Resource`:
AccessibilityRequested
ManageAccessibilityUpdates
bevy::bevy_a11y::Focus
DiagnosticsStore
FrameCount
bevy::prelude::State<S>
SystemInfo
bevy::prelude::Axis<T>
and 141 others
note: required by a bound in `bevy::prelude::App::insert_resource`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:419:31
|
419 | pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
| ^^^^^^^^ required by this bound in `App::insert_resource`
```
</details>
### Putting A `QueryData` in a `QueryFilter` Slot
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
#[derive(Component)]
struct A;
#[derive(Component)]
struct B;
fn my_system(_query: Query<&A, &B>) {}
fn main() {
App::new()
.add_systems(Update, my_system)
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `&B` is not a valid `Query` filter
--> examples/app/empty.rs:9:22
|
9 | fn my_system(_query: Query<&A, &B>) {}
| ^^^^^^^^^^^^^ invalid `Query` filter
|
= help: the trait `QueryFilter` is not implemented for `&B`
= help: the following other types implement trait `QueryFilter`:
With<T>
Without<T>
bevy::prelude::Or<()>
bevy::prelude::Or<(F0,)>
bevy::prelude::Or<(F0, F1)>
bevy::prelude::Or<(F0, F1, F2)>
bevy::prelude::Or<(F0, F1, F2, F3)>
bevy::prelude::Or<(F0, F1, F2, F3, F4)>
and 28 others
note: required by a bound in `bevy::prelude::Query`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\query.rs:349:51
|
349 | pub struct Query<'world, 'state, D: QueryData, F: QueryFilter = ()> {
| ^^^^^^^^^^^ required by this bound in `Query`
```
</details>
### Missing `#[derive(Component)]`
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
struct A;
fn my_system(mut commands: Commands) {
commands.spawn(A);
}
fn main() {
App::new()
.add_systems(Startup, my_system)
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `A` is not a `Bundle`
--> examples/app/empty.rs:6:20
|
6 | commands.spawn(A);
| ----- ^ invalid `Bundle`
| |
| required by a bound introduced by this call
|
= help: the trait `bevy::prelude::Component` is not implemented for `A`, which is required by `A: Bundle`
= note: consider annotating `A` with `#[derive(Component)]` or `#[derive(Bundle)]`
= help: the following other types implement trait `Bundle`:
TransformBundle
SceneBundle
DynamicSceneBundle
AudioSourceBundle<Source>
SpriteBundle
SpriteSheetBundle
Text2dBundle
MaterialMesh2dBundle<M>
and 34 others
= note: required for `A` to implement `Bundle`
note: required by a bound in `bevy::prelude::Commands::<'w, 's>::spawn`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\commands\mod.rs:243:21
|
243 | pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
| ^^^^^^ required by this bound in `Commands::<'w, 's>::spawn`
```
</details>
### Missing `#[derive(Asset)]`
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
struct A;
fn main() {
App::new()
.init_asset::<A>()
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `A` is not an `Asset`
--> examples/app/empty.rs:7:23
|
7 | .init_asset::<A>()
| ---------- ^ invalid `Asset`
| |
| required by a bound introduced by this call
|
= help: the trait `Asset` is not implemented for `A`
= note: consider annotating `A` with `#[derive(Asset)]`
= help: the following other types implement trait `Asset`:
Font
AnimationGraph
DynamicScene
Scene
AudioSource
Pitch
bevy::bevy_gltf::Gltf
GltfNode
and 17 others
note: required by a bound in `init_asset`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_asset\src\lib.rs:307:22
|
307 | fn init_asset<A: Asset>(&mut self) -> &mut Self;
| ^^^^^ required by this bound in `AssetApp::init_asset`
```
</details>
### Mismatched Input and Output on System Piping
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
fn producer() -> u32 {
123
}
fn consumer(_: In<u16>) {}
fn main() {
App::new()
.add_systems(Update, producer.pipe(consumer))
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `fn(bevy::prelude::In<u16>) {consumer}` is not a valid system with input `u32` and output `_`
--> examples/app/empty.rs:11:44
|
11 | .add_systems(Update, producer.pipe(consumer))
| ---- ^^^^^^^^ invalid system
| |
| required by a bound introduced by this call
|
= help: the trait `bevy::prelude::IntoSystem<u32, _, _>` is not implemented for fn item `fn(bevy::prelude::In<u16>) {consumer}`
= note: expecting a system which consumes `u32` and produces `_`
note: required by a bound in `pipe`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_ecs\src\system\mod.rs:168:12
|
166 | fn pipe<B, Final, MarkerB>(self, system: B) -> PipeSystem<Self::System, B::System>
| ---- required by a bound in this associated function
167 | where
168 | B: IntoSystem<Out, Final, MarkerB>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `IntoSystem::pipe`
```
</details>
### Missing Reflection
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
#[derive(Component)]
struct MyComponent;
fn main() {
App::new()
.register_type::<MyComponent>()
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `MyComponent` does not provide type registration information
--> examples/app/empty.rs:8:26
|
8 | .register_type::<MyComponent>()
| ------------- ^^^^^^^^^^^ the trait `GetTypeRegistration` is not implemented for `MyComponent`
| |
| required by a bound introduced by this call
|
= note: consider annotating `MyComponent` with `#[derive(Reflect)]`
= help: the following other types implement trait `GetTypeRegistration`:
bool
char
isize
i8
i16
i32
i64
i128
and 443 others
note: required by a bound in `bevy::prelude::App::register_type`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:619:29
|
619 | pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::register_type`
```
</details>
### Missing `#[derive(States)]` Implementation
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash)]
enum AppState {
#[default]
Menu,
InGame {
paused: bool,
turbo: bool,
},
}
fn main() {
App::new()
.init_state::<AppState>()
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: the trait bound `AppState: FreelyMutableState` is not satisfied
--> examples/app/empty.rs:15:23
|
15 | .init_state::<AppState>()
| ---------- ^^^^^^^^ the trait `FreelyMutableState` is not implemented for `AppState`
| |
| required by a bound introduced by this call
|
= note: consider annotating `AppState` with `#[derive(States)]`
note: required by a bound in `bevy::prelude::App::init_state`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:282:26
|
282 | pub fn init_state<S: FreelyMutableState + FromWorld>(&mut self) -> &mut Self {
| ^^^^^^^^^^^^^^^^^^ required by this bound in `App::init_state`
```
</details>
### Adding a `System` with Unhandled Output
<details>
<summary>Example Code</summary>
```rust
use bevy::prelude::*;
fn producer() -> u32 {
123
}
fn main() {
App::new()
.add_systems(Update, consumer)
.run();
}
```
</details>
<details>
<summary>Error Generated</summary>
```error
error[E0277]: `fn() -> u32 {producer}` does not describe a valid system configuration
--> examples/app/empty.rs:9:30
|
9 | .add_systems(Update, producer)
| ----------- ^^^^^^^^ invalid system configuration
| |
| required by a bound introduced by this call
|
= help: the trait `IntoSystem<(), (), _>` is not implemented for fn item `fn() -> u32 {producer}`, which is required by `fn() -> u32 {producer}: IntoSystemConfigs<_>`
= help: the following other types implement trait `IntoSystemConfigs<Marker>`:
<Box<(dyn bevy::prelude::System<In = (), Out = ()> + 'static)> as IntoSystemConfigs<()>>
<NodeConfigs<Box<(dyn bevy::prelude::System<In = (), Out = ()> + 'static)>> as IntoSystemConfigs<()>>
<(S0,) as IntoSystemConfigs<(SystemConfigTupleMarker, P0)>>
<(S0, S1) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1)>>
<(S0, S1, S2) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2)>>
<(S0, S1, S2, S3) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3)>>
<(S0, S1, S2, S3, S4) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3, P4)>>
<(S0, S1, S2, S3, S4, S5) as IntoSystemConfigs<(SystemConfigTupleMarker, P0, P1, P2, P3, P4, P5)>>
and 14 others
= note: required for `fn() -> u32 {producer}` to implement `IntoSystemConfigs<_>`
note: required by a bound in `bevy::prelude::App::add_systems`
--> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:342:23
|
339 | pub fn add_systems<M>(
| ----------- required by a bound in this associated function
...
342 | systems: impl IntoSystemConfigs<M>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::add_systems`
```
</details>
</details>
## Testing
CI passed locally.
## Migration Guide
Upgrade to version 1.78 (or higher) of Rust.
## Future Work
- Currently, hints are not supported in this diagnostic. Ideally,
suggestions like _"consider using ..."_ would be in a hint rather than a
note, but that is the best option for now.
- System chaining and other `all_tuples!(...)`-based traits have bad
error messages due to the slightly different error message format.
---------
Co-authored-by: Jamie Ridding <Themayu@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
# 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
- There are several redundant imports in the tests and examples that are
not caught by CI because additional flags need to be passed.
## Solution
- Run `cargo check --workspace --tests` and `cargo check --workspace
--examples`, then fix all warnings.
- Add `test-check` to CI, which will be run in the check-compiles job.
This should catch future warnings for tests. Examples are already
checked, but I'm not yet sure why they weren't caught.
## Discussion
- Should the `--tests` and `--examples` flags be added to CI, so this is
caught in the future?
- If so, #12818 will need to be merged first. It was also a warning
raised by checking the examples, but I chose to split off into a
separate PR.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
Fix Pr CI failing over dead code in tests and main branch CI failing
over a missing semicolon. Fixes#12620.
## Solution
Add dead_code annotations and a semicolon.
# Objective
`QueryState::archetype_component_access` is only really ever used to
extend `SystemMeta`'s. It can be removed to save some memory for every
`Query` in an app.
## Solution
* Remove it.
* Have `new_archetype` pass in a `&mut Access<ArchetypeComponentId>`
instead and pull it from `SystemMeta` directly.
* Split `QueryState::new` from `QueryState::new_with_access` and a
common `QueryState::new_uninitialized`.
* Split `new_archetype` into an internal and public version. Call the
internal version in `update_archetypes`.
This should make it faster to construct new QueryStates, and by proxy
lenses and joins as well.
`matched_tables` also similarly is only used to deduplicate inserting
into `matched_table_ids`. If we can find another efficient way to do so,
it might also be worth removing.
The [generated
assembly](https://github.com/james7132/bevy_asm_tests/compare/main...remove-query-state-archetype-component-access#diff-496530101f0b16e495b7e9b77c0e906ae3068c8adb69ed36c92d5a1be5a9efbe)
reflects this well, with all of the access related updates in
`QueryState` being removed.
---
## Changelog
Removed: `QueryState::archetype_component_access`.
Changed: `QueryState::new_archetype` now takes a `&mut
Access<ArchetypeComponentId>` argument, which will be updated with the
new accesses.
Changed: `QueryState::update_archetype_component_access` now takes a
`&mut Access<ArchetypeComponentId>` argument, which will be updated with
the new accesses.
## Migration Guide
TODO
# Objective
`initialize_resource<T>` and it's non-send equivalent is only used in
two locations each. Fix#6285.
## Solution
Remove them, replace their calls with their internals. Cut down on a bit
of generic codegen.
This does mean that `initialize_resource_internal` is now `pub(crate)`,
but that's likely OK given that only one variant will remain once
NonSend resources are removed from the World.
# Objective
- Part of #11590
- Fix `unsafe_op_in_unsafe_fn` for trivial cases in bevy_ecs
## Solution
Fix `unsafe_op_in_unsafe_fn` in bevy_ecs for trivial cases, i.e., add an
`unsafe` block when the safety comment already exists or add a comment
like "The invariants are uphold by the caller".
---------
Co-authored-by: James Liu <contact@jamessliu.com>
# Objective
We deprecated quite a few APIs in 0.13. 0.13 has shipped already. It
should be OK to remove them in 0.14's release. Fixes#4059. Fixes#9011.
## Solution
Remove them.
# Objective
It would be convenient to be able to call functions with `Commands` as a
parameter without having to move your own instance of `Commands`. Since
this struct is composed entirely of references, we can easily get an
owned instance of `Commands` by shortening the lifetime.
## Solution
Add `Commands::reborrow`, `EntiyCommands::reborrow`, and
`Deferred::reborrow`, which returns an owned version of themselves with
a shorter lifetime.
Remove unnecessary lifetimes from `EntityCommands`. The `'w` and `'s`
lifetimes only have to be separate for `Commands` because it's used as a
`SystemParam` -- this is not the case for `EntityCommands`.
---
## Changelog
Added `Commands::reborrow`. This is useful if you have `&mut Commands`
but need `Commands`. Also added `EntityCommands::reborrow` and
`Deferred:reborrow` which serve the same purpose.
## Migration Guide
The lifetimes for `EntityCommands` have been simplified.
```rust
// Before (Bevy 0.12)
struct MyStruct<'w, 's, 'a> {
commands: EntityCommands<'w, 's, 'a>,
}
// After (Bevy 0.13)
struct MyStruct<'a> {
commands: EntityCommands<'a>,
}
```
The method `EntityCommands::commands` now returns `Commands` rather than
`&mut Commands`.
```rust
// Before (Bevy 0.12)
let commands = entity_commands.commands();
commands.spawn(...);
// After (Bevy 0.13)
let mut commands = entity_commands.commands();
commands.spawn(...);
```
# Objective
Document a few common cases of which lifetime is required when using
SystemParam Derive
## Solution
Added a table in the doc comment
---------
Co-authored-by: laund <me@laund.moe>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
`SystemName` might be useful in systems which accept `&mut World`.
## Solution
- `impl ExclusiveSystemParam for SystemName`
- move `SystemName` into a separate file, because it no longer belongs
to a file which defines `SystemParam`
- add a test for new impl, and for existing impl
## Changelog
- `impl ExclusiveSystemParam for SystemName`
# Objective
- Users are often confused when their command effects are not visible in
the next system. This PR auto inserts sync points if there are deferred
buffers on a system and there are dependents on that system (systems
with after relationships).
- Manual sync points can lead to users adding more than needed and it's
hard for the user to have a global understanding of their system graph
to know which sync points can be merged. However we can easily calculate
which sync points can be merged automatically.
## Solution
1. Add new edge types to allow opting out of new behavior
2. Insert an sync point for each edge whose initial node has deferred
system params.
3. Reuse nodes if they're at the number of sync points away.
* add opt outs for specific edges with `after_ignore_deferred`,
`before_ignore_deferred` and `chain_ignore_deferred`. The
`auto_insert_apply_deferred` boolean on `ScheduleBuildSettings` can be
set to false to opt out for the whole schedule.
## Perf
This has a small negative effect on schedule build times.
```text
group auto-sync main-for-auto-sync
----- ----------- ------------------
build_schedule/1000_schedule 1.06 2.8±0.15s ? ?/sec 1.00 2.7±0.06s ? ?/sec
build_schedule/1000_schedule_noconstraints 1.01 26.2±0.88ms ? ?/sec 1.00 25.8±0.36ms ? ?/sec
build_schedule/100_schedule 1.02 13.1±0.33ms ? ?/sec 1.00 12.9±0.28ms ? ?/sec
build_schedule/100_schedule_noconstraints 1.08 505.3±29.30µs ? ?/sec 1.00 469.4±12.48µs ? ?/sec
build_schedule/500_schedule 1.00 485.5±6.29ms ? ?/sec 1.00 485.5±9.80ms ? ?/sec
build_schedule/500_schedule_noconstraints 1.00 6.8±0.10ms ? ?/sec 1.02 6.9±0.16ms ? ?/sec
```
---
## Changelog
- Auto insert sync points and added `after_ignore_deferred`,
`before_ignore_deferred`, `chain_no_deferred` and
`auto_insert_apply_deferred` APIs to opt out of this behavior
## Migration Guide
- `apply_deferred` points are added automatically when there is ordering
relationship with a system that has deferred parameters like `Commands`.
If you want to opt out of this you can switch from `after`, `before`,
and `chain` to the corresponding `ignore_deferred` API,
`after_ignore_deferred`, `before_ignore_deferred` or
`chain_ignore_deferred` for your system/set ordering.
- You can also set `ScheduleBuildSettings::auto_insert_sync_points` to
`false` if you want to do it for the whole schedule. Note that in this
mode you can still add `apply_deferred` points manually.
- For most manual insertions of `apply_deferred` you should remove them
as they cannot be merged with the automatically inserted points and
might reduce parallelizability of the system graph.
## TODO
- [x] remove any apply_deferred used in the engine
- [x] ~~decide if we should deprecate manually using apply_deferred.~~
We'll still allow inserting manual sync points for now for whatever edge
cases users might have.
- [x] Update migration guide
- [x] rerun schedule build benchmarks
---------
Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
# Objective
Since #10776 split `WorldQuery` to `WorldQueryData` and
`WorldQueryFilter`, it should be clear that the query is actually
composed of two parts. It is not factually correct to call "query" only
the data part. Therefore I suggest to rename the `Q` parameter to `D` in
`Query` and related items.
As far as I know, there shouldn't be breaking changes from renaming
generic type parameters.
## Solution
I used a combination of rust-analyzer go to reference and `Ctrl-F`ing
various patterns to catch as many cases as possible. Hopefully I got
them all. Feel free to check if you're concerned of me having missed
some.
## Notes
This and #10779 have many lines in common, so merging one will cause a
lot of merge conflicts to the other.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Shorten paths by removing unnecessary prefixes
## Solution
- Remove the prefixes from many paths which do not need them. Finding
the paths was done automatically using built-in refactoring tools in
Jetbrains RustRover.
# Objective
- Fixes#7680
- This is an updated for https://github.com/bevyengine/bevy/pull/8899
which had the same objective but fell a long way behind the latest
changes
## Solution
The traits `WorldQueryData : WorldQuery` and `WorldQueryFilter :
WorldQuery` have been added and some of the types and functions from
`WorldQuery` has been moved into them.
`ReadOnlyWorldQuery` has been replaced with `ReadOnlyWorldQueryData`.
`WorldQueryFilter` is safe (as long as `WorldQuery` is implemented
safely).
`WorldQueryData` is unsafe - safely implementing it requires that
`Self::ReadOnly` is a readonly version of `Self` (this used to be a
safety requirement of `WorldQuery`)
The type parameters `Q` and `F` of `Query` must now implement
`WorldQueryData` and `WorldQueryFilter` respectively.
This makes it impossible to accidentally use a filter in the data
position or vice versa which was something that could lead to bugs.
~~Compile failure tests have been added to check this.~~
It was previously sometimes useful to use `Option<With<T>>` in the data
position. Use `Has<T>` instead in these cases.
The `WorldQuery` derive macro has been split into separate derive macros
for `WorldQueryData` and `WorldQueryFilter`.
Previously it was possible to derive both `WorldQuery` for a struct that
had a mixture of data and filter items. This would not work correctly in
some cases but could be a useful pattern in others. *This is no longer
possible.*
---
## Notes
- The changes outside of `bevy_ecs` are all changing type parameters to
the new types, updating the macro use, or replacing `Option<With<T>>`
with `Has<T>`.
- All `WorldQueryData` types always returned `true` for `IS_ARCHETYPAL`
so I moved it to `WorldQueryFilter` and
replaced all calls to it with `true`. That should be the only logic
change outside of the macro generation code.
- `Changed<T>` and `Added<T>` were being generated by a macro that I
have expanded. Happy to revert that if desired.
- The two derive macros share some functions for implementing
`WorldQuery` but the tidiest way I could find to implement them was to
give them a ton of arguments and ask clippy to ignore that.
## Changelog
### Changed
- Split `WorldQuery` into `WorldQueryData` and `WorldQueryFilter` which
now have separate derive macros. It is not possible to derive both for
the same type.
- `Query` now requires that the first type argument implements
`WorldQueryData` and the second implements `WorldQueryFilter`
## Migration Guide
- Update derives
```rust
// old
#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct CustomQuery {
entity: Entity,
a: &'static mut ComponentA
}
#[derive(WorldQuery)]
struct QueryFilter {
_c: With<ComponentC>
}
// new
#[derive(WorldQueryData)]
#[world_query_data(mutable, derive(Debug))]
struct CustomQuery {
entity: Entity,
a: &'static mut ComponentA,
}
#[derive(WorldQueryFilter)]
struct QueryFilter {
_c: With<ComponentC>
}
```
- Replace `Option<With<T>>` with `Has<T>`
```rust
/// old
fn my_system(query: Query<(Entity, Option<With<ComponentA>>)>)
{
for (entity, has_a_option) in query.iter(){
let has_a:bool = has_a_option.is_some();
//todo!()
}
}
/// new
fn my_system(query: Query<(Entity, Has<ComponentA>)>)
{
for (entity, has_a) in query.iter(){
//todo!()
}
}
```
- Fix queries which had filters in the data position or vice versa.
```rust
// old
fn my_system(query: Query<(Entity, With<ComponentA>)>)
{
for (entity, _) in query.iter(){
//todo!()
}
}
// new
fn my_system(query: Query<Entity, With<ComponentA>>)
{
for entity in query.iter(){
//todo!()
}
}
// old
fn my_system(query: Query<AnyOf<(&ComponentA, With<ComponentB>)>>)
{
for (entity, _) in query.iter(){
//todo!()
}
}
// new
fn my_system(query: Query<Option<&ComponentA>, Or<(With<ComponentA>, With<ComponentB>)>>)
{
for entity in query.iter(){
//todo!()
}
}
```
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>