Commit graph

553 commits

Author SHA1 Message Date
iiYese
5b899b48f5
Better SystemId to Entity conversions (#13090)
# Objective

- Better `SystemId` <-> `Entity` conversion.

## Solution

- Provide a method `SystemId::from_entity` to create a `SystemId<I, O>`
form an `Entity`. When users want to deal with the entities manually
they need a way to convert the `Entity` back to a `SystemId` to actually
run the system with `Commands` or `World`.
- Provide a method `SystemId::entity` that returns an `Entity` from
`SystemId`. The current `From` impl is not very discoverable as it does
not appear on the `SystemId` doc page.
- Remove old `From` impl.

## Migration Guide

```rust
let system_id = world.register_system(my_sys);

// old
let entity = Entity::from(system_id);

// new
let entity = system_id.entity();
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-04-25 18:47:49 +00:00
BD103
c8d214d505
Add #[track_caller] to Query methods (#12984)
# Objective

- Closes #12958

## Solution

- Find all methods under `Query` that mention panicking, and add
`#[track_caller]` to them.

---

## Changelog

- Added `#[track_caller]` to `Query::many`, `Query::many_mut`,
`Query::transmute_lens`, and `Query::transmute_lens_filtered`.

## For reviewers

I'm unfamiliar with the depths of the `Query` struct. Please check
whether it makes since for the updated methods to have
`#[track_caller]`, and if I missed any!
2024-04-24 04:51:18 +00:00
Jonathan
e9be54b0ea
Parallel event reader (#12554)
# 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>
2024-04-22 16:37:42 +00:00
James Liu
54456b7ea6
Make SystemParam::new_archetype and QueryState::new_archetype unsafe functions (#13044)
# 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.
2024-04-21 02:49:42 +00:00
targrub
8316166622
Fix uses of "it's" vs "its". (#13033)
Grammar changes only.
2024-04-19 18:17:31 +00:00
Peter Hayman
f516de456b
Add EntityWorldMut::remove_by_id (#12842)
# Objective

- Add `remove_by_id` method to `EntityWorldMut` and `EntityCommands`
- This is a duplicate of the awesome work by @mateuseap, last updated
04/09/23 - #9663
- I'm opening a second one to ensure the feature makes it into `0.14`
- Fixes #9261

## Solution

Almost identical to #9663 with three exceptions
- Uses a closure instead of struct for commands, consistent with other
similar commands
- Does not refactor `EntityCommands::insert`, so no migration guide
- `EntityWorldMut::remove_by_id` is now safe containing unsafe blocks, I
think thats what @SkiFire13 was indicating should happen [in this
comment](https://github.com/bevyengine/bevy/pull/9663#discussion_r1314307525)

## Changelog

- Added `EntityWorldMut::remove_by_id` method and its tests.
- Added `EntityCommands::remove_by_id` method and its tests.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-04-03 09:50:32 +00:00
BD103
84363f2fab
Remove redundant imports (#12817)
# 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>
2024-04-01 19:59:08 +00:00
unknownue
50699ecf76
Fix typos in insert_or_spawn_batch/spawn_batch methods (#12812)
# Objective

- The `bundles` parameter in `insert_or_spawn_batch` method has
inconsistent naming with docs (e.g. `bundles_iter`) since #11107.

## Solution

- Replace `bundles` with `bundles_iter`, as `bundles_iter` is more
expressive to its type.
2024-03-31 20:18:27 +00:00
James Liu
a6e37e7a2a
Add QueryState::contains, document complexity, and make as_nop pub(crate) (#12776)
# Objective
Fixes #12752. Fixes #12750. Document the runtime complexity of all of
the `O(1)` operations on the individual APIs.

## Solution

  * Mirror `Query::contains` onto `QueryState::contains`
  * Make `QueryState::as_nop` pub(crate)
  * Make `NopWorldQuery` pub(crate)
  * Document all of the O(1) operations on Query and QueryState.
2024-03-29 14:49:43 +00:00
James Liu
741803d8c9
Implement QueryData for &Archetype and EntityLocation (#12398)
# Objective
Fixes #12392, fixes #12393, and fixes #11387. Implement QueryData for
Archetype and EntityLocation.

## Solution
Add impls for both of the types.

---

## Changelog
Added: `&Archetype` now implements `QueryData`
Added: `EntityLocation` now implements `QueryData`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-03-29 06:41:01 +00:00
Pablo Reinhardt
78335a5ddc
Allow Commands to register systems (#11019)
# Objective

- Allow registering of systems from Commands with
`Commands::register_one_shot_system`
- Make registering of one shot systems more easy

## Solution

- Add the Command `RegisterSystem` for Commands use.
- Creation of SystemId based on lazy insertion of the System
- Changed the privacy of the fields in SystemId so Commands can return
the SystemId

---

## Changelog

### Added
- Added command `RegisterSystem`
- Added function `Commands::register_one_shot_system`
- Added function `App::register_one_shot_system`

### Changed
- Changed the privacy and the type of struct tuple to regular struct of
SystemId

## Migration Guide

- Changed SystemId fields from tuple struct to a normal struct
If you want to access the entity field, you should use
`SystemId::entity` instead of `SystemId::0`

## Showcase
> Before, if you wanted to register a system with `Commands`, you would
need to do:
```rust
commands.add(|world: &mut World| {
    let id = world.register_system(your_system);
    // You would need to insert the SystemId inside an entity or similar
})
```
> Now, you can:
```rust
let id = commands.register_one_shot_system(your_system);
// Do what you want with the Id

```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pablo Reinhardt <pabloreinhardt@gmail.com>
2024-03-22 17:31:40 +00:00
Charles Bournhonesque
e33b93e312
Update ecs query docs (#12595)
# Objective

I'm reading through the ecs query code for the first time, and updating
the docs:
- fixed some typos
- added some docs about things I was confused about (in particular what
the difference between `matches_component_set` and
`update_component_access` was)
2024-03-22 13:28:41 +00:00
Brezak
69e78bd03e
Fix Ci failing over dead code in tests (#12623)
# 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.
2024-03-21 18:08:47 +00:00
James Liu
eebf3d61ec
Remove archetype_component_access from QueryState (#12474)
# 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
2024-03-17 19:01:52 +00:00
James Liu
4b64d1d1d7
Make a note about the performance of Query::is_empty (#12466)
# Objective
`Query::is_empty` does not mention the potential performance footgun of
using it with non-archetypal filters.

## Solution
Document it.
2024-03-14 01:36:03 +00:00
Eira Fransham
baaf4c8c2d
SystemId should manually implement Eq (#12436)
# Objective

`System<f32>` currently does not implement `Eq` even though it should

## Solution

Manually implement `Eq` like other traits are manually implemented
2024-03-12 22:11:21 +00:00
Mike
9cd3165105
Query Joins (#11535)
# Objective

- Add a way to combine 2 queries together in a similar way to
`Query::transmute_lens`
- Fixes #1658

## Solution

- Use a similar method to query transmute, but take the intersection of
matched archetypes between the 2 queries and the union of the accesses
to create the new underlying QueryState.

---

## Changelog

- Add query joins

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-03-11 19:07:36 +00:00
James Liu
879b170f28
Mention in docs about the query iteration order and result uniqueness. (#12400)
# Objective
Fix #10876. Improve `Query` and `QueryState`'s docs.

## Solution
Explicitly denote that Query is always guaranteed to return results from
all matching entities once and only once for each entity, and that
iteration order is not guaranteed in any way.
2024-03-11 18:17:46 +00:00
James Liu
ab6a5cac9f
Remove initialize_resource<T> and friends (#12307)
# 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.
2024-03-05 16:09:13 +00:00
Stepan Koltsov
70b70cd323
Rewrite part of Commands rustdoc (#11141)
- Explain it is flushed in the same schedule run (was not obvious to me)
- Point to `apply_deferred` example
- Remove mentions of `System::apply_deferred` and
`Schedule::apply_deferred` which are probably too low level for the most
users

Co-authored-by: James Liu <contact@jamessliu.com>
2024-03-05 09:52:48 +00:00
Gino Valente
e8583d132c
bevy_ecs: Fix up docs for World::run_system and World::run_system_with_input (#12289)
# Objective

- The doc example for `World::run_system_with_input` mistakenly
indicates that systems share state
- Some of the doc example code is unnecessary and/or could be cleaned up

## Solution

Replace the incorrect result value for the correct one in the doc
example. I also went with an explicit `assert_eq` check as it presents
the same information but can be validated by CI via doc tests.

Also removed some unnecessary code, such as the `Resource` derives on
`Counter`. In fact, I just replaced `Counter` with a `u8` in the
`Local`. I think it makes the example a little cleaner.

---

## Changelog

- Update docs for `World::run_system` and `World::run_system_with_input`
2024-03-04 21:59:24 +00:00
targrub
13cbb9cf10
Move commands module into bevy::ecs::world (#12234)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/11628

## Migration Guide

`Command` and `CommandQueue` have migrated from `bevy_ecs::system` to
`bevy_ecs::world`, so `use bevy_ecs::world::{Command, CommandQueue};`
when necessary.
2024-03-02 23:13:45 +00:00
James O'Brien
94ff123d7f
Component Lifecycle Hooks and a Deferred World (#10756)
# Objective

- Provide a reliable and performant mechanism to allows users to keep
components synchronized with external sources: closing/opening sockets,
updating indexes, debugging etc.
- Implement a generic mechanism to provide mutable access to the world
without allowing structural changes; this will not only be used here but
is a foundational piece for observers, which are key for a performant
implementation of relations.

## Solution

- Implement a new type `DeferredWorld` (naming is not important,
`StaticWorld` is also suitable) that wraps a world pointer and prevents
user code from making any structural changes to the ECS; spawning
entities, creating components, initializing resources etc.
- Add component lifecycle hooks `on_add`, `on_insert` and `on_remove`
that can be assigned callbacks in user code.

---

## Changelog
- Add new `DeferredWorld` type.
- Add new world methods: `register_component::<T>` and
`register_component_with_descriptor`. These differ from `init_component`
in that they provide mutable access to the created `ComponentInfo` but
will panic if the component is already in any archetypes. These
restrictions serve two purposes:
1. Prevent users from defining hooks for components that may already
have associated hooks provided in another plugin. (a use case better
served by observers)
2. Ensure that when an `Archetype` is created it gets the appropriate
flags to early-out when triggering hooks.
- Add methods to `ComponentInfo`: `on_add`, `on_insert` and `on_remove`
to be used to register hooks of the form `fn(DeferredWorld, Entity,
ComponentId)`
- Modify `BundleInserter`, `BundleSpawner` and `EntityWorldMut` to
trigger component hooks when appropriate.
- Add bit flags to `Archetype` indicating whether or not any contained
components have each type of hook, this can be expanded for other flags
as needed.
- Add `component_hooks` example to illustrate usage. Try it out! It's
fun to mash keys.

## Safety
The changes to component insertion, removal and deletion involve a large
amount of unsafe code and it's fair for that to raise some concern. I
have attempted to document it as clearly as possible and have confirmed
that all the hooks examples are accepted by `cargo miri` as not causing
any undefined behavior. The largest issue is in ensuring there are no
outstanding references when passing a `DeferredWorld` to the hooks which
requires some use of raw pointers (as was already happening to some
degree in those places) and I have taken some time to ensure that is the
case but feel free to let me know if I've missed anything.

## Performance
These changes come with a small but measurable performance cost of
between 1-5% on `add_remove` benchmarks and between 1-3% on `insert`
benchmarks. One consideration to be made is the existence of the current
`RemovedComponents` which is on average more costly than the addition of
`on_remove` hooks due to the early-out, however hooks doesn't completely
remove the need for `RemovedComponents` as there is a chance you want to
respond to the removal of a component that already has an `on_remove`
hook defined in another plugin, so I have not removed it here. I do
intend to deprecate it with the introduction of observers in a follow up
PR.

## Discussion Questions
- Currently `DeferredWorld` implements `Deref` to `&World` which makes
sense conceptually, however it does cause some issues with rust-analyzer
providing autocomplete for `&mut World` references which is annoying.
There are alternative implementations that may address this but involve
more code churn so I have attempted them here. The other alternative is
to not implement `Deref` at all but that leads to a large amount of API
duplication.
- `DeferredWorld`, `StaticWorld`, something else?
- In adding support for hooks to `EntityWorldMut` I encountered some
unfortunate difficulties with my desired API. If commands are flushed
after each call i.e. `world.spawn() // flush commands .insert(A) //
flush commands` the entity may be despawned while `EntityWorldMut` still
exists which is invalid. An alternative was then to add
`self.world.flush_commands()` to the drop implementation for
`EntityWorldMut` but that runs into other problems for implementing
functions like `into_unsafe_entity_cell`. For now I have implemented a
`.flush()` which will flush the commands and consume `EntityWorldMut` or
users can manually run `world.flush_commands()` after using
`EntityWorldMut`.
- In order to allowing querying on a deferred world we need
implementations of `WorldQuery` to not break our guarantees of no
structural changes through their `UnsafeWorldCell`. All our
implementations do this, but there isn't currently any safety
documentation specifying what is or isn't allowed for an implementation,
just for the caller, (they also shouldn't be aliasing components they
didn't specify access for etc.) is that something we should start doing?
(see 10752)

Please check out the example `component_hooks` or the tests in
`bundle.rs` for usage examples. I will continue to expand this
description as I go.

See #10839 for a more ergonomic API built on top of this one that isn't
subject to the same restrictions and supports `SystemParam` dependency
injection.
2024-03-01 14:59:22 +00:00
amy universe
cbfeb9438a
include links in error messages (#12165)
# Objective

Fixes #12118

## Solution
did a grip for any "B000" in the crates directory, and added the links

note: ignored the test functions in this file
https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/system/mod.rs#L537
2024-02-28 00:01:18 +00:00
porkbrain
43b859dfcf
Implements conversion from SystemId to Entity (#11759)
# Objective

Right now when using egui, systems are inserted without any identifier
and to the root. I'd like to name those systems and insert them as
children to a root entity. This helps to keep the editor organized.

## Solution

- Although the `SystemId` is documented as an opaque type, examples
depicted above benefit from tear down of the abstraction.

---

## Changelog

### Added
- Implemented `From<SystemId>` for `Entity`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-26 12:17:30 +00:00
Charles Bournhonesque
5bcc100d10
Update docstrings for some Commands to use the correct type (#12111)
# Objective

- A tiny nit I noticed; I think the type of these function is
`EntityCommand`, not `Command`

Co-authored-by: Charles Bournhonesque <cbournhonesque@snapchat.com>
2024-02-25 19:48:33 +00:00
James Liu
42e61557f8
Immediately apply deferred system params in System::run (#11823)
# Objective
Fixes #11821. 

## Solution
* Run `System::apply_deferred` in `System::run` after executing the
system.
* Switch to using `System::run_unsafe` in `SingleThreadedExecutor` to
preserve the current behavior.
* Remove the `System::apply_deferred` in `SimpleExecutor` as it's now
redundant.
* Remove the `System::apply_deferred` when running one-shot systems, as
it's now redundant.

---

## Changelog
Changed: `System::run` will now immediately apply deferred system params
after running the system.

## Migration Guide
`System::run` will now always run `System::apply_deferred` immediately
after running the system now. If you were running systems and then
applying their deferred buffers at a later point in time, you can
eliminate the latter.

```rust
// in 0.13
system.run(world);
// .. sometime later ...
system.apply_deferred(world);

// in 0.14
system.run(world);
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-24 14:01:06 +00:00
Ame
9d67edc3a6
fix some typos (#12038)
# Objective

Split - containing only the fixed typos

-
https://github.com/bevyengine/bevy/pull/12036#pullrequestreview-1894738751


# Migration Guide
In `crates/bevy_mikktspace/src/generated.rs` 

```rs
// before
pub struct SGroup {
    pub iVertexRepresentitive: i32,
    ..
}

// after
pub struct SGroup {
    pub iVertexRepresentative: i32,
    ..
}
```

In `crates/bevy_core_pipeline/src/core_2d/mod.rs`

```rs
// before
Node2D::ConstrastAdaptiveSharpening

// after
Node2D::ContrastAdaptiveSharpening
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: François <mockersf@gmail.com>
2024-02-22 18:55:22 +00:00
Tristan Guichaoua
33c7a2251e
bevy_ecs address trivial cases of unsafe_op_in_unsafe_fn (#11861)
# 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>
2024-02-22 00:04:38 +00:00
Jakob Hellermann
a491bce680
Fix SystemTypeSet::system_type being out of sync with System::type_id (#12030)
## Objective

Always have `some_system.into_system().type_id() ==
some_system.into_system_set().system_type().unwrap()`.

System sets have a `fn system_type() -> Option<TypeId>` that is
implemented by `SystemTypeSet` to returning the TypeId of the system's
function type. This was implemented in
https://github.com/bevyengine/bevy/pull/7715 and is used in
`bevy_mod_debugdump` to handle `.after(function)` constraints.

Back then, `System::type_id` always also returned the type id of the
function item, not of `FunctionSystem<M, F>`.

https://github.com/bevyengine/bevy/pull/11728 changes the behaviour of
`System::type_id` so that it returns the id of the
`FunctionSystem`/`ExclusiveFunctionSystem` wrapper, but it did not
change `SystemTypeSet::system_type`, so doing the lookup breaks in
`bevy_mod_debugdump`.

## Solution

Change `IntoSystemSet` for functions to return a
`SystemTypeSet<FunctionSystem>` /
`SystemTypeSet<ExclusiveFunctionSystem>` instead of `SystemTypeSet<F>`.
2024-02-21 23:40:45 +00:00
James Liu
bc82749012
Remove APIs deprecated in 0.13 (#11974)
# 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.
2024-02-19 19:04:47 +00:00
James Liu
e34fb68677
refactor: Extract parallel queue abstraction (#7348)
# Objective
There's a repeating pattern of `ThreadLocal<Cell<Vec<T>>>` which is very
useful for low overhead, low contention multithreaded queues that have
cropped up in a few places in the engine. This pattern is surprisingly
useful when building deferred mutation across multiple threads, as noted
by it's use in `ParallelCommands`.

However, `ThreadLocal<Cell<Vec<T>>>` is not only a mouthful, it's also
hard to ensure the thread-local queue is replaced after it's been
temporarily removed from the `Cell`.

## Solution
Wrap the pattern into `bevy_utils::Parallel<T>` which codifies the
entire pattern and ensures the user follows the contract. Instead of
fetching indivdual cells, removing the value, mutating it, and replacing
it, `Parallel::get` returns a `ParRef<'a, T>` which contains the
temporarily removed value and a reference back to the cell, and will
write the mutated value back to the cell upon being dropped.

I would like to use this to simplify the remaining part of #4899 that
has not been adopted/merged.

---

## Changelog
TODO

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
2024-02-19 16:31:15 +00:00
Joseph
bd25135330
Fix double indirection when applying command queues (#11822)
# Objective

When applying a command, we currently use double indirection for the
world reference `&mut Option<&mut World>`. Since this is used across a
`fn` pointer boundary, this can't get optimized away.

## Solution

Reborrow the world reference and pass `Option<&mut World>` instead.
2024-02-12 15:27:18 +00:00
Joseph
9c2257332a
Add a method for detecting changes within a certain scope (#11687)
# Objective

Bevy's change detection functionality is invaluable for writing robust
apps, but it only works in the context of systems and exclusive systems.
Oftentimes it is necessary to detect changes made in earlier code
without having to place the code in separate systems, but it is not
currently possible to do so since there is no way to set the value of
`World::last_change_tick`.

`World::clear_trackers` allows you to update the change tick, but this
has unintended side effects, since it irreversibly affects the behavior
of change and removal detection for the entire app.

## Solution

Add a method `World::last_change_tick_scope`. This allows you to set
`last_change_tick` to a specific value for a region of code. To ensure
that misuse doesn't break unrelated functions, we restore the world's
original change tick at the end of the provided scope.

### Example

A function that uses this to run an update loop repeatedly, allowing
each iteration of the loop to react to changes made in the previous loop
iteration.

```rust
fn update_loop(
    world: &mut World,
    mut update_fn: impl FnMut(&mut World) -> std::ops::ControlFlow<()>,
) {
    let mut last_change_tick = world.last_change_tick();

    // Repeatedly run the update function until it requests a break.
    loop {
        // Update once.
        let control_flow = world.last_change_tick_scope(last_change_tick, |world| {
            update_fn(world)
        });

        // End the loop when the closure returns `ControlFlow::Break`.
        if control_flow.is_break() {
            break;
        }

        // Increment the change tick so the next update can detect changes from this update.
        last_change_tick = world.change_tick();
        world.increment_change_tick();
    }
}
```

---

## Changelog

+ Added `World::last_change_tick_scope`, which allows you to specify the
reference for change detection within a certain scope.
2024-02-12 15:09:11 +00:00
Zachary Harrold
950bd2284d
System::type_id Consistency (#11728)
# Objective

- Fixes #11679

## Solution

- Added `IntoSystem::system_type_id` which returns the equivalent of
`system.into_system().type_id()` without construction. This allows for
getting the `TypeId` of functions (a function is an unnamed type and
therefore you cannot call `TypeId::of::<apply_deferred::System>()`)
- Added default implementation of `System::type_id` to ensure
consistency between implementations. Some returned `Self`, while others
were returning an inner value instead. This ensures consistency with
`IntoSystem::system_type_id`.

## Migration Guide

If you use `System::type_id()` on function systems (exclusive or not),
ensure you are comparing its value to other `System::type_id()` calls,
or `IntoSystem::system_type_id()`.

This code wont require any changes, because `IntoSystem`'s are directly
compared to each other.

```rust
fn test_system() {}

let type_id = test_system.type_id();

// ...

// No change required
assert_eq!(test_system.type_id(), type_id);
```

Likewise, this code wont, because `System`'s are directly compared.

```rust
fn test_system() {}

let type_id = IntoSystem::into_system(test_system).type_id();

// ...

// No change required
assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id);
```

The below _does_ require a change, since you're comparing a `System`
type to a `IntoSystem` type.

```rust
fn test_system() {}

// Before
assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id());

// After
assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id());
```
2024-02-06 14:43:33 +00:00
Zachary Harrold
1974723a63
Deprecated Various Component Methods from Query and QueryState (#9920)
# Objective

- (Partially) Fixes #9904
- Acts on #9910

## Solution

- Deprecated the relevant methods from `Query`, cascading changes as
required across Bevy.

---

## Changelog

- Deprecated `QueryState::get_component_unchecked_mut` method
- Deprecated `Query::get_component` method
- Deprecated `Query::get_component_mut` method
- Deprecated `Query::component` method
- Deprecated `Query::component_mut` method
- Deprecated `Query::get_component_unchecked_mut` method

## Migration Guide

### `QueryState::get_component_unchecked_mut`

Use `QueryState::get_unchecked_manual` and select for the exact
component based on the structure of the exact query as required.

### `Query::(get_)component(_unchecked)(_mut)`

Use `Query::get` and select for the exact component based on the
structure of the exact query as required.

- For mutable access (`_mut`), use `Query::get_mut`
- For unchecked access (`_unchecked`), use `Query::get_unchecked`
- For panic variants (non-`get_`), add `.unwrap()`

## Notes

- `QueryComponentError` can be removed once these deprecated methods are
also removed. Due to an interaction with `thiserror`'s derive macro, it
is not marked as deprecated.
2024-02-04 01:01:59 +00:00
Lane Kolbly
9fcf862114
bevy_ecs: Add doc example for par_iter_mut (#11311) (#11499)
# Objective

Fixes #11311 

## Solution

Adds an example to the documentation for `par_iter_mut`. I didn't add
any examples to `par_iter`, because I couldn't think of a good example
and I figure users can infer that `par_iter` and `par_iter_mut` are
similar.
2024-01-28 02:13:03 +00:00
Trashtalk217
a955d65ffa
Exclusive systems can now be used for one-shot systems (#11560)
Joy notified me that exclusive systems should now work (they may have
always worked, I don't know), so here's a quick change to the
documentation.
2024-01-27 16:10:39 +00:00
Pixelstorm
df063ab1ef
Implement Debug for CommandQueue (#11444)
# Objective

Allow users to impl Debug on types containing `CommandQueue`s

## Solution

Derive Debug on `CommandQueue`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-01-22 15:45:17 +00:00
Joseph
7d69d3195f
refactor: Simplify lifetimes for Commands and related types (#11445)
# 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(...);
```
2024-01-22 15:35:42 +00:00
laund
e2e4e8eb9a
document which lifetime is needed for systemparam derive (#11321)
# 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>
2024-01-22 15:32:42 +00:00
James O'Brien
ea42d14344
Dynamic queries and builder API (#9774)
# Objective
Expand the existing `Query` API to support more dynamic use cases i.e.
scripting.

## Prior Art
 - #6390 
 - #8308 
- #10037

## Solution
- Create a `QueryBuilder` with runtime methods to define the set of
component accesses for a built query.
- Create new `WorldQueryData` implementations `FilteredEntityMut` and
`FilteredEntityRef` as variants of `EntityMut` and `EntityRef` that
provide run time checked access to the components included in a given
query.
- Add new methods to `Query` to create "query lens" with a subset of the
access of the initial query.

### Query Builder
The `QueryBuilder` API allows you to define a query at runtime. At it's
most basic use it will simply create a query with the corresponding type
signature:
```rust
let query = QueryBuilder::<Entity, With<A>>::new(&mut world).build();
// is equivalent to
let query = QueryState::<Entity, With<A>>::new(&mut world);
```
Before calling `.build()` you also have the opportunity to add
additional accesses and filters. Here is a simple example where we add
additional filter terms:
```rust
let entity_a = world.spawn((A(0), B(0))).id();
let entity_b = world.spawn((A(0), C(0))).id();

let mut query_a = QueryBuilder::<Entity>::new(&mut world)
    .with::<A>()
    .without::<C>()
    .build();
            
assert_eq!(entity_a, query_a.single(&world));
```
This alone is useful in that allows you to decide which archetypes your
query will match at runtime. However it is also very limited, consider a
case like the following:
```rust
let query_a = QueryBuilder::<&A>::new(&mut world)
// Add an additional access
    .data::<&B>()
    .build();
```
This will grant the query an additional read access to component B
however we have no way of accessing the data while iterating as the type
signature still only includes &A. For an even more concrete example of
this consider dynamic components:
```rust
let query_a = QueryBuilder::<Entity>::new(&mut world)
// Adding a filter is easy since it doesn't need be read later
    .with_id(component_id_a)
// How do I access the data of this component?
    .ref_id(component_id_b)
    .build();
```
With this in mind the `QueryBuilder` API seems somewhat incomplete by
itself, we need some way method of accessing the components dynamically.
So here's one:
### Query Transmutation
If the problem is not having the component in the type signature why not
just add it? This PR also adds transmute methods to `QueryBuilder` and
`QueryState`. Here's a simple example:
```rust
world.spawn(A(0));
world.spawn((A(1), B(0)));
let mut query = QueryBuilder::<()>::new(&mut world)
    .with::<B>()
    .transmute::<&A>()
    .build();

query.iter(&world).for_each(|a| assert_eq!(a.0, 1));
```
The `QueryState` and `QueryBuilder` transmute methods look quite similar
but are different in one respect. Transmuting a builder will always
succeed as it will just add the additional accesses needed for the new
terms if they weren't already included. Transmuting a `QueryState` will
panic in the case that the new type signature would give it access it
didn't already have, for example:
```rust
let query = QueryState::<&A, Option<&B>>::new(&mut world);
/// This is fine, the access for Option<&A> is less restrictive than &A
query.transmute::<Option<&A>>(&world);
/// Oh no, this would allow access to &B on entities that might not have it, so it panics
query.transmute::<&B>(&world);
/// This is right out
query.transmute::<&C>(&world);
```
This is quite an appealing API to also have available on `Query` however
it does pose one additional wrinkle: In order to to change the iterator
we need to create a new `QueryState` to back it. `Query` doesn't own
it's own state though, it just borrows it, so we need a place to borrow
it from. This is why `QueryLens` exists, it is a place to store the new
state so it can be borrowed when you call `.query()` leaving you with an
API like this:
```rust
fn function_that_takes_a_query(query: &Query<&A>) {
    // ...
}

fn system(query: Query<(&A, &B)>) {
    let lens = query.transmute_lens::<&A>();
    let q = lens.query();
    function_that_takes_a_query(&q);
}
```
Now you may be thinking: Hey, wait a second, you introduced the problem
with dynamic components and then described a solution that only works
for static components! Ok, you got me, I guess we need a bit more:
### Filtered Entity References
Currently the only way you can access dynamic components on entities
through a query is with either `EntityMut` or `EntityRef`, however these
can access all components and so conflict with all other accesses. This
PR introduces `FilteredEntityMut` and `FilteredEntityRef` as
alternatives that have additional runtime checking to prevent accessing
components that you shouldn't. This way you can build a query with a
`QueryBuilder` and actually access the components you asked for:
```rust
let mut query = QueryBuilder::<FilteredEntityRef>::new(&mut world)
    .ref_id(component_id_a)
    .with(component_id_b)
    .build();

let entity_ref = query.single(&world);

// Returns Some(Ptr) as we have that component and are allowed to read it
let a = entity_ref.get_by_id(component_id_a);
// Will return None even though the entity does have the component, as we are not allowed to read it
let b = entity_ref.get_by_id(component_id_b);
```
For the most part these new structs have the exact same methods as their
non-filtered equivalents.

Putting all of this together we can do some truly dynamic ECS queries,
check out the `dynamic` example to see it in action:
```
Commands:
    comp, c   Create new components
    spawn, s  Spawn entities
    query, q  Query for entities
Enter a command with no parameters for usage.

> c A, B, C, Data 4  
Component A created with id: 0
Component B created with id: 1
Component C created with id: 2
Component Data created with id: 3

> s A, B, Data 1
Entity spawned with id: 0v0

> s A, C, Data 0
Entity spawned with id: 1v0

> q &Data
0v0: Data: [1, 0, 0, 0]
1v0: Data: [0, 0, 0, 0]

> q B, &mut Data                                                                                     
0v0: Data: [2, 1, 1, 1]

> q B || C, &Data 
0v0: Data: [2, 1, 1, 1]
1v0: Data: [0, 0, 0, 0]
```
## Changelog
 - Add new `transmute_lens` methods to `Query`.
- Add new types `QueryBuilder`, `FilteredEntityMut`, `FilteredEntityRef`
and `QueryLens`
- `update_archetype_component_access` has been removed, archetype
component accesses are now determined by the accesses set in
`update_component_access`
- Added method `set_access` to `WorldQuery`, this is called before
`update_component_access` for queries that have a restricted set of
accesses, such as those built by `QueryBuilder` or `QueryLens`. This is
primarily used by the `FilteredEntity*` variants and has an empty trait
implementation.
- Added method `get_state` to `WorldQuery` as a fallible version of
`init_state` when you don't have `&mut World` access.

## Future Work
Improve performance of `FilteredEntityMut` and `FilteredEntityRef`,
currently they have to determine the accesses a query has in a given
archetype during iteration which is far from ideal, especially since we
already did the work when matching the archetype in the first place. To
avoid making more internal API changes I have left it out of this PR.

---------

Co-authored-by: Mike Hsu <mike.hsu@gmail.com>
2024-01-16 19:16:49 +00:00
Ixentus
e2fd63104d
Simplify conditions (#11316)
# Objective

- Conditions don't have to be closures unless they have state or mutate.

## Solution

- Simplify conditions when possible.

---

## Changelog

The following run conditions are now regular systems:
- resource_exists<T>
- resource_added<T>
- resource_changed<T>
- resource_exists_and_changed<T>
- state_exists<S: States>
- state_changed<S: States>
- any_with_component<T: Component>

## Migration Guide

- resource_exists<T>() -> resource_exists<T>
- resource_added<T>() -> resource_added<T>
- resource_changed<T>() -> resource_changed<T>
- resource_exists_and_changed<T>() -> resource_exists_and_changed<T>
- state_exists<S: States>() -> state_exists<S: States>
- state_changed<S: States>() -> state_changed<S: States>
- any_with_component<T: Component>() -> any_with_component<T: Component>
2024-01-13 13:22:17 +00:00
Joseph
df2ba09989
Restore support for running fn EntityCommands on entities that might be despawned (#11107)
# Objective

In #9604 we removed the ability to define an `EntityCommand` as
`fn(Entity, &mut World)`. However I have since realized that `fn(Entity,
&mut World)` is an incredibly expressive and powerful way to define a
command for an entity that may or may not exist (`fn(EntityWorldMut)`
only works on entities that are alive).

## Solution

Support `EntityCommand`s in the style of `fn(Entity, &mut World)`, as
well as `fn(EntityWorldMut)`. Use a marker generic on the
`EntityCommand` trait to allow multiple impls.

The second commit in this PR replaces all of the internal command
definitions with ones using `fn` definitions. This is mostly just to
show off how expressive this style of command is -- we can revert this
commit if we'd rather avoid breaking changes.

---

## Changelog

Re-added support for expressively defining an `EntityCommand` as a
function that takes `Entity, &mut World`.

## Migration Guide

All `Command` types in `bevy_ecs`, such as `Spawn`, `SpawnBatch`,
`Insert`, etc., have been made private. Use the equivalent methods on
`Commands` or `EntityCommands` instead.
2024-01-08 22:32:28 +00:00
Chia-Hsiang Cheng
b6da40cfe6
Print a warning for un-applied commands being dropped from a CommandQueue (#11146)
# Objective

- Fixes #11125 
## Solution

Add a warning for un-applied commands to the `drop` function.
2024-01-03 15:32:57 +00:00
Stepan Koltsov
6bc2686a7a
impl ExclusiveSystemParam for SystemName (#11163)
# 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`
2024-01-01 17:08:29 +00:00
Adam
8baefa1570
Implement Deref and DerefMut for In (#11104)
# Objective

Implement Deref and DerefMut for In<T>

makes it so the user doesn't have to add ".0" in most cases
2024-01-01 16:55:07 +00:00
Doonv
189ceaf0d3
Replace or document ignored doctests (#11040)
# Objective

There are a lot of doctests that are `ignore`d for no documented reason.
And that should be fixed.

## Solution

I searched the bevy repo with the regex ` ```[a-z,]*ignore ` in order to
find all `ignore`d doctests. For each one of the `ignore`d doctests, I
did the following steps:
1. Attempt to remove the `ignored` attribute while still passing the
test. I did this by adding hidden dummy structs and imports.
2. If step 1 doesn't work, attempt to replace the `ignored` attribute
with the `no_run` attribute while still passing the test.
3. If step 2 doesn't work, keep the `ignored` attribute but add
documentation for why the `ignored` attribute was added.

---------

Co-authored-by: François <mockersf@gmail.com>
2024-01-01 16:50:56 +00:00
Stepan Koltsov
4fba03b529
impl ExclusiveSystemParam for PhantomData (#11153)
# Objective

Implement `ExclusiveSystemParam` for `PhantomData`.

For the same reason `SystemParam` impl exists: to simplify writing
generic code.


786abbf3f5/crates/bevy_ecs/src/system/system_param.rs (L1557)

Also for consistency.

## Solution

`impl ExclusiveSystemParam for PhantomData`.

## Changelog
Added: PhantomData<T> now implements ExclusiveSystemParam.
2024-01-01 16:02:21 +00:00
Stepan Koltsov
ac58a5fe57
Better doc for SystemName (#11084)
Compared to [current
documentation](https://docs.rs/bevy/latest/bevy/ecs/system/struct.SystemName.html)
it is now immediately clear that it is `SystemParam` readily available
to user, and not just some accidentally exposed internal data type.
2023-12-25 05:09:15 +00:00
Tygyh
7b8305e5b4
Remove unnecessary parens (#11075)
# Objective

- Increase readability.

## Solution

- Remove unnecessary parens.
2023-12-24 17:43:01 +00:00
Tygyh
63d17e8494
Simplify equality assertions (#10988)
# Objective

- Shorten assertions.

## Solution

- Replace '==' assertions with 'assert_eq()' and '!=' assertions with
'assert_ne()' .
2023-12-16 23:58:41 +00:00
Mike
6b84ba97a3
Auto insert sync points (#9822)
# 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>
2023-12-14 16:34:01 +00:00
Tygyh
b2661ea73d
Reorder impl to be the same as the trait (#10964)
# Objective

- Make the implementation order consistent between all sources to fit
the order in the trait.

## Solution

- Change the implementation order.
2023-12-13 21:19:49 +00:00
Federico Rinaldi
9c78128e8f
Rename Q type parameter to D when referring to WorldQueryData (#10782)
# 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>
2023-12-13 18:50:46 +00:00
Mantas
5af2f022d8
Rename WorldQueryData & WorldQueryFilter to QueryData & QueryFilter (#10779)
# Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` &
`QueryFilter`

Fixes #10776 

## Solution

Traits `WorldQueryData` & `WorldQueryFilter` were renamed to `QueryData`
and `QueryFilter`, respectively. Related Trait types were also renamed.

---

## Changelog

- Trait `WorldQueryData` has been renamed to `QueryData`. Derive macro's
`QueryData` attribute `world_query_data` has been renamed to
`query_data`.
- Trait `WorldQueryFilter` has been renamed to `QueryFilter`. Derive
macro's `QueryFilter` attribute `world_query_filter` has been renamed to
`query_filter`.
- Trait's `ExtractComponent` type `Query` has been renamed to `Data`.
- Trait's `GetBatchData` types `Query` & `QueryFilter` has been renamed
to `Data` & `Filter`, respectively.
- Trait's `ExtractInstance` type `Query` has been renamed to `Data`.
- Trait's `ViewNode` type `ViewQuery` has been renamed to `ViewData`.
- Trait's `RenderCommand` types `ViewWorldQuery` & `ItemWorldQuery` has
been renamed to `ViewData` & `ItemData`, respectively.

## Migration Guide

Note: if merged before 0.13 is released, this should instead modify the
migration guide of #10776 with the updated names.

- Rename `WorldQueryData` & `WorldQueryFilter` trait usages to
`QueryData` & `QueryFilter` and their respective derive macro attributes
`world_query_data` & `world_query_filter` to `query_data` &
`query_filter`.
- Rename the following trait type usages:
  - Trait's `ExtractComponent` type `Query` to `Data`.
  - Trait's `GetBatchData` type `Query` to `Data`.
  - Trait's `ExtractInstance` type `Query` to `Data`.
  - Trait's `ViewNode` type `ViewQuery` to `ViewData`'
- Trait's `RenderCommand` types `ViewWolrdQuery` & `ItemWorldQuery` to
`ViewData` & `ItemData`, respectively.

```rust
// Before
#[derive(WorldQueryData)]
#[world_query_data(derive(Debug))]
struct EmptyQuery {
    empty: (),
}

// After
#[derive(QueryData)]
#[query_data(derive(Debug))]
struct EmptyQuery {
    empty: (),
}

// Before
#[derive(WorldQueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
    _c: With<ComponentC>,
    _d: With<ComponentD>,
    _or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
    _generic_tuple: (With<T>, With<P>),
}

// After
#[derive(QueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
    _c: With<ComponentC>,
    _d: With<ComponentD>,
    _or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
    _generic_tuple: (With<T>, With<P>),
}

// Before
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
    type Query = &'static Self;
    type Filter = With<Camera>;
    type Out = (DenoiseCAS, CASUniform);

    fn extract_component(item: QueryItem<Self::Query>) -> Option<Self::Out> {
        //...
    }
}

// After
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
    type Data = &'static Self;
    type Filter = With<Camera>;
    type Out = (DenoiseCAS, CASUniform);

    fn extract_component(item: QueryItem<Self::Data>) -> Option<Self::Out> {
        //...
    }
}

// Before
impl GetBatchData for MeshPipeline {
    type Param = SRes<RenderMeshInstances>;
    type Query = Entity;
    type QueryFilter = With<Mesh3d>;
    type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
    type BufferData = MeshUniform;

    fn get_batch_data(
        mesh_instances: &SystemParamItem<Self::Param>,
        entity: &QueryItem<Self::Query>,
    ) -> (Self::BufferData, Option<Self::CompareData>) {
        // ....
    }
}

// After
impl GetBatchData for MeshPipeline {
    type Param = SRes<RenderMeshInstances>;
    type Data = Entity;
    type Filter = With<Mesh3d>;
    type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
    type BufferData = MeshUniform;

    fn get_batch_data(
        mesh_instances: &SystemParamItem<Self::Param>,
        entity: &QueryItem<Self::Data>,
    ) -> (Self::BufferData, Option<Self::CompareData>) {
        // ....
    }
}

// Before
impl<A> ExtractInstance for AssetId<A>
where
    A: Asset,
{
    type Query = Read<Handle<A>>;
    type Filter = ();

    fn extract(item: QueryItem<'_, Self::Query>) -> Option<Self> {
        Some(item.id())
    }
}

// After
impl<A> ExtractInstance for AssetId<A>
where
    A: Asset,
{
    type Data = Read<Handle<A>>;
    type Filter = ();

    fn extract(item: QueryItem<'_, Self::Data>) -> Option<Self> {
        Some(item.id())
    }
}

// Before
impl ViewNode for PostProcessNode {
    type ViewQuery = (
        &'static ViewTarget,
        &'static PostProcessSettings,
    );

    fn run(
        &self,
        _graph: &mut RenderGraphContext,
        render_context: &mut RenderContext,
        (view_target, _post_process_settings): QueryItem<Self::ViewQuery>,
        world: &World,
    ) -> Result<(), NodeRunError> {
        // ...
    }
}

// After
impl ViewNode for PostProcessNode {
    type ViewData = (
        &'static ViewTarget,
        &'static PostProcessSettings,
    );

    fn run(
        &self,
        _graph: &mut RenderGraphContext,
        render_context: &mut RenderContext,
        (view_target, _post_process_settings): QueryItem<Self::ViewData>,
        world: &World,
    ) -> Result<(), NodeRunError> {
        // ...
    }
}

// Before
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
    type Param = SRes<PipelineCache>;
    type ViewWorldQuery = ();
    type ItemWorldQuery = ();
    #[inline]
    fn render<'w>(
        item: &P,
        _view: (),
        _entity: (),
        pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
        pass: &mut TrackedRenderPass<'w>,
    ) -> RenderCommandResult {
        // ...
    }
}

// After
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
    type Param = SRes<PipelineCache>;
    type ViewData = ();
    type ItemData = ();
    #[inline]
    fn render<'w>(
        item: &P,
        _view: (),
        _entity: (),
        pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
        pass: &mut TrackedRenderPass<'w>,
    ) -> RenderCommandResult {
        // ...
    }
}
```
2023-12-12 19:45:50 +00:00
Ben Frankel
9c8576996f
Add a doc note about despawn footgun (#10889)
# Objective

The `Despawn` command breaks the hierarchy whenever you use it if the
despawned entity has a parent or any children. This is a serious footgun
because the `Despawn` command has the shortest name, the behavior is
unexpected and not likely to be what you want, and the crash that it
causes can be very difficult to track down.

## Solution

Until this can be fixed by relations, add a note mentioning the footgun
in the documentation.
2023-12-12 19:44:05 +00:00
TheBigCheese
6a15ed564d
Improve EntityWorldMut.remove, retain and despawn docs by linking to more detail (#10943)
## Solution

`Commands.remove` and `.retain` (because I copied `remove`s doc)
referenced `EntityWorldMut.remove` and `retain` for more detail but the
`Commands` docs are much more detailed (which makes sense because it is
the most common api), so I have instead inverted this so that
`EntityWorldMut` docs link to `Commands`.

I also made `EntityWorldMut.despawn` reference `World.despawn` for more
details, like `Commands.despawn` does.
2023-12-12 19:27:11 +00:00
Nicola Papale
d2614f2d80
Add a couple assertions for system types (#10893)
# Objective

Test more complex function signatures for exclusive systems, and test
that `StaticSystemParam` is indeed a `SystemParam`.

I mean, it currently works, but might as well add a test for it.
2023-12-06 20:35:46 +00:00
TheBigCheese
9da65b10b4
Add EntityCommands.retain and EntityWorldMut.retain (#10873)
# Objective
Adds `EntityCommands.retain` and `EntityWorldMut.retain` to remove all
components except the given bundle from the entity.
Fixes #10865.

## Solution

I added a private unsafe function in `EntityWorldMut` called
`remove_bundle_info` which performs the shared behaviour of `remove` and
`retain`, namely taking a `BundleInfo` of components to remove, and
removing them from the given entity. Then `retain` simply gets all the
components on the entity and filters them by whether they are in the
bundle it was passed, before passing this `BundleInfo` into
`remove_bundle_info`.

`EntityCommands.retain` just creates a new type `Retain` which runs
`EntityWorldMut.retain` when run.

---

## Changelog

Added `EntityCommands.retain` and `EntityWorldMut.retain`, which remove
all components except the given bundle from the entity, they can also be
used to remove all components by passing `()` as the bundle.
2023-12-05 15:37:33 +00:00
Nathan
24c6a7df05
Clarifying Commands' purpose (#10837)
# Objective
As described in [Issue
#10805](https://github.com/bevyengine/bevy/issues/10805) I have changed
"impactful changes" to "structural changes"

## Solution
Updated the text "impactful" to "structural"
2023-12-02 10:07:19 +00:00
James Liu
2148518758
Override QueryIter::fold to port Query::for_each perf gains to select Iterator combinators (#6773)
# Objective
After #6547, `Query::for_each` has been capable of automatic
vectorization on certain queries, which is seeing a notable (>50% CPU
time improvements) for iteration. However, `Query::for_each` isn't
idiomatic Rust, and lacks the flexibility of iterator combinators.

Ideally, `Query::iter` and friends should be able to achieve the same
results. However, this does seem to blocked upstream
(rust-lang/rust#104914) by Rust's loop optimizations.

## Solution
This is an intermediate solution and refactor. This moves the
`Query::for_each` implementation onto the `Iterator::fold`
implementation for `QueryIter` instead. This should result in the same
automatic vectorization optimization on all `Iterator` functions that
internally use fold, including `Iterator::for_each`, `Iterator::count`,
etc.

With this, it should close the gap between the two completely.
Internally, this PR changes `Query::for_each` to use
`query.iter().for_each(..)` instead of the duplicated implementation.

Separately, the duplicate implementations of internal iteration (i.e.
`Query::par_for_each`) now use portions of the current `Query::for_each`
implementation factored out into their own functions.

This also massively cleans up our internal fragmentation of internal
iteration options, deduplicating the iteration code used in `for_each`
and `par_iter().for_each()`.

---

## Changelog
Changed: `Query::for_each`, `Query::for_each_mut`, `Query::for_each`,
and `Query::for_each_mut` have been moved to `QueryIter`'s
`Iterator::for_each` implementation, and still retains their performance
improvements over normal iteration. These APIs are deprecated in 0.13
and will be removed in 0.14.

---------

Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-12-01 09:09:55 +00:00
tygyh
fd308571c4
Remove unnecessary path prefixes (#10749)
# 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.
2023-11-28 23:43:40 +00:00
Mark Wainwright
f0a8994f55
Split WorldQuery into WorldQueryData and WorldQueryFilter (#9918)
# 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>
2023-11-28 03:56:07 +00:00
Zachary Harrold
6e871ab919
Implement Drop for CommandQueue (#10746)
# Objective

- Fixes #10676, preventing a possible memory leak for commands which
owned resources.

## Solution

Implemented `Drop` for `CommandQueue`. This has been done entirely in
the private API of `CommandQueue`, ensuring no breaking changes. Also
added a unit test, `test_command_queue_inner_drop_early`, based on the
reproduction steps as outlined in #10676.

## Notes

I believe this can be applied to `0.12.1` as well, but I am uncertain of
the process to make that kind of change. Please let me know if there's
anything I can do to help with the back-porting of this change.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-11-27 22:35:36 +00:00
Mike
11b1b3a24f
delete methods deprecated in 0.12 (#10693)
## Changelog

- delete methods deprecated in 0.12
2023-11-24 16:15:47 +00:00
Mike
208ecb53dc
Append commands (#10400)
# Objective

- I've been experimenting with different patterns to try and make async
tasks more convenient. One of the better ones I've found is to return a
command queue to allow for deferred &mut World access. It can be
convenient to check for task completion in a normal system, but it is
hard to do something with the command queue after getting it back. This
pr adds a `append` to Commands. This allows appending the returned
command queue onto the system's commands.

## Solution

- I edited the async compute example to use the new `append`, but not
sure if I should keep the example changed as this might be too
opinionated.

## Future Work

- It would be very easy to pull the pattern used in the example out into
a plugin or a external crate, so users wouldn't have to add the checking
system.

---

## Changelog

- add `append` to `Commands` and `CommandQueue`
2023-11-22 00:04:37 +00:00
Andrew Safigan
a22020bf5c
Make impl block for RemovedSystem generic (#10651)
# Objective

Make the impl block for RemovedSystem generic so that the methods can be
called for systems that have inputs or outputs.

## Solution

Simply adding generics to the impl block.
2023-11-21 01:27:29 +00:00
Stepan Koltsov
0c9f265423
Link to In in pipe documentation (#10596) 2023-11-17 15:34:58 +00:00
Nathan Fenner
1f05e1e2ab
Add 'World::run_system_with_input' function + allow World::run_system to get system output (#10380)
# Objective

Allows chained systems taking an `In<_>` input parameter to be run as
one-shot systems. This API was mentioned in #8963.

In addition, `run_system(_with_input)` returns the system output, for
any `'static` output type.

## Solution

A new function, `World::run_system_with_input` allows a `SystemId<I, O>`
to be run by providing an `I` value as input and producing `O` as an
output.

`SystemId<I, O>` is now generic over the input type `I` and output type
`O`, along with the related functions and types `RegisteredSystem`,
`RemovedSystem`, `register_system`, `remove_system`, and
`RegisteredSystemError`. These default to `()`, preserving the existing
API, for all of the public types.

---

## Changelog

- Added `World::run_system_with_input` function to allow one-shot
systems that take `In<_>` input parameters
- Changed `World::run_system` and `World::register_system` to support
systems with return types beyond `()`
- Added `Commands::run_system_with_input` command that schedules a
one-shot system with an `In<_>` input parameter
2023-11-15 13:44:44 +00:00
Giacomo Stevanato
e75c2f8b16
Remove a ptr-to-int cast in CommandQueue::apply (#10475)
# Objective

- `CommandQueue::apply` calculates the address of the end of the
internal buffer as a `usize` rather than as a pointer, requiring two
casts of `cursor` to `usize`. Casting pointers to integers is generally
discouraged and may also prevent optimizations. It's also unnecessary
here.

## Solution

- Calculate the end address as a pointer rather than a `usize`.

Small note:

A trivial translation of the old code to use pointers would have
computed `end_addr` as `cursor.add(self.bytes.len())`, which is not
wrong but is an additional `unsafe` operation that also needs to be
properly documented and proven correct. However this operation is
already implemented in the form of the safe `as_mut_ptr_range`, so I
just used that.
2023-11-09 19:32:33 +00:00
Aevyrie
0cc11791b9
Allow registering boxed systems (#10378)
# Objective

- Allow registration of one-shot systems when those systems have already
been `Box`ed.
- Needed for `bevy_eventlisteners` which allows adding event listeners
with callbacks in normal systems. The current one shot system
implementation requires systems be registered from an exclusive system,
and that those systems be passed in as types that implement
`IntoSystem`. However, the eventlistener callback crate allows users to
define their callbacks in normal systems, by boxing the system and
deferring initialization to an exclusive system.

## Solution

- Separate the registration of the system from the boxing of the system.
This is non-breaking, and adds a new method.

---

## Changelog

- Added `World::register_boxed_system` to allow registration of
already-boxed one shot systems.
2023-11-08 14:54:32 +00:00
Pascal Hertleif
0c2c52a0cd
Derive Error for more error types (#10240)
# Objective

Align all error-like types to implement `Error`.

Fixes  #10176

## Solution

- Derive `Error` on more types
- Refactor instances of manual implementations that could be derived

This adds thiserror as a dependency to bevy_transform, which might
increase compilation time -- but I don't know of any situation where you
might only use that but not any other crate that pulls in bevy_utils.

The `contributors` example has a `LoadContributorsError` type, but as
it's an example I have not updated it. Doing that would mean either
having a `use bevy_internal::utils::thiserror::Error;` in an example
file, or adding `thiserror` as a dev-dependency to the main `bevy`
crate.

---

## Changelog

- All `…Error` types now implement the `Error` trait
2023-10-28 22:20:37 +00:00
Edgar Geier
a830530be4
Replace all labels with interned labels (#7762)
# Objective

First of all, this PR took heavy inspiration from #7760 and #5715. It
intends to also fix #5569, but with a slightly different approach.


This also fixes #9335 by reexporting `DynEq`.

## Solution

The advantage of this API is that we can intern a value without
allocating for zero-sized-types and for enum variants that have no
fields. This PR does this automatically in the `SystemSet` and
`ScheduleLabel` derive macros for unit structs and fieldless enum
variants. So this should cover many internal and external use cases of
`SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory
will be allocated.

- The interning returns a `Interned<dyn SystemSet>`, which is just a
wrapper around a `&'static dyn SystemSet`.
- `Hash` and `Eq` are implemented in terms of the pointer value of the
reference, similar to my first approach of anonymous system sets in
#7676.
- Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`.
- The debug output of `Interned<T>` is the same as the interned value.

Edit: 
- `AppLabel` is now also interned and the old
`derive_label`/`define_label` macros were replaced with the new
interning implementation.
- Anonymous set ids are reused for different `Schedule`s, reducing the
amount of leaked memory.

### Pros
- `InternedSystemSet` and `InternedScheduleLabel` behave very similar to
the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied
without an allocation.
- Many use cases don't allocate at all.
- Very fast lookups and comparisons when using `InternedSystemSet` and
`InternedScheduleLabel`.
- The `intern` module might be usable in other areas.
- `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement
`{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics.

### Cons
- Implementors of `SystemSet` and `ScheduleLabel` still need to
implement `Hash` and `Eq` (and `Clone`) for it to work.

## Changelog

### Added

- Added `intern` module to `bevy_utils`.
- Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`.

### Changed

- Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with
`InternedSystemSet` and `InternedScheduleLabel`.
- Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`.
- Replaced `AppLabelId` with `InternedAppLabel`.
- Changed `AppLabel` to use `Debug` for error messages.
- Changed `AppLabel` to use interning.
- Changed `define_label`/`derive_label` to use interning. 
- Replaced `define_boxed_label`/`derive_boxed_label` with
`define_label`/`derive_label`.
- Changed anonymous set ids to be only unique inside a schedule, not
globally.
- Made interned label types implement their label trait. 

### Removed

- Removed `define_boxed_label` and `derive_boxed_label`. 

## Migration guide

- Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with
`InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`.
- Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with
`InternedSystemSet` or `Interned<dyn SystemSet>`.
- Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn
AppLabel>`.
- Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet`
need to implement:
  - `dyn_hash` directly instead of implementing `DynHash`
  - `as_dyn_eq`
- Pass labels to `World::try_schedule_scope`, `World::schedule_scope`,
`World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`,
`Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and
`Schedules::get_mut` by value instead of by reference.

---------

Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-10-25 21:39:23 +00:00
Joseph
0716922165
ParamSets containing non-send parameters should also be non-send (#10211)
# Objective

Fix #10207

## Solution

Mark a `ParamSet`'s `SystemMeta` as non-send if any of its component
parameters are non-send.
2023-10-21 18:07:52 +00:00
Mike
687e379800
Updates for rust 1.73 (#10035)
# Objective

- Updates for rust 1.73

## Solution

- new doc check for `redundant_explicit_links`
- updated to text for compile fail tests

---

## Changelog

- updates for rust 1.73
2023-10-06 00:31:10 +00:00
Nicola Papale
1bf271d56e
Add a public API to ArchetypeGeneration/Id (#9825)
Objective
---------

- Since #6742, It is not possible to build an `ArchetypeId` from a
`ArchetypeGeneration`
- This was useful to 3rd party crate extending the base bevy ECS
capabilities, such as [`bevy_ecs_dynamic`] and now
[`bevy_mod_dynamic_query`]
- Making `ArchetypeGeneration` opaque this way made it completely
useless, and removed the ability to limit archetype updates to a subset
of archetypes.
- Making the `index` method on `ArchetypeId` private prevented the use
of bitfields and other optimized data structure to store sets of
archetype ids. (without `transmute`)

This PR is not a simple reversal of the change. It exposes a different
API, rethought to keep the private stuff private and the public stuff
less error-prone.

- Add a `StartRange<ArchetypeGeneration>` `Index` implementation to
`Archetypes`
- Instead of converting the generation into an index, then creating a
ArchetypeId from that index, and indexing `Archetypes` with it, use
directly the old `ArchetypeGeneration` to get the range of new
archetypes.

From careful benchmarking, it seems to also be a performance improvement
(~0-5%) on add_archetypes.

---

Changelog
---------

- Added `impl Index<RangeFrom<ArchetypeGeneration>> for Archetypes` this
allows you to get a slice of newly added archetypes since the last
recorded generation.
- Added `ArchetypeId::index` and `ArchetypeId::new` methods. It should
enable 3rd party crates to use the `Archetypes` API in a meaningful way.

[`bevy_ecs_dynamic`]:
https://github.com/jakobhellermann/bevy_ecs_dynamic/tree/main
[`bevy_mod_dynamic_query`]:
https://github.com/nicopap/bevy_mod_dynamic_query/

---------

Co-authored-by: vero <email@atlasdostal.com>
2023-10-02 12:54:45 +00:00
Joseph
8cc255c2f0
Hide UnsafeWorldCell::unsafe_world (#9741)
# Objective

We've done a lot of work to remove the pattern of a `&World` with
interior mutability (#6404, #8833). However, this pattern still persists
within `bevy_ecs` via the `unsafe_world` method.

## Solution

* Make `unsafe_world` private. Adjust any callsites to use
`UnsafeWorldCell` for interior mutability.
* Add `UnsafeWorldCell::removed_components`, since it is always safe to
access the removed components collection through `UnsafeWorldCell`.

## Future Work

Remove/hide `UnsafeWorldCell::world_metadata`, once we have provided
safe ways of accessing all world metadata.

---

## Changelog

+ Added `UnsafeWorldCell::removed_components`, which provides read-only
access to a world's collection of removed components.
2023-10-02 12:46:43 +00:00
SADIK KUZU
483f2464a8
Fix typos (#9965)
# Objective

- There were a few typos in the project.
- This PR fixes these typos.

## Solution

- Fixing the typos.

Signed-off-by: SADIK KUZU <sadikkuzu@hotmail.com>
2023-09-29 12:26:41 +00:00
Bruce Mitchener
a5a457c3c8
docs: Use intradoc links for method references. (#9958)
# Objective

- Use intradoc links to let the compiler verify correctness.

## Solution

- Use intradoc links.
2023-09-29 07:09:14 +00:00
Rob Parrett
7063c86ed4
Fix some typos (#9934)
# Objective

To celebrate the turning of the seasons, I took a small walk through the
codebase guided by the "[code spell
checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)"
VS Code extension and fixed a few typos.
2023-09-26 19:46:24 +00:00
Joseph
e60249e59d
Improve codegen for world validation (#9464)
# Objective

Improve code-gen for `QueryState::validate_world` and
`SystemState::validate_world`.

## Solution

* Move panics into separate, non-inlined functions, to reduce the code
size of the outer methods.
* Mark the panicking functions with `#[cold]` to help the compiler
optimize for the happy path.
* Mark the functions with `#[track_caller]` to make debugging easier.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2023-09-21 20:57:06 +00:00
Ethereumdegen
3ee9edf280
add try_insert to entity commands (#9844)
# Objective

- I spoke with some users in the ECS channel of bevy discord today and
they suggested that I implement a fallible form of .insert for
components.

- In my opinion, it would be nice to have a fallible .insert like
.try_insert (or to just make insert be fallible!) because it was causing
a lot of panics in my game. In my game, I am spawning terrain chunks and
despawning them in the Update loop. However, this was causing bevy_xpbd
to panic because it was trying to .insert some physics components on my
chunks and a race condition meant that its check to see if the entity
exists would pass but then the next execution step it would not exist
and would do an .insert and then panic. This means that there is no way
to avoid a panic with conditionals.

Luckily, bevy_xpbd does not care about inserting these components if the
entity is being deleted and so if there were a .try_insert, like this PR
provides it could use that instead in order to NOT panic.

( My interim solution for my own game has been to run the entity despawn
events in the Last schedule but really this is just a hack and I should
not be expected to manage the scheduling of despawns like this - it
should just be easy and simple. IF it just so happened that bevy_xpbd
ran .inserts in the Last schedule also, this would be an untenable soln
overall )

## Solution

- Describe the solution used to achieve the objective above.

Add a new command named TryInsert (entitycommands.try_insert) which
functions exactly like .insert except if the entity does not exist it
will not panic. Instead, it will log to info. This way, crates that are
attaching components in ways which they do not mind that the entity no
longer exists can just use try_insert instead of insert.

---

## Changelog

 

## Additional Thoughts

In my opinion, NOT panicing should really be the default and having an
.insert that does panic should be the odd edgecase but removing the
panic! from .insert seems a bit above my paygrade -- although i would
love to see it. My other thought is it would be good for .insert to
return an Option AND not panic but it seems it uses an event bus right
now so that seems to be impossible w the current architecture.
2023-09-20 19:34:30 +00:00
Trashtalk217
e4b368721d
One Shot Systems (#8963)
I'm adopting this ~~child~~ PR.

# Objective

- Working with exclusive world access is not always easy: in many cases,
a standard system or three is more ergonomic to write, and more
modularly maintainable.
- For small, one-off tasks (commonly handled with scripting), running an
event-reader system incurs a small but flat overhead cost and muddies
the schedule.
- Certain forms of logic (e.g. turn-based games) want very fine-grained
linear and/or branching control over logic.
- SystemState is not automatically cached, and so performance can suffer
and change detection breaks.
- Fixes https://github.com/bevyengine/bevy/issues/2192.
- Partial workaround for https://github.com/bevyengine/bevy/issues/279.

## Solution

- Adds a SystemRegistry resource to the World, which stores initialized
systems keyed by their SystemSet.
- Allows users to call world.run_system(my_system) and
commands.run_system(my_system), without re-initializing or losing state
(essential for change detection).
- Add a Callback type to enable convenient use of dynamic one shot
systems and reduce the mental overhead of working with Box<dyn
SystemSet>.
- Allow users to run systems based on their SystemSet, enabling more
complex user-made abstractions.

## Future work

- Parameterized one-shot systems would improve reusability and bring
them closer to events and commands. The API could be something like
run_system_with_input(my_system, my_input) and use the In SystemParam.
- We should evaluate the unification of commands and one-shot systems
since they are two different ways to run logic on demand over a World.

### Prior attempts

- https://github.com/bevyengine/bevy/pull/2234
- https://github.com/bevyengine/bevy/pull/2417
- https://github.com/bevyengine/bevy/pull/4090
- https://github.com/bevyengine/bevy/pull/7999

This PR continues the work done in
https://github.com/bevyengine/bevy/pull/7999.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Federico Rinaldi <gisquerin@gmail.com>
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Alejandro Pascual Pozo <alejandro.pascual.pozo@gmail.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Dmytro Banin <banind@cs.washington.edu>
Co-authored-by: James Liu <contact@jamessliu.com>
2023-09-19 20:17:05 +00:00
louis-le-cam
9ee9d627d7
Rename RemovedComponents::iter/iter_with_id to read/read_with_id (#9778)
# Objective

Rename RemovedComponents::iter/iter_with_id to read/read_with_id to make
it clear that it consume the data

Fixes #9755.

(It's my first pull request, if i've made any mistake, please let me
know)

## Solution

Refactor RemovedComponents::iter/iter_with_id to read/read_with_id



## Changelog

Refactor RemovedComponents::iter/iter_with_id to read/read_with_id

Deprecate RemovedComponents::iter/iter_with_id

Remove IntoIterator implementation

Update removal_detection example accordingly

---

## Migration Guide

Rename calls of RemovedComponents::iter/iter_with_id to
read/read_with_id

Replace IntoIterator iteration (&mut <RemovedComponents>) with .read()

---------

Co-authored-by: denshi_ika <mojang2824@gmail.com>
2023-09-15 12:37:20 +00:00
Mike
324c057b71
Cache System Tracing Spans (#9390)
# Objective

- Reduce the overhead of tracing by caching the system spans.

Yellow is this pr. Red is main.


![image](https://github.com/bevyengine/bevy/assets/2180432/fe9bb7c2-ae9a-4522-80a9-75a943a562b6)
2023-09-13 19:10:11 +00:00
Zachary Harrold
4c6b6fc24a
Moved get_component(_unchecked_mut) from Query to QueryState (#9686)
# Objective

- Fixes #9683

## Solution

- Moved `get_component` from `Query` to `QueryState`.
- Moved `get_component_unchecked_mut` from `Query` to `QueryState`.
- Moved `QueryComponentError` from `bevy_ecs::system` to
`bevy_ecs::query`. Minor Breaking Change.
- Narrowed scope of `unsafe` blocks in `Query` methods.

---

## Migration Guide

- `use bevy_ecs::system::QueryComponentError;` -> `use
bevy_ecs::query::QueryComponentError;`

## Notes

I am not very familiar with unsafe Rust nor its use within Bevy, so I
may have committed a Rust faux pas during the migration.

---------

Co-authored-by: Zac Harrold <zharrold@c5prosolutions.com>
Co-authored-by: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com>
2023-09-11 19:04:22 +00:00
Edgar Geier
118509e4aa
Replace IntoSystemSetConfig with IntoSystemSetConfigs (#9247)
# Objective

- Fixes #9244.

## Solution


- Changed the `(Into)SystemSetConfigs` traits and structs be more like
the `(Into)SystemConfigs` traits and structs.
- Replaced uses of `IntoSystemSetConfig` with `IntoSystemSetConfigs`
- Added generic `ItemConfig` and `ItemConfigs` types.
- Changed `SystemConfig(s)` and `SystemSetConfig(s)` to be type aliases
to `ItemConfig(s)`.
- Added generic `process_configs` to `ScheduleGraph`.
- Changed `configure_sets_inner` and `add_systems_inner` to reuse
`process_configs`.

---

## Changelog

- Added `run_if` to `IntoSystemSetConfigs`
- Deprecated `Schedule::configure_set` and `App::configure_set`
- Removed `IntoSystemSetConfig`

## Migration Guide

- Use `App::configure_sets` instead of `App::configure_set`
- Use `Schedule::configure_sets` instead of `Schedule::configure_set`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-09-05 17:15:27 +00:00
Hennadii Chernyshchyk
9309d89bb8
Add panicking helpers for getting components from Query (#9659)
# Objective

- Currently we don't have panicking alternative for getting components
from `Query` like for resources. Partially addresses #9443.

## Solution

- Add these functions.

---

## Changelog

### Added

- `Query::component` and `Query::component_mut` to get specific
component from query and panic on error.
2023-09-04 12:31:12 +00:00
Joseph
58f7dac689
Fix unsoundness in QueryState::is_empty (#9463)
# Objective

`QueryState::is_empty` is unsound, as it does not validate the world. If
a mismatched world is passed in, then the query filter may cast a
component to an incorrect type, causing undefined behavior.

## Solution

Add world validation. To prevent a performance regression in `Query`
(whose world does not need to be validated), the unchecked function
`is_empty_unsafe_world_cell` has been added. This also allows us to
remove one of the last usages of the private function
`UnsafeWorldCell::unsafe_world`, which takes us a step towards being
able to remove that method entirely.
2023-09-02 23:43:22 +00:00
Joseph
bc8bf34818
Allow disjoint mutable world access via EntityMut (#9419)
# Objective

Fix #4278
Fix #5504
Fix #9422

Provide safe ways to borrow an entire entity, while allowing disjoint
mutable access. `EntityRef` and `EntityMut` are not suitable for this,
since they provide access to the entire world -- they are just helper
types for working with `&World`/`&mut World`.

This has potential uses for reflection and serialization

## Solution

Remove `EntityRef::world`, which allows it to soundly be used within
queries.

`EntityMut` no longer supports structural world mutations, which allows
multiple instances of it to exist for different entities at once.
Structural world mutations are performed using the new type
`EntityWorldMut`.

```rust
fn disjoint_system(
     q2: Query<&mut A>,
     q1: Query<EntityMut, Without<A>>,
) { ... }

let [entity1, entity2] = world.many_entities_mut([id1, id2]);
*entity1.get_mut::<T>().unwrap() = *entity2.get().unwrap();

for entity in world.iter_entities_mut() {
    ...
}
```

---

## Changelog

- Removed `EntityRef::world`, to fix a soundness issue with queries.
+ Removed the ability to structurally mutate the world using
`EntityMut`, which allows it to be used in queries.
+ Added `EntityWorldMut`, which is used to perform structural mutations
that are no longer allowed using `EntityMut`.

## Migration Guide

**Note for maintainers: ensure that the guide for #9604 is updated
accordingly.**

Removed the method `EntityRef::world`, to fix a soundness issue with
queries. If you need access to `&World` while using an `EntityRef`,
consider passing the world as a separate parameter.

`EntityMut` can no longer perform 'structural' world mutations, such as
adding or removing components, or despawning the entity. Additionally,
`EntityMut::world`, `EntityMut::world_mut` , and
`EntityMut::world_scope` have been removed.
Instead, use the newly-added type `EntityWorldMut`, which is a helper
type for working with `&mut World`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-08-28 23:30:59 +00:00
Mike
33fdc5f5db
Move schedule name into Schedule (#9600)
# Objective

- Move schedule name into `Schedule` to allow the schedule name to be
used for errors and tracing in Schedule methods
- Fixes #9510

## Solution

- Move label onto `Schedule` and adjust api's on `World` and `Schedule`
to not pass explicit label where it makes sense to.
- add name to errors and tracing.
- `Schedule::new` now takes a label so either add the label or use
`Schedule::default` which uses a default label. `default` is mostly used
in doc examples and tests.

---

## Changelog

- move label onto `Schedule` to improve error message and logging for
schedules.

## Migration Guide

`Schedule::new` and `App::add_schedule`
```rust
// old
let schedule = Schedule::new();
app.add_schedule(MyLabel, schedule);

// new
let schedule = Schedule::new(MyLabel);
app.add_schedule(schedule);
```

if you aren't using a label and are using the schedule struct directly
you can use the default constructor.
```rust
// old
let schedule = Schedule::new();
schedule.run(world);

// new
let schedule = Schedule::default();
schedule.run(world);
```

`Schedules:insert`
```rust
// old
let schedule = Schedule::new();
schedules.insert(MyLabel, schedule);

// new
let schedule = Schedule::new(MyLabel);
schedules.insert(schedule);
```

`World::add_schedule`
```rust
// old
let schedule = Schedule::new();
world.add_schedule(MyLabel, schedule);

// new
let schedule = Schedule::new(MyLabel);
world.add_schedule(schedule);
```
2023-08-28 20:44:48 +00:00
Noah
72fc63e594
implement insert and remove reflected entity commands (#8895)
# Objective

To enable non exclusive system usage of reflected components and make
reflection more ergonomic to use by making it more in line with standard
entity commands.

## Solution

- Implements a new `EntityCommands` extension trait for reflection
related functions in the reflect module of bevy_ecs.
- Implements 4 new commands, `insert_reflect`,
`insert_reflect_with_registry`, `remove_reflect`, and
`remove_reflect_with_registry`. Both insert commands take a `Box<dyn
Reflect>` component while the remove commands take the component type
name.

- Made `EntityCommands` fields pub(crate) to allow access in the reflect
module. (Might be worth making these just public to enable user end
custom entity commands in a different pr)
- Added basic tests to ensure the commands are actually working.
- Documentation of functions.

---

## Changelog

Added:
-  Implements 4 new commands on the new entity commands extension.
- `insert_reflect`
- `remove_reflect`
- `insert_reflect_with_registry`
- `remove_reflect_with_registry`

The commands operate the same except the with_registry commands take a
generic parameter for a resource that implements `AsRef<TypeRegistry>`.
Otherwise the default commands use the `AppTypeRegistry` for reflection
data.

Changed:

- Made `EntityCommands` fields pub(crate) to allow access in the reflect
module.

> Hopefully this time it works. Please don't make me rebase again ☹
2023-08-28 18:21:20 +00:00
Zachary Harrold
1839ff7e2a
Replaced EntityCommand Implementation for FnOnce (#9604)
# Objective

- Fixes #4917
- Replaces #9602

## Solution

- Replaced `EntityCommand` implementation for `FnOnce` to apply to
`FnOnce(EntityMut)` instead of `FnOnce(Entity, &mut World)`

---

## Changelog

- `FnOnce(Entity, &mut World)` no longer implements `EntityCommand`.
This is a breaking change.

## Migration Guide

### 1. New-Type `FnOnce`

Create an `EntityCommand` type which implements the method you
previously wrote:

```rust
pub struct ClassicEntityCommand<F>(pub F);

impl<F> EntityCommand for ClassicEntityCommand<F>
where
    F: FnOnce(Entity, &mut World) + Send + 'static,
{
    fn apply(self, id: Entity, world: &mut World) {
        (self.0)(id, world);
    }
}

commands.add(ClassicEntityCommand(|id: Entity, world: &mut World| {
    /* ... */
}));
```

### 2. Extract `(Entity, &mut World)` from `EntityMut`

The method `into_world_mut` can be used to gain access to the `World`
from an `EntityMut`.

```rust
let old = |id: Entity, world: &mut World| {
    /* ... */
};

let new = |mut entity: EntityMut| {
    let id = entity.id();
    let world = entity.into_world_mut();
    /* ... */
};
```
2023-08-28 18:08:53 +00:00
Joseph
da8ab16d83
Relax more Sync bounds on Local (#9589)
# Objective

#5483 allows for the creation of non-`Sync` locals. However, it's not
actually possible to use these types as there is a `Sync` bound on the
`Deref` impls.

## Solution

Remove the unnecessary bounds.
2023-08-28 17:47:15 +00:00
Joseph
474b55a29c
Add system.map(...) for transforming the output of a system (#8526)
# Objective

Any time we wish to transform the output of a system, we currently use
system piping to do so:

```rust
my_system.pipe(|In(x)| do_something(x))
```

Unfortunately, system piping is not a zero cost abstraction. Each call
to `.pipe` requires allocating two extra access sets: one for the second
system and one for the combined accesses of both systems. This also adds
extra work to each call to `update_archetype_component_access`, which
stacks as one adds multiple layers of system piping.

## Solution

Add the `AdapterSystem` abstraction: similar to `CombinatorSystem`, this
allows you to implement a trait to generically control how a system is
run and how its inputs and outputs are processed. Unlike
`CombinatorSystem`, this does not have any overhead when computing world
accesses which makes it ideal for simple operations such as inverting or
ignoring the output of a system.

Add the extension method `.map(...)`: this is similar to `.pipe(...)`,
only it accepts a closure as an argument instead of an `In<T>` system.

```rust
my_system.map(do_something)
```

This has the added benefit of making system names less messy: a system
that ignores its output will just be called `my_system`, instead of
`Pipe(my_system, ignore)`

---

## Changelog

TODO

## Migration Guide

The `system_adapter` functions have been deprecated: use `.map` instead,
which is a lightweight alternative to `.pipe`.

```rust
// Before:
my_system.pipe(system_adapter::ignore)
my_system.pipe(system_adapter::unwrap)
my_system.pipe(system_adapter::new(T::from))

// After:
my_system.map(std::mem::drop)
my_system.map(Result::unwrap)
my_system.map(T::from)

// Before:
my_system.pipe(system_adapter::info)
my_system.pipe(system_adapter::dbg)
my_system.pipe(system_adapter::warn)
my_system.pipe(system_adapter::error)

// After:
my_system.map(bevy_utils::info)
my_system.map(bevy_utils::dbg)
my_system.map(bevy_utils::warn)
my_system.map(bevy_utils::error)
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-08-28 16:36:46 +00:00
Joseph
e8b3892517
Improve various Debug implementations (#9588)
# Objective

* `Local` and `SystemName` implement `Debug` manually, but they could
derive it.
* `QueryState` and `dyn System` have unconventional debug formatting.
2023-08-26 21:27:41 +00:00
Christian Hughes
349dd8bd45
Relax In/Out bounds on impl Debug for dyn System (#9581)
# Objective

Resolves #9580

## Solution

Relaxed the bounds on the `Debug` impl for `dyn System`
2023-08-26 13:57:19 +00:00
Joseph
69750a03ca
Implement Debug for UnsafeWorldCell (#9460)
# Objective

* Add more ways to use `UnsafeWorldCell` in safe code -- you no longer
need to call `.world_metadata()` to format it.
2023-08-20 22:00:12 +00:00
Zeenobit
1e170d2e90
Add RunSystem (#9366)
Add a `RunSystem` extension trait to allow for immediate execution of
systems on a `World` for debugging and/or testing purposes.

# Objective

Fixes #6184

Initially, I made this CL as `ApplyCommands`. After a discussion with
@cart , we decided a more generic implementation would be better to
support all systems. This is the new revised CL. Sorry for the long
delay! 😅

This CL allows users to do this:
```rust
use bevy::prelude::*;
use bevy::ecs::system::RunSystem;

struct T(usize);

impl Resource for T {}

fn system(In(n): In<usize>, mut commands: Commands) -> usize {
    commands.insert_resource(T(n));
    n + 1
}

let mut world = World::default();
let n = world.run_system_with(1, system);
assert_eq!(n, 2);
assert_eq!(world.resource::<T>().0, 1);
```

## Solution

This is implemented as a trait extension and not included in any
preludes to ensure it's being used consciously.
Internally, it just initializes and runs a systems, and applies any
deferred parameters all "in place".
The trait has 2 functions (one of which calls the other by default):
- `run_system_with` is the general implementation, which allows user to
pass system input parameters
- `run_system` is the ergonomic wrapper for systems with no input
parameter (to avoid having the user pass `()` as input).

~~Additionally, this trait is also implemented for `&mut App`. I added
this mainly for ergonomics (`app.run_system` vs.
`app.world.run_system`).~~ (Removed based on feedback)

---------

Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2023-08-11 20:41:48 +00:00
Nicola Papale
77fa8a9a9c
Add a paragraph to the lifetimeless module doc (#9312)
# Objective

The `lifetimeless` module has been a source of confusion for bevy users
for a while now.

## Solution

Add a couple paragraph explaining that, yes, you can use one of the type
alias safely, without ever leaking any memory.
2023-08-02 22:01:56 +00:00
Ryan Devenney
264195ed77
replace parens with square brackets when referencing _mut on Query docs #9200 (#9223)
# Objective

Fixes #9200 
Switches ()'s to []'s when talking about the optional `_mut` suffix in
the ECS Query Struct page to have more idiomatic docs.

## Solution

Replace `()` with `[]` in appropriate doc pages.
2023-07-20 21:41:07 +00:00
ClayenKitten
ffc572728f
Fix typos throughout the project (#9090)
# Objective

Fix typos throughout the project.

## Solution

[`typos`](https://github.com/crate-ci/typos) project was used for
scanning, but no automatic corrections were applied. I checked
everything by hand before fixing.

Most of the changes are documentation/comments corrections. Also, there
are few trivial changes to code (variable name, pub(crate) function name
and a few error/panic messages).

## Unsolved

`bevy_reflect_derive` has
[typo](1b51053f19/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs (L76))
in enum variant name that I didn't fix. Enum is `pub(crate)`, so there
shouldn't be any trouble if fixed. However, code is tightly coupled with
macro usage, so I decided to leave it for more experienced contributor
just in case.
2023-07-10 00:11:51 +00:00
0xc0001a2040
15be0d1a61
Add/fix track_caller attribute on panicking entity accessor methods (#8951)
# Objective

`World::entity`, `World::entity_mut` and `Commands::entity` should be
marked with `track_caller` to display where (in user code) the call with
the invalid `Entity` was made. `Commands::entity` already has the
attibute, but it does nothing due to the call to `unwrap_or_else`.

## Solution

- Apply the `track_caller` attribute to the `World::entity_mut` and
`World::entity`.
- Remove the call to `unwrap_or_else` which makes the `track_caller`
attribute useless (because `unwrap_or_else` is not `track_caller`
itself). The avoid eager evaluation of the panicking branch it is never
inlined.

---------

Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
2023-06-26 18:35:11 +00:00
James Liu
70f91b2b9e
Implement WorldQuery for EntityRef (#6960)
# Objective
Partially address #5504. Fix #4278. Provide "whole entity" access in
queries. This can be useful when you don't know at compile time what
you're accessing (i.e. reflection via `ReflectComponent`).

## Solution
Implement `WorldQuery` for `EntityRef`. 

- This provides read-only access to the entire entity, and supports
anything that `EntityRef` can normally do.
- It matches all archetypes and tables and will densely iterate when
possible.
- It marks all of the ArchetypeComponentIds of a matched archetype as
read.
- Adding it to a query will cause it to panic if used in conjunction
with any other mutable access.
 - Expanded the docs on Query to advertise this feature.
 - Added tests to ensure the panics were working as intended.
 - Added `EntityRef` to the ECS prelude.

To make this safe, `EntityRef::world` was removed as it gave potential
`UnsafeCell`-like access to other parts of the `World` including aliased
mutable access to the components it would otherwise read safely.

## Performance
Not great beyond the additional parallelization opportunity over
exclusive systems. The `EntityRef` is fetched from `Entities` like any
other call to `World::entity`, which can be very random access heavy.
This could be simplified if `ArchetypeRow` is available in
`WorldQuery::fetch`'s arguments, but that's likely not something we
should optimize for.

## Future work
An equivalent API where it gives mutable access to all components on a
entity can be done with a scoped version of `EntityMut` where it does
not provide `&mut World` access nor allow for structural changes to the
entity is feasible as well. This could be done as a safe alternative to
exclusive system when structural mutation isn't required or the target
set of entities is scoped.

---

## Changelog
Added: `Access::has_any_write`
Added: `EntityRef` now implements `WorldQuery`. Allows read-only access
to the entire entity, incompatible with any other mutable access, can be
mixed with `With`/`Without` filters for more targeted use.
Added: `EntityRef` to `bevy::ecs::prelude`.
Removed: `EntityRef::world`

## Migration Guide
TODO

---------

Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
Co-authored-by: Jakob Hellermann <jakob.hellermann@protonmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-06-22 21:20:00 +00:00
Thierry Berger
17e1d211c5
doc: update a reference from add_system to add_systems (#8881)
Small fix for a forgotten documentation comment.
2023-06-18 17:17:02 +00:00
JoJoJet
8ec81496ff
Add a method to run read-only systems using &World (#8849)
# Objective

Resolves #7558.

Systems that are known to never modify the world implement the trait
`ReadOnlySystem`. This is a perfect place to add a safe API for running
a system with a shared reference to a World.

---

## Changelog

- Added the trait method `ReadOnlySystem::run_readonly`, which allows a
system to be run using `&World`.
2023-06-15 22:54:53 +00:00
JoJoJet
db8d3651e0
Migrate the rest of the engine to UnsafeWorldCell (#8833)
# Objective

Follow-up to #6404 and #8292.

Mutating the world through a shared reference is surprising, and it
makes the meaning of `&World` unclear: sometimes it gives read-only
access to the entire world, and sometimes it gives interior mutable
access to only part of it.

This is an up-to-date version of #6972.

## Solution

Use `UnsafeWorldCell` for all interior mutability. Now, `&World`
*always* gives you read-only access to the entire world.

---

## Changelog

TODO - do we still care about changelogs?

## Migration Guide

Mutating any world data using `&World` is now considered unsound -- the
type `UnsafeWorldCell` must be used to achieve interior mutability. The
following methods now accept `UnsafeWorldCell` instead of `&World`:

- `QueryState`: `get_unchecked`, `iter_unchecked`,
`iter_combinations_unchecked`, `for_each_unchecked`,
`get_single_unchecked`, `get_single_unchecked_manual`.
- `SystemState`: `get_unchecked_manual`

```rust
let mut world = World::new();
let mut query = world.query::<&mut T>();

// Before:
let t1 = query.get_unchecked(&world, entity_1);
let t2 = query.get_unchecked(&world, entity_2);

// After:
let world_cell = world.as_unsafe_world_cell();
let t1 = query.get_unchecked(world_cell, entity_1);
let t2 = query.get_unchecked(world_cell, entity_2);
```

The methods `QueryState::validate_world` and
`SystemState::matches_world` now take a `WorldId` instead of `&World`:

```rust
// Before:
query_state.validate_world(&world);

// After:
query_state.validate_world(world.id());
```

The methods `QueryState::update_archetypes` and
`SystemState::update_archetypes` now take `UnsafeWorldCell` instead of
`&World`:

```rust
// Before:
query_state.update_archetypes(&world);

// After:
query_state.update_archetypes(world.as_unsafe_world_cell_readonly());
```
2023-06-15 01:31:56 +00:00
Jonathan
c475e271be
Implement Clone for CombinatorSystem (#8826)
# Objective

Make a combined system cloneable if both systems are cloneable on their
own. This is necessary for using chained conditions (e.g
`cond1.and_then(cond2)`) with `distributive_run_if()`.

## Solution

Implement `Clone` for `CombinatorSystem<Func, A, B>` where `A, B:
Clone`.
2023-06-12 19:44:51 +00:00
Natanael Mojica
f135535cd6
Rename Command's "write" method to "apply" (#8814)
# Objective

- Fixes #8811 .

## Solution

- Rename "write" method to "apply" in Command trait definition.
- Rename other implementations of command trait throughout bevy's code
base.

---

## Changelog

- Changed: `Command::write` has been changed to `Command::apply`
- Changed: `EntityCommand::write` has been changed to
`EntityCommand::apply`

## Migration Guide

- `Command::write` implementations need to be changed to implement
`Command::apply` instead. This is a mere name change, with no further
actions needed.
- `EntityCommand::write` implementations need to be changed to implement
`EntityCommand::apply` instead. This is a mere name change, with no
further actions needed.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-06-12 17:53:47 +00:00
JoJoJet
32faf4cb5c
Document every public item in bevy_ecs (#8731)
# Objective

Title.

---------

Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
2023-06-10 23:23:48 +00:00
CatThingy
89cbc78d3d
Require #[derive(Event)] on all Events (#7086)
# Objective

Be consistent with `Resource`s and `Components` and have `Event` types
be more self-documenting.
Although not susceptible to accidentally using a function instead of a
value due to `Event`s only being initialized by their type, much of the
same reasoning for removing the blanket impl on `Resource` also applies
here.

* Not immediately obvious if a type is intended to be an event
* Prevent invisible conflicts if the same third-party or primitive types
are used as events
* Allows for further extensions (e.g. opt-in warning for missed events)

## Solution

Remove the blanket impl for the `Event` trait. Add a derive macro for
it.

---

## Changelog

- `Event` is no longer implemented for all applicable types. Add the
`#[derive(Event)]` macro for events.

## Migration Guide

* Add the `#[derive(Event)]` macro for events. Third-party types used as
events should be wrapped in a newtype.
2023-06-06 14:44:32 +00:00
Alice Cecile
cbd4abf0fc
Rename apply_system_buffers to apply_deferred (#8726)
# Objective

- `apply_system_buffers` is an unhelpful name: it introduces a new
internal-only concept
- this is particularly rough for beginners as reasoning about how
commands work is a critical stumbling block

## Solution

- rename `apply_system_buffers` to the more descriptive `apply_deferred`
- rename related fields, arguments and methods in the internals fo
bevy_ecs for consistency
- update the docs


## Changelog

`apply_system_buffers` has been renamed to `apply_deferred`, to more
clearly communicate its intent and relation to `Deferred` system
parameters like `Commands`.

## Migration Guide

- `apply_system_buffers` has been renamed to `apply_deferred`
- the `apply_system_buffers` method on the `System` trait has been
renamed to `apply_deferred`
- the `is_apply_system_buffers` function has been replaced by
`is_apply_deferred`
- `Executor::set_apply_final_buffers` is now
`Executor::set_apply_final_deferred`
- `Schedule::apply_system_buffers` is now `Schedule::apply_deferred`

---------

Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
2023-06-02 14:04:13 +00:00
JoJoJet
5472ea4a14
Improve encapsulation for commands and add docs (#8725)
# Objective

Several of our built-in `Command` types are too public:
- `GetOrSpawn` is public, even though it only makes sense to call it
from within `Commands::get_or_spawn`.
- `Remove` and `RemoveResource` contain public `PhantomData` marker
fields.

## Solution

Remove `GetOrSpawn` and use an anonymous command. Make the marker fields
private.

---

## Migration Guide

The `Command` types `Remove` and `RemoveResource` may no longer be
constructed manually.

```rust
// Before:
commands.add(Remove::<T> {
    entity: id,
    phantom: PhantomData,
});

// After:
commands.add(Remove::<T>::new(id));

// Before:
commands.add(RemoveResource::<T> { phantom: PhantomData });

// After:
commands.add(RemoveResource::<T>::new());
```

The command type `GetOrSpawn` has been removed. It was not possible to
use this type outside of `bevy_ecs`.
2023-05-31 16:45:46 +00:00
Sélène Amanita
ca81d3e435
Document query errors (#8692)
# Objective

Add documentation to `Query` and `QueryState` errors in bevy_ecs
(`QuerySingleError`, `QueryEntityError`, `QueryComponentError`)

## Solution

- Change display message for `QueryEntityError::QueryDoesNotMatch`: this
error can also happen when the entity has a component which is filtered
out (with `Without<C>`)
- Fix wrong reference in the documentation of `Query::get_component` and
`Query::get_component_mut` from `QueryEntityError` to
`QueryComponentError`
- Complete the documentation of the three error enum variants.
- Add examples for `QueryComponentError::MissingReadAccess` and
`QueryComponentError::MissingWriteAccess`
- Add reference to `QueryState` in `QueryEntityError`'s documentation.

---

## Migration Guide

Expect `QueryEntityError::QueryDoesNotMatch`'s display message to
change? Not sure that counts.

---------

Co-authored-by: harudagondi <giogdeasis@gmail.com>
2023-05-30 14:41:14 +00:00
JoJoJet
85a918a8dd
Improve safety for the multi-threaded executor using UnsafeWorldCell (#8292)
# Objective

Fix #7833.

Safety comments in the multi-threaded executor don't really talk about
system world accesses, which makes it unclear if the code is actually
valid.

## Solution

Update the `System` trait to use `UnsafeWorldCell`. This type's API is
written in a way that makes it much easier to cleanly maintain safety
invariants. Use this type throughout the multi-threaded executor, with a
liberal use of safety comments.

---

## Migration Guide

The `System` trait now uses `UnsafeWorldCell` instead of `&World`. This
type provides a robust API for interior mutable world access.
- The method `run_unsafe` uses this type to manage world mutations
across multiple threads.
- The method `update_archetype_component_access` uses this type to
ensure that only world metadata can be used.

```rust
let mut system = IntoSystem::into_system(my_system);
system.initialize(&mut world);

// Before:
system.update_archetype_component_access(&world);
unsafe { system.run_unsafe(&world) }

// After:
system.update_archetype_component_access(world.as_unsafe_world_cell_readonly());
unsafe { system.run_unsafe(world.as_unsafe_world_cell()) }
```

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2023-05-29 15:22:10 +00:00
Troels Jessen
55d6c7d56e
Added reference to ParallelCommands in the Commands doc (#8510)
# Objective

Fixes #8414

---------

Co-authored-by: Sheepyhead <trojes@tuta.io>
Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
2023-05-01 15:31:33 +00:00
Wybe Westra
abf12f3b3b
Fixed several missing links in docs. (#8117)
Links in the api docs are nice. I noticed that there were several places
where structs / functions and other things were referenced in the docs,
but weren't linked. I added the links where possible / logical.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
2023-04-23 17:28:36 +00:00
JoJoJet
ce252f8cf7
Reorganize system modules (#8419)
# Objective

Follow-up to #8377.

As the system module has been refactored, there are many types that no
longer make sense to live in the files that they do:
- The `IntoSystem` trait is in `function_system.rs`, even though this
trait is relevant to all kinds of systems. Same for the `In<T>` type.
- `PipeSystem` is now just an implementation of `CombinatorSystem`, so
`system_piping.rs` no longer needs its own file.

## Solution

- Move `IntoSystem`, `In<T>`, and system piping combinators & tests into
the top-level `mod.rs` file for `bevy_ecs::system`.
- Move `PipeSystem` into `combinator.rs`.
2023-04-17 21:10:57 +00:00
JoJoJet
b03b7b557e
Simplify system piping and make it more flexible (#8377)
# Objective

- Currently, it is not possible to call `.pipe` on a system that takes
any input other than `()`.
- The `IntoPipeSystem` trait is currently very difficult to parse due to
its use of generics.

## Solution

Remove the `IntoPipeSystem` trait, and move the `pipe` method to
`IntoSystem`.

---

## Changelog

- System piping has been made more flexible: it is now possible to call
`.pipe` on a system that takes an input.

## Migration Guide

The `IntoPipeSystem` trait has been removed, and the `pipe` method has
been moved to the `IntoSystem` trait.

```rust

// Before:
use bevy_ecs::system::IntoPipeSystem;
schedule.add_systems(first.pipe(second));

// After:
use bevy_ecs::system::IntoSystem;
schedule.add_systems(first.pipe(second));
```
2023-04-17 16:08:32 +00:00
JoJoJet
328347f44c
Add a missing safety invariant to System::run_unsafe (#7778)
# Objective

The implementation of `System::run_unsafe` for `FunctionSystem` requires
that the world is the same one used to initialize the system. However,
the `System` trait has no requirements that the world actually matches,
which makes this implementation unsound.

This was previously mentioned in
https://github.com/bevyengine/bevy/pull/7605#issuecomment-1426491871

Fixes part of #7833.

## Solution

Add the safety invariant that
`System::update_archetype_component_access` must be called prior to
`System::run_unsafe`. Since
`FunctionSystem::update_archetype_component_access` properly validates
the world, this ensures that `run_unsafe` is not called with a
mismatched world.

Most exclusive systems are not required to be run on the same world that
they are initialized with, so this is not a concern for them. Systems
formed by combining an exclusive system with a regular system *do*
require the world to match, however the validation is done inside of
`System::run` when needed.
2023-04-17 15:20:42 +00:00
Vladyslav Batyrenko
71fccb2897
Improve or-with disjoint checks (#7085)
# Objective

This PR attempts to improve query compatibility checks in scenarios
involving `Or` filters.

Currently, for the following two disjoint queries, Bevy will throw a
panic:

```
fn sys(_: Query<&mut C, Or<(With<A>, With<B>)>>, _: Query<&mut C, (Without<A>, Without<B>)>) {}
``` 

This PR addresses this particular scenario.

## Solution

`FilteredAccess::with` now stores a vector of `AccessFilters`
(representing a pair of `with` and `without` bitsets), where each member
represents an `Or` "variant".
Filters like `(With<A>, Or<(With<B>, Without<C>)>` are expected to be
expanded into `A * B + A * !C`.

When calculating whether queries are compatible, every `AccessFilters`
of a query is tested for incompatibility with every `AccessFilters` of
another query.

---

## Changelog

- Improved system and query data access compatibility checks in
scenarios involving `Or` filters

---------

Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-04-17 15:16:58 +00:00
JoJoJet
c37a53d52d
Add a regression test for change detection between piped systems (#8368)
# Objective

The behavior of change detection within `PipeSystem` is very tricky and
subtle, and is not currently covered by any of our tests as far as I'm
aware.
2023-04-13 17:59:29 +00:00
Mikkel Rasmussen
e9312254d8
Non-breaking change* from UK spellings to US (#8291)
Fixes issue mentioned in PR #8285.

_Note: By mistake, this is currently dependent on #8285_
# Objective

Ensure consistency in the spelling of the documentation.

Exceptions:
`crates/bevy_mikktspace/src/generated.rs` - Has not been changed from
licence to license as it is part of a licensing agreement.

Maybe for further consistency,
https://github.com/bevyengine/bevy-website should also be given a look.

## Solution

### Changed the spelling of the current words (UK/CN/AU -> US) :
cancelled -> canceled (Breaking API changes in #8285)
behaviour -> behavior (Breaking API changes in #8285)
neighbour -> neighbor
grey -> gray
recognise -> recognize
centre -> center
metres -> meters
colour -> color

### ~~Update [`engine_style_guide.md`]~~ Moved to #8324 

---

## Changelog

Changed UK spellings in documentation to US

## Migration Guide

Non-breaking changes*

\* If merged after #8285
2023-04-08 16:22:46 +00:00
JoJoJet
3442a13d2c
Use UnsafeWorldCell to increase code quality for SystemParam (#8174)
# Objective

The type `&World` is currently in an awkward place, since it has two
meanings:
1. Read-only access to the entire world.
2. Interior mutable access to the world; immutable and/or mutable access
to certain portions of world data.

This makes `&World` difficult to reason about, and surprising to see in
function signatures if one does not know about the interior mutable
property.

The type `UnsafeWorldCell` was added in #6404, which is meant to
alleviate this confusion by adding a dedicated type for interior mutable
world access. However, much of the engine still treats `&World` as an
interior mutable-ish type. One of those places is `SystemParam`.

## Solution

Modify `SystemParam::get_param` to accept `UnsafeWorldCell` instead of
`&World`. Simplify the safety invariants, since the `UnsafeWorldCell`
type encapsulates the concept of constrained world access.

---

## Changelog

`SystemParam::get_param` now accepts an `UnsafeWorldCell` instead of
`&World`. This type provides a high-level API for unsafe interior
mutable world access.

## Migration Guide

For manual implementers of `SystemParam`: the function `get_item` now
takes `UnsafeWorldCell` instead of `&World`. To access world data, use:

* `.get_entity()`, which returns an `UnsafeEntityCell` which can be used
to access component data.
* `get_resource()` and its variants, to access resource data.
2023-04-01 15:45:07 +00:00
JoJoJet
a954f3e150
Remove #[system_param(ignore)] and #[world_query(ignore)] (#8265)
# Objective

Follow-up to #8030.

Now that `SystemParam` and `WorldQuery` are implemented for
`PhantomData`, the `ignore` attributes are now unnecessary.

---

## Changelog

- Removed the attributes `#[system_param(ignore)]` and
`#[world_query(ignore)]`.

## Migration Guide

The attributes `#[system_param(ignore)]` and `#[world_query]` ignore
have been removed. If you were using either of these with `PhantomData`
fields, you can simply remove the attribute:

```rust
#[derive(SystemParam)]
struct MyParam<'w, 's, Marker> {
    ...
    // Before:
    #[system_param(ignore)
    _marker: PhantomData<Marker>,

    // After:
    _marker: PhantomData<Marker>,
}
#[derive(WorldQuery)]
struct MyQuery<Marker> {
    ...
    // Before:
    #[world_query(ignore)
    _marker: PhantomData<Marker>,

    // After:
    _marker: PhantomData<Marker>,
}
```

If you were using this for another type that implements `Default`,
consider wrapping that type in `Local<>` (this only works for
`SystemParam`):

```rust
#[derive(SystemParam)]
struct MyParam<'w, 's> {
    // Before:
    #[system_param(ignore)]
    value: MyDefaultType, // This will be initialized using `Default` each time `MyParam` is created.

    // After:
    value: Local<MyDefaultType>, // This will be initialized using `Default` the first time `MyParam` is created.
}
```

If you are implementing either trait and need to preserve the exact
behavior of the old `ignore` attributes, consider manually implementing
`SystemParam` or `WorldQuery` for a wrapper struct that uses the
`Default` trait:

```rust
// Before:

#[derive(WorldQuery)
struct MyQuery {
   #[world_query(ignore)]
    str: String,
}

// After:

#[derive(WorldQuery)
struct MyQuery {
    str: DefaultQuery<String>,
}

pub struct DefaultQuery<T: Default>(pub T);

unsafe impl<T: Default> WorldQuery for DefaultQuery<T> {
    type Item<'w> = Self;
    ...
    unsafe fn fetch<'w>(...) -> Self::Item<'w> {
        Self(T::default())
    }
}
```
2023-03-30 23:02:25 +00:00
JoJoJet
98954311b3
Use actual tests for SystemParam regression tests (#8270)
# Objective

Our regression tests for `SystemParam` currently consist of a bunch of
loosely dispersed struct definitions. This is messy, and doesn't fully
test their functionality.

## Solution

Group the struct definitions into functions annotated with `#[test]`.
This not only makes the module more organized, but it allows us to call
`assert_is_system`, which has the potential to catch some bugs that
would have been missed with the old approach. Also, this approach is
consistent with how `WorldQuery` regression tests are organized.
2023-03-30 21:47:36 +00:00
JoJoJet
d9113cca6f
Make #[system_param(ignore)] and #[world_query(ignore)] unnecessary (#8030)
# Objective

When using `PhantomData` fields with the `#[derive(SystemParam)]` or
`#[derive(WorldQuery)]` macros, the user is required to add the
`#[system_param(ignore)]` attribute so that the macro knows to treat
that field specially. This is undesirable, since it makes the macro more
fragile and less consistent.

## Solution

Implement `SystemParam` and `WorldQuery` for `PhantomData`. This makes
the `ignore` attributes unnecessary.

Some internal changes make the derive macro compatible with types that
have invariant lifetimes, which fixes #8192. From what I can tell, this
fix requires `PhantomData` to implement `SystemParam` in order to ensure
that all of a type's generic parameters are always constrained.

---

## Changelog

+ Implemented `SystemParam` and `WorldQuery` for `PhantomData<T>`.
+ Fixed a miscompilation caused when invariant lifetimes were used with
the `SystemParam` macro.
2023-03-30 15:12:26 +00:00
Rob Parrett
a141aed67d
Format SystemState doc example code (#8261)
# Objective

I noticed some funky whitespace in the examples in the
[`SystemState`](https://docs.rs/bevy/latest/bevy/ecs/system/struct.SystemState.html#example)
doc examples.

## Solution

Semi-manually reformatted these particular code blocks and hid some of
the imports and boilerplate not relevant to the example.


([format_code_in_doc_comments](https://rust-lang.github.io/rustfmt/?version=v1.5.1&search=#format_code_in_doc_comments)
seemingly has a bunch of issues and has not been stabilized)
2023-03-30 10:06:05 +00:00
Robert Walter
5f0abbfd15
Make standard commands more ergonomic (in niche cases) (#8249)
# Objective

I ran into a case where I need to create a `CommandQueue` and push
standard `Command` actions like `Insert` or `Remove` to it manually. I
saw that `Remove` looked as follows:

```rust
struct Remove<T> {
  entity: Entity,
  phantom: PhantomData<T>
}
```

so naturally, I tried to use `Remove::<Foo>::from(entity)` but it didn't
exist. We need to specify the `PhantomData` explicitly when creating
this command action. The same goes for `RemoveResource` and
`InitResource`

## Solution

This PR implements the following:

- `From<Entity>` for `Remove<T>`
- `Default` for `RemoveResource` and `InitResource`
- use these traits in the implementation of methods of `Commands`
- rename `phantom` field on the structs above to `_phantom` to have a
more uniform field naming scheme for the command actions

---

## Changelog

> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.

- Added: implemented `From<Entity>` for `Remove<T>` and `Default` for
`RemoveResource` and `InitResource` for ergonomics

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-03-29 18:27:48 +00:00
Trevor Lovell
464d35aef5
docs: update docs and comments that still refer to stages (#8156)
# Objective
Documentation should no longer be using pre-stageless terminology to
avoid confusion.

## Solution
- update all docs referring to stages to instead refer to sets/schedules
where appropriate
- also mention `apply_system_buffers` for anything system-buffer-related
that previously referred to buffers being applied "at the end of a
stage"
2023-03-27 21:50:21 +00:00
JoJoJet
27f2265e11
Fix name conflicts caused by the SystemParam and WorldQuery macros (#8012)
# Objective

Fix #1727
Fix #8010

Meta types generated by the `SystemParam` and `WorldQuery` derive macros
can conflict with user-defined types if they happen to have the same
name.

## Solution

In order to check if an identifier would conflict with user-defined
types, we can just search the original `TokenStream` passed to the macro
to see if it contains the identifier (since the meta types are defined
in an anonymous scope, it's only possible for them to conflict with the
struct definition itself). When generating an identifier for meta types,
we can simply check if it would conflict, and then add additional
characters to the name until it no longer conflicts with anything.

The `WorldQuery` "Item" and read-only structs are a part of a module's
public API, and thus it is intended for them to conflict with
user-defined types.
2023-03-22 15:45:25 +00:00
JoJoJet
daa1b0209a
Check for conflicting accesses in assert_is_system (#8154)
# Objective

The function `assert_is_system` is used in documentation tests to ensure
that example code actually produces valid systems. Currently,
`assert_is_system` just checks that each function parameter implements
`SystemParam`. To further check the validity of the system, we should
initialize the passed system so that it will be checked for conflicting
accesses. Not only does this enforce the validity of our examples, but
it provides a convenient way to demonstrate conflicting accesses via a
`should_panic` example, which is nicely rendered by rustdoc:

![should_panic
example](https://user-images.githubusercontent.com/21144246/226767682-d1c2f6b9-fc9c-4a4f-a4c4-c7f6070a115f.png)

## Solution

Initialize the system with an empty world to trigger its internal access
conflict checks.

---

## Changelog

The function `bevy::ecs::system::assert_is_system` now panics when
passed a system with conflicting world accesses, as does
`assert_is_read_only_system`.

## Migration Guide

The functions `assert_is_system` and `assert_is_read_only_system` (in
`bevy_ecs::system`) now panic if the passed system has invalid world
accesses. Any tests that called this function on a system with invalid
accesses will now fail. Either fix the system's conflicting accesses, or
specify that the test is meant to fail:

1. For regular tests (that is, functions annotated with `#[test]`), add
the `#[should_panic]` attribute to the function.
2. For documentation tests, add `should_panic` to the start of the code
block: ` ```should_panic`
2023-03-22 13:35:55 +00:00
Carter Anderson
aefe1f0739
Schedule-First: the new and improved add_systems (#8079)
Co-authored-by: Mike <mike.hsu@gmail.com>
2023-03-18 01:45:34 +00:00
Bruce Reif (Buswolley)
bca4b36d4d
change not implemation to custom system struct (#8105)
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2023-03-17 21:37:16 +00:00
Turki Jamaan
4a62afb97b
Doc and test get_many(_mut) ordering (#8045) 2023-03-16 12:55:44 +00:00
Chris Russell
a63881905a
Pass query change ticks to QueryParIter instead of always using change ticks from World. (#8029)
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: James Liu <contact@jamessliu.com>
2023-03-13 22:06:16 +00:00
JoJoJet
ed97c621b8
Move docs for !Sync resources onto the correct trait (#8066) 2023-03-13 16:16:14 +00:00
JoJoJet
fd1af7c8b8
Replace multiple calls to add_system with add_systems (#8001) 2023-03-10 18:15:22 +00:00
JoJoJet
2e7b915ba4
Increase type safety and clarity for change detection (#7905) 2023-03-09 17:17:02 +00:00
Peter Gavin
10e6122c64 make Query::par_iter accept &self (#7912)
This seems to have been a typo/mistake.
2023-03-06 00:00:38 +00:00
JoJoJet
15c55a12ff Fix a typo in CombinatorSystem (#7823)
# Objective

I made a typo in #7605.

## Solution

Fix it.
2023-02-26 02:27:41 +00:00
Cameron
be22569db7 EntityMut: rename remove_intersection to remove and remove to take (#7810)
# Objective

- A more intuitive distinction between the two. `remove_intersection` is verbose and unclear.
- `EntityMut::remove` and `Commands::remove` should match.


## Solution

- What the title says.

---

## Migration Guide

Before
```rust
fn clear_children(parent: Entity, world: &mut World) {
    if let Some(children) = world.entity_mut(parent).remove::<Children>() {
        for &child in &children.0 {
            world.entity_mut(child).remove_intersection::<Parent>();
        }
    }
}
```

After
```rust
fn clear_children(parent: Entity, world: &mut World) {
    if let Some(children) = world.entity_mut(parent).take::<Children>() {
        for &child in &children.0 {
            world.entity_mut(child).remove::<Parent>();
        }
    }
}
```
2023-02-26 00:09:19 +00:00
JoJoJet
695d30bd54 Clean up marker generics for systems (#7789)
# Objective

While we use `#[doc(hidden)]` to try and hide marker generics from the user, these types reveal themselves in compiler errors, adding visual noise and confusion.

## Solution

Replace the `AlreadyWasSystem` marker generic with `()`, to reduce visual noise in error messages. This also makes it possible to return `impl Condition<()>` from combinators.

For function systems, use their function signature as the marker type. This should drastically improve the legibility of some error messages.  
The `InputMarker` type has been removed, since it is unnecessary.
2023-02-23 05:11:12 +00:00
JoJoJet
ee4c8c5ecd Use consistent names for marker generics (#7788)
# Objective

Several places in the ECS use marker generics to avoid overlapping trait implementations, but different places alternately refer to it as `Params` and `Marker`. This is potentially confusing, since it might not be clear that the same pattern is being used. Additionally, users might be misled into thinking that the `Params` type corresponds to the `SystemParam`s of a system.

## Solution

Rename `Params` to `Marker`.
2023-02-23 04:37:08 +00:00
JoJoJet
0c98f9a225 Add AND/OR combinators for run conditions (#7605)
# Objective

Fix #7584.

## Solution

Add an abstraction for creating custom system combinators with minimal boilerplate. Use this to implement AND/OR combinators. Use this to simplify the implementation of `PipeSystem`.

## Example

Feel free to bikeshed on the syntax.

I chose the names `and_then`/`or_else` to emphasize the fact that these short-circuit, while I chose method syntax to empasize that the arguments are *not* treated equally.

```rust
app.add_systems((
    my_system.run_if(resource_exists::<R>().and_then(resource_equals(R(0)))),
    our_system.run_if(resource_exists::<R>().or_else(resource_exists::<S>())),
));
```

---

## Todo

- [ ] Decide on a syntax
- [x] Write docs
- [x] Write tests

## Changelog

+ Added the extension methods `.and_then(...)` and `.or_else(...)` to run conditions, which allows combining run conditions with short-circuiting behavior.
+ Added the trait `Combine`, which can be used with the new `CombinatorSystem` to create system combinators with custom behavior.
2023-02-20 18:16:11 +00:00
dis-da-moe
8853bef6df implement TypeUuid for primitives and fix multiple-parameter generics having the same TypeUuid (#6633)
# Objective

- Fixes #5432 
- Fixes #6680

## Solution

- move code responsible for generating the `impl TypeUuid` from `type_uuid_derive` into a new function, `gen_impl_type_uuid`.
- this allows the new proc macro, `impl_type_uuid`, to call the code for generation.
- added struct `TypeUuidDef` and implemented `syn::Parse` to allow parsing of the input for the new macro.
- finally, used the new macro `impl_type_uuid` to implement `TypeUuid` for the standard library (in `crates/bevy_reflect/src/type_uuid_impl.rs`).
- fixes #6680 by doing a wrapping add of the param's index to its `TYPE_UUID`

Co-authored-by: dis-da-moe <84386186+dis-da-moe@users.noreply.github.com>
2023-02-16 17:09:44 +00:00
JoJoJet
4f57f380c7 Simplify generics for the SystemParamFunction trait (#7675)
# Objective

The `SystemParamFunction` (and `ExclusiveSystemParamFunction`) trait is very cumbersome to use, due to it requiring four generic type parameters. These are currently all used as marker parameters to satisfy rust's trait coherence rules.

### Example (before)

```rust
pub fn pipe<AIn, Shared, BOut, A, AParam, AMarker, B, BParam, BMarker>(
    mut system_a: A,
    mut system_b: B,
) -> impl FnMut(In<AIn>, ParamSet<(AParam, BParam)>) -> BOut
where
    A: SystemParamFunction<AIn, Shared, AParam, AMarker>,
    B: SystemParamFunction<Shared, BOut, BParam, BMarker>,
    AParam: SystemParam,
    BParam: SystemParam,
```

## Solution

Turn the `In`, `Out`, and `Param` generics into associated types. Merge the marker types together to retain coherence.

### Example (after)

```rust
pub fn pipe<A, B, AMarker, BMarker>(
    mut system_a: A,
    mut system_b: B,
) -> impl FnMut(In<A::In>, ParamSet<(A::Param, B::Param)>) -> B::Out
where
    A: SystemParamFunction<AMarker>,
    B: SystemParamFunction<BMarker, In = A::Out>,
```

---

## Changelog

+ Simplified the `SystemParamFunction` and `ExclusiveSystemParamFunction` traits.

## Migration Guide

For users of the `SystemParamFunction` trait, the generic type parameters `In`, `Out`, and `Param` have been turned into associated types. The same has been done with the `ExclusiveSystemParamFunction` trait.
2023-02-15 19:41:15 +00:00
JoJoJet
5efc226290 Allow piping run conditions (#7547)
# Objective

Run conditions are a special type of system that do not modify the world, and which return a bool. Due to the way they are currently implemented, you can *only* use bare function systems as a run condition. Among other things, this prevents the use of system piping with run conditions. This make very basic constructs impossible, such as `my_system.run_if(my_condition.pipe(not))`.

Unblocks a basic solution for #7202.

## Solution

Add the trait `ReadOnlySystem`, which is implemented for any system whose parameters all implement `ReadOnlySystemParam`. Allow any `-> bool` system implementing this trait to be used as a run condition.

---

## Changelog

+ Added the trait `ReadOnlySystem`, which is implemented for any `System` type whose parameters all implement `ReadOnlySystemParam`.
+ Added the function `bevy::ecs::system::assert_is_read_only_system`.
2023-02-07 22:22:16 +00:00
JoJoJet
d26b63a04d Add a SystemParam primitive for deferred mutations; allow #[derive]ing more types of SystemParam (#6817)
# Objective

One pattern to increase parallelism is deferred mutation: instead of directly mutating the world (and preventing other systems from running at the same time), you queue up operations to be applied to the world at the end of the stage. The most common example of this pattern uses the `Commands` SystemParam.

In order to avoid the overhead associated with commands, some power users may want to add their own deferred mutation behavior. To do this, you must implement the unsafe trait `SystemParam`, which interfaces with engine internals in a way that we'd like users to be able to avoid.

## Solution

Add the `Deferred<T>` primitive `SystemParam`, which encapsulates the deferred mutation pattern.
This can be combined with other types of `SystemParam` to safely and ergonomically create powerful custom types.

Essentially, this is just a variant of `Local<T>` which can run code at the end of the stage.

This type is used in the engine to derive `Commands` and `ParallelCommands`, which removes a bunch of unsafe boilerplate.

### Example

```rust
use bevy_ecs::system::{Deferred, SystemBuffer};

/// Sends events with a delay, but may run in parallel with other event writers.
#[derive(SystemParam)]
pub struct BufferedEventWriter<'s, E: Event> {
    queue: Deferred<'s, EventQueue<E>>,
}

struct EventQueue<E>(Vec<E>);

impl<'s, E: Event> BufferedEventWriter<'s, E> {
    /// Queues up an event to be sent at the end of this stage.
    pub fn send(&mut self, event: E) {
        self.queue.0.push(event);
    }
}

// The `SystemBuffer` trait controls how [`Deferred`] gets applied at the end of the stage.
impl<E: Event> SystemBuffer for EventQueue<E> {
    fn apply(&mut self, world: &mut World) {
        let mut events = world.resource_mut::<Events<E>>();
        for e in self.0.drain(..) {
            events.send(e);
        }
    }
}
```

---

## Changelog

+ Added the `SystemParam` type `Deferred<T>`, which can be used to defer `World` mutations. Powered by the new trait `SystemBuffer`.
2023-02-06 21:57:57 +00:00