Commit graph

812 commits

Author SHA1 Message Date
JoJoJet
b8263b55fb Support system.in_schedule() and system.on_startup() (#7790)
# Objective

Support the following syntax for adding systems:

```rust
App::new()
    .add_system(setup.on_startup())
    .add_systems((
        show_menu.in_schedule(OnEnter(GameState::Paused)),
        menu_ssytem.in_set(OnUpdate(GameState::Paused)),
        hide_menu.in_schedule(OnExit(GameState::Paused)),
    ))
```

## Solution

Add the traits `IntoSystemAppConfig{s}`, which provide the extension methods necessary for configuring which schedule a system belongs to. These extension methods return `IntoSystemAppConfig{s}`, which `App::add_system{s}` uses to choose which schedule to add systems to.

---

## Changelog

+ Added the extension methods `in_schedule(label)` and  `on_startup()` for configuring the schedule a system belongs to.

## Future Work

* Replace all uses of `add_startup_system` in the engine.
* Deprecate this method
2023-02-24 18:33:55 +00:00
JoJoJet
e27e04a4a7 Remove a duplicate lookup in apply_state_transitions (#7800)
# Objective

Remove a duplicate resource lookup and an unnecessary panic.
2023-02-24 10:49:14 +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
remiCzn
a0606393d7 Add example in Schedule docs (#7775)
# Objective

Fixes #3980

## Solution

Added examples to show how to run a `Schedule`, one with a unique system, and another with several systems

---

## Changelog

- Added: examples in docs to show how to run a `Schedule`


Co-authored-by: remiCzn <77072160+remiCzn@users.noreply.github.com>
2023-02-22 15:52:37 +00:00
JoJoJet
588af17aa3 Make boxed conditions read-only (#7786)
# Objective

The `BoxedCondition` type alias does not require the underlying system to be read-only.

## Solution

Define the type alias using `ReadOnlySystem` instead of `System`.
2023-02-22 15:25:40 +00:00
Cameron
3ec87e49ca Stageless: prettier cycle reporting (#7463)
Graph theory make head hurty. Closes #7367.

Basically, when we topologically sort the dependency graph, we already find its strongly-connected components (a really [neat algorithm][1]). This PR adds an algorithm that can dissect those into simple cycles, giving us more useful error reports.

test: `system_build_errors::dependency_cycle`
```
schedule has 1 before/after cycle(s):
cycle 1: system set 'A' must run before itself
system set 'A'
 ... which must run before system set 'B'
 ... which must run before system set 'A'
```
```
schedule has 1 before/after cycle(s):
cycle 1: system 'foo' must run before itself
system 'foo'
 ... which must run before system 'bar'
 ... which must run before system 'foo'
```

test: `system_build_errors::hierarchy_cycle`
```
schedule has 1 in_set cycle(s):
cycle 1: system set 'A' contains itself
system set 'A'
 ... which contains system set 'B'
 ... which contains system set 'A'
 ```

[1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
2023-02-21 13:42:20 +00:00
Rob Parrett
da8bf66cf8 Remove unnecessary clippy allows (#7768)
# Objective

I think that these allows are no longer necessary after #6534.

## Solution

Let's remove them and see if clippy complains.
2023-02-20 23:59:03 +00:00
Rob Parrett
03c545056c Fix some more typos (#7767)
# Objective

I managed to dig up some more typos with a combination of the "[code spell checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)" and "[open folder](https://marketplace.visualstudio.com/items?itemName=rwu823.open-folder)" vscode extensions.

## Solution

Fix em
2023-02-20 23:36:28 +00:00
Rob Parrett
b39f83640f Fix some typos (#7763)
# Objective

Stumbled on a typo and went on a typo hunt.

## Solution

Fix em
2023-02-20 22:56:57 +00:00
Ida "Iyes
17d1fa4a8b Add more "common run conditions" (#7579)
Add some more useful common run conditions.

Some of these existed in `iyes_loopless`. I know people used them, and it would be a regression for those users, when they try to migrate to new Bevy stageless, if they are missing.

I also took the opportunity to add a few more new ones.

---

## Changelog

### Added
 - More "common run conditions": on_event, resource change detection, state_changed, any_with_component
2023-02-20 22:56:56 +00:00
James Liu
4e15d3d8bb Don't log a trace if EventWriter::send_batch is empty (#7753)
# Objective
Fix #5026.

## Solution
Only make a `trace!` log if the event count changed.

---

## Changelog
Changed: `EventWriter::send_batch` will only log a TRACE level log if the batch is non-empty.
2023-02-20 21:51:21 +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
Edgar Geier
acff2210c0 Add report_sets option to ScheduleBuildSettings (#7756)
# Objective

- Fixes #7442.

## Solution

- Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue.

The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: 
```
82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these:
 -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush)
    conflict on: bevy_ecs::world::World
 -- scene_spawner_system (Update) and close_when_requested (Update)
    conflict on: bevy_ecs::world::World
 -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta)
    conflict on: bevy_ecs::world::World
 -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate)
    conflict on: ["bevy_transform::components::transform::Transform"]
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate)
    conflict on: bevy_ecs::world::World
 -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta)
    conflict on: bevy_ecs::world::World
 -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
 -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush)
    conflict on: bevy_ecs::world::World
```

Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
JoJoJet
a69e6a1207 Implement FromWorld for WorldId (#7726)
# Objective

Allow using `Local<WorldId>` in systems.

## Solution

- Describe the solution used to achieve the objective above.

---

## Changelog

+ `WorldId` now implements the `FromWorld` trait.
2023-02-20 15:02:16 +00:00
shuo
d46427b4e4 for disconnected, use Vec instead of HashSet to reduce insert overhead (#7744)
# Objective

- Improve `Schedule::initialize` performance

## Solution

- replace `disconnected`'s type from HashSet to Vec in `check_graph`
2023-02-19 16:35:39 +00:00
shuo
bd54c4d2d1 extract topsort logic to a new method, one pass to detect cycles and … (#7727)
…top sort. reduce mem alloc

# Objective

- Reduce alloc count.
- Improve code quality.

## Solution

- use `TarjanScc::run` directly, which calls a closure with each scc, in closure, we can detect cycles and flatten nodes
2023-02-19 16:35:38 +00:00
JoJoJet
5a5125671b Deprecate ChangeTrackers<T> in favor of Ref<T> (#7306)
# Objective

`ChangeTrackers<>` is a `WorldQuery` type that lets you access the change ticks for a component. #7097 has added `Ref<>`, which gives access to a component's value in addition to its change ticks. Since bevy's access model does not separate a component's value from its change ticks, there is no benefit to using `ChangeTrackers<T>` over `Ref<T>`.

## Solution

Deprecate `ChangeTrackers<>`.

---

## Changelog

* `ChangeTrackers<T>` has been deprecated. It will be removed in Bevy 0.11.

## Migration Guide

`ChangeTrackers<T>` has been deprecated, and will be removed in the next release. Any usage should be replaced with `Ref<T>`.

```rust
// Before (0.9)
fn my_system(q: Query<(&MyComponent, ChangeTrackers<MyComponent>)>) {
    for (value, trackers) in &q {
        if trackers.is_changed() {
            // Do something with `value`.
        }
    }
}

// After (0.10)
fn my_system(q: Query<Ref<MyComponent>>) {
    for value in &q {
        if value.is_changed() {
            // Do something with `value`.
        }
    }
}
```
2023-02-19 16:19:56 +00:00
Liam Gallagher
64b0f19a65 Implement SystemParam for WorldId (#7741)
# Objective

Fixes #7736

## Solution

Implement the `SystemParam` trait for `WorldId`

## Changelog

- `WorldId` can now be taken as a system parameter and will return the id of the world the system is running in
2023-02-19 03:26:13 +00:00
Edgar Geier
67a89e9c58 Add distributive_run_if to IntoSystemConfigs (#7724)
# Objective

- Fixes #7659.

## Solution

- This PR extracted the `distributive_run_if` part of #7676, because it does not require the controversial introduction of anonymous system sets.
- The distinctive name should make the user aware about the differences between `IntoSystemConfig::run_if` and `IntoSystemConfigs::distributive_run_if`.
- The documentation explains in detail the consequences of using the API and possible pit falls when using it.
- A test demonstrates the possibility of changing the condition result, resulting in some of the systems not being run.

---

## Changelog

### Added
- Add `distributive_run_if` to `IntoSystemConfigs` to enable adding a run condition to each system when using `add_systems`.
2023-02-18 21:33:09 +00:00
shuo
609ad5aaa6 introduce EntityLocation::INVALID const and adjust Entities::get comment (#7623)
also remove one un-needed mut.
2023-02-18 21:15:57 +00:00
Jakob Hellermann
b2e1694c12 make ScheduleGraph::initialize public (#7723)
follow-up to https://github.com/bevyengine/bevy/pull/7716

# Objective

System access is only populated in `System::initialize`, so without calling `initialize` it's actually impossible to see most ambiguities.

## Solution


- make `initialize` public. The method is idempotent, so calling it multiple times doesn't hurt
2023-02-17 20:25:28 +00:00
Aceeri
b24ed8bb0c IntoIterator for EventReader (#7720)
# Objective
Continuation of https://github.com/bevyengine/bevy/pull/5719
Now that we have a definable type for the iterator.

---

## Changelog
- Implemented IntoIterator for EventReader so you can now do `&mut reader` instead of `reader.iter()` for events.
2023-02-17 15:37:36 +00:00
James Liu
04256735f6 Cleanup ScheduleBuildSettings (#7721)
# Objective
Fix #7440. Fix #7441. 

## Solution

 * Remove builder functions on `ScheduleBuildSettings` in favor of public fields, move docs to the fields.
 * Add `use_shortnames` and use it in `get_node_name` to feed it through `bevy_utils::get_short_name`.
2023-02-17 15:17:52 +00:00
James Liu
69d3a15eae Default to using ExecutorKind::SingleThreaded on wasm32 (#7717)
# Objective
Web builds do not support running on multiple threads right now. Defaulting to the multi-threaded executor has significant overhead without any benefit.

## Solution
Default to the single threaded executor on wasm32 builds.
2023-02-17 00:22:56 +00:00
Jakob Hellermann
45442f7367 expose ambiguities of ScheduleGraph (#7716)
# Objective

- other tools (bevy_mod_debugdump) would like to have access to the ambiguities so that they can do their own reporting/visualization

## Solution

- store `conflicting_systems` in `ScheduleGraph` after calling `build_schedule`

The solution isn't very pretty and as pointed out it https://github.com/bevyengine/bevy/pull/7522, there may be a better way of exposing this, but this is the quick and dirty way if we want to have this functionality exposed in 0.10.
2023-02-17 00:22:55 +00:00
Aceeri
c5702b9b5d Make RemovedComponents mirror EventReaders api surface (#7713)
# Objective
- RemovedComponents is just a thin wrapper around Events/ManualEventReader which is the same as an EventReader, so most usecases that of an EventReader will probably be useful for RemovedComponents too.

I was thinking of making a trait for this but I don't think it is worth the overhead currently.

## Solution
- Mirror the api surface of EventReader
2023-02-17 00:01:13 +00:00
JoJoJet
a95033b288 Optimize .nth() and .last() for event iterators (#7530)
# Objective

Motivated by #7469.

`EventReader` iterators use the default implementations for `.nth()` and `.last()`, which includes iterating over and throwing out all events before the desired one.

## Solution

Add specialized implementations for these methods that directly updates the unread event counter and returns a reference to the desired event.

TODO:

- [x] Add a unit test.
- [x] ~~Add a benchmark, to see if the compiler was doing this automatically already.~~ *On second thought, this doesn't feel like a very useful thing to include in the benchmark suite.*
2023-02-16 23:34:18 +00:00
Jakob Hellermann
b1646e9cee change is_system_type() -> bool to system_type() -> Option<TypeId> (#7715)
# Objective

- it would be nice to be able to associate a `NodeId` of a system type set to the `NodeId` of the actual system (used in bevy_mod_debugdump)

## Solution

- make `system_type` return the type id of the system
  - that way you can check if a `dyn SystemSet` is the system type set of a `dyn System`
- I don't know if this information is already present somewhere else in the scheduler or if there is a better way to expose it
2023-02-16 22:25:48 +00:00
Edgar Geier
6a63940367 Allow adding systems to multiple sets that share the same base set (#7709)
# Objective

Fixes #7702.

## Solution

- Added an test that ensures that no error is returned if a system or set is inside two different sets that share the same base set.
- Added an check to only return an error if the two base sets are not equal.
2023-02-16 17:09:46 +00:00
Jakob Hellermann
b35818c0a3 expose ScheduleGraph for third party dependencies (#7522)
# Objective

The `ScheduleGraph` should be expose so that crates like [bevy_mod_debugdump](https://github.com/jakobhellermann/bevy_mod_debugdump/blob/stageless/docs/README.md) can access useful information. 

## Solution

- expose `ScheduleGraph`, `NodeId`, `BaseSetMembership`, `Dag`
- add accessor functions for sets and systems

## Changelog

- expose `ScheduleGraph` for use in third party tools

This does expose our use of `petgraph` as a graph library, so we can only change that as a breaking change.
2023-02-16 17:09:45 +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
81307290e2 Fix trait bounds for run conditions (#7688)
# Objective

The trait `Condition<>` is implemented for any type that can be converted into a `ReadOnlySystem` which takes no inputs and returns a bool. However, due to the current implementation, consumers of the trait cannot rely on the fact that `<T as Condition>::System` implements `ReadOnlySystem`. In cases such as the `not` combinator (added in #7559), we are required to add redundant `T::System: ReadOnlySystem` trait bounds, even though this should be implied by the `Condition<>` trait.

## Solution

Add a hidden associated type which allows the compiler to figure out that the `System` associated type implements `ReadOnlySystem`.
2023-02-16 16:45:48 +00:00
shuo
1dc713b605 add len, is_empty, iter method on SparseSets, make SparseSets inspect… (#7638)
…able like Table. Rename clear to clear_entities to clarify that metadata keeps, only value cleared

# Objective

- Provide some inspectability for SparseSets. 

## Solution

- `Tables` has these three methods, len, is_empty and iter too. Add these methods to `SparseSets`, so user can print the shape of storage.

---

## Changelog

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

- Add `len`, `is_empty`, `iter` methods on SparseSets.
- Rename `clear` to `clear_entities` to clarify its purpose.
- Add `new_for_test` on `ComponentInfo` to make test code easy.
- Add test case covering new methods.

## Migration Guide

> This section is optional. If there are no breaking changes, you can delete this section.

- Simply adding new functionality is not a breaking change.
2023-02-15 23:52:02 +00:00
Саня Череп
e392e99f7e feat: improve initialize_bundle error message (#7464)
# Objective

This PR improves message that caused by duplicate components in bundle.

## Solution

Show names of duplicate components.

The solution is not very elegant, in my opinion, I will be happy to listen to suggestions for improving it

Co-authored-by: Саня Череп <41489405+SDesya74@users.noreply.github.com>
2023-02-15 22:56:22 +00:00
JoJoJet
670c4c1852 Use a default implementation for set_if_neq (#7660)
# Objective

While porting my crate `bevy_trait_query` to bevy 0.10, I ran into an issue with the `DetectChangesMut` trait. Due to the way that the `set_if_neq` method (added in #6853) is implemented, you are forced to write a nonsense implementation of it for dynamically sized types. This edge case shows up when implementing trait queries, since `DetectChangesMut` is implemented for `Mut<dyn Trait>`.

## Solution

Simplify the generics for `set_if_neq` and add the `where Self::Target: Sized` trait bound to it. Add a default implementation so implementers don't need to implement a method with nonsensical trait bounds.
2023-02-15 20:10:23 +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
Giacomo Stevanato
8d51f4a2a5 Remove useless access to archetype in UnsafeWorldCell::fetch_table (#7665)
# Objective

- #6402 changed `World::fetch_table` (now `UnsafeWorldCell::fetch_table`) to access the archetype in order to get the `table_id` and `table_row` of the entity involved. However this is useless since those were already present in the `EntityLocation`
- Moreover it's useless for `UnsafeWorldCell::fetch_table` to return the `TableRow` too, since the caller must already have access to the `EntityLocation` which contains the `TableRow`.
- The result is that `UnsafeWorldCell::fetch_table` now only does 2 memory fetches instead of 4.

## Solution

- Revert the changes to the implementation of `UnsafeWorldCell::fetch_table` made in #6402
2023-02-15 04:39:18 +00:00
shuo
11a7ff2645 use bevy_utils::HashMap for better performance. TypeId is predefined … (#7642)
…u64, so hash safety is not a concern

# Objective

- While reading the code, just noticed the BundleInfo's HashMap is std::collections::HashMap, which uses a slow but safe hasher.

## Solution

- Use bevy_utils::HashMap instead

benchmark diff (I run several times in a linux box, the perf improvement is consistent, though numbers varies from time to time, I paste my last run result here):

``` bash
cargo bench -- spawn
   Compiling bevy_ecs v0.9.0 (/home/lishuo/developer/pr/bevy/crates/bevy_ecs)
   Compiling bevy_app v0.9.0 (/home/lishuo/developer/pr/bevy/crates/bevy_app)
   Compiling benches v0.1.0 (/home/lishuo/developer/pr/bevy/benches)
    Finished bench [optimized] target(s) in 1m 17s
     Running benches/bevy_ecs/change_detection.rs (/home/lishuo/developer/pr/bevy/benches/target/release/deps/change_detection-86c5445d0dc34529)
Gnuplot not found, using plotters backend
     Running benches/bevy_ecs/benches.rs (/home/lishuo/developer/pr/bevy/benches/target/release/deps/ecs-e49b3abe80bfd8c0)
Gnuplot not found, using plotters backend
spawn_commands/2000_entities
                        time:   [153.94 µs 159.19 µs 164.37 µs]
                        change: [-14.706% -11.050% -6.9633%] (p = 0.00 < 0.05)
                        Performance has improved.
spawn_commands/4000_entities
                        time:   [328.77 µs 339.11 µs 349.11 µs]
                        change: [-7.6331% -3.9932% +0.0487%] (p = 0.06 > 0.05)
                        No change in performance detected.
spawn_commands/6000_entities
                        time:   [445.01 µs 461.29 µs 477.36 µs]
                        change: [-16.639% -13.358% -10.006%] (p = 0.00 < 0.05)
                        Performance has improved.
spawn_commands/8000_entities
                        time:   [657.94 µs 677.71 µs 696.95 µs]
                        change: [-8.8708% -5.2591% -1.6847%] (p = 0.01 < 0.05)
                        Performance has improved.

get_or_spawn/individual time:   [452.02 µs 466.70 µs 482.07 µs]
                        change: [-17.218% -14.041% -10.728%] (p = 0.00 < 0.05)
                        Performance has improved.
get_or_spawn/batched    time:   [291.12 µs 301.12 µs 311.31 µs]
                        change: [-12.281% -8.9163% -5.3660%] (p = 0.00 < 0.05)
                        Performance has improved.

spawn_world/1_entities  time:   [81.668 ns 84.284 ns 86.860 ns]
                        change: [-12.251% -6.7872% -1.5402%] (p = 0.02 < 0.05)
                        Performance has improved.
spawn_world/10_entities time:   [789.78 ns 821.96 ns 851.95 ns]
                        change: [-19.738% -14.186% -8.0733%] (p = 0.00 < 0.05)
                        Performance has improved.
spawn_world/100_entities
                        time:   [7.9906 µs 8.2449 µs 8.5013 µs]
                        change: [-12.417% -6.6837% -0.8766%] (p = 0.02 < 0.05)
                        Change within noise threshold.
spawn_world/1000_entities
                        time:   [81.602 µs 84.161 µs 86.833 µs]
                        change: [-13.656% -8.6520% -3.0491%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
Benchmarking spawn_world/10000_entities: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.0s, enable flat sampling, or reduce sample count to 70.
spawn_world/10000_entities
                        time:   [813.02 µs 839.76 µs 865.41 µs]
                        change: [-12.133% -6.1970% -0.2302%] (p = 0.05 < 0.05)
                        Change within noise threshold.
```

---

## Changelog

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

- use bevy_utils::HashMap for Bundles::bundle_ids

## Migration Guide

> This section is optional. If there are no breaking changes, you can delete this section.

- Not a breaking change, hashmap is internal impl.
2023-02-15 04:19:26 +00:00
Niklas Eicker
0bce78439b Cleanup system sets called labels (#7678)
# Objective

We have a few old system labels that are now system sets but are still named or documented as labels. Documentation also generally mentioned system labels in some places.


## Solution

- Clean up naming and documentation regarding system sets

## Migration Guide

`PrepareAssetLabel` is now called `PrepareAssetSet`
2023-02-14 21:46:07 +00:00
Niklas Eicker
f1c0850b81 Rename state_equals condition to in_state (#7677)
# Objective

- Improve readability of the run condition for systems only running in a certain state

## Solution

- Rename `state_equals` to `in_state` (see [comment by cart](https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428740311) in #7634 )
- `.run_if(state_equals(variant))` now is `.run_if(in_state(variant))`

This breaks the naming pattern a bit with the related conditions `state_exists` and `state_exists_and_equals` but I could not think of better names for those and think the improved readability of `in_state` is worth it.
2023-02-14 21:30:14 +00:00
Alice Cecile
0a9c469d19 Remove .on_update method to improve API consistency and clarity (#7667)
# Objective

Fixes #7632.

As discussed in #7634, it can be quite challenging for users to intuit the mental model of how states now work.

## Solution

Rather than change the behavior of the `OnUpdate` system set, instead work on making sure it's easy to understand what's going on.

Two things have been done:

1. Remove the `.on_update` method from our bevy of system building traits. This was special-cased and made states feel much more magical than they need to.
2. Improve the docs for the `OnUpdate` system set.
2023-02-14 00:13:10 +00:00
Kurt Kühnert
68c94c0732 Document usage of SRes::into_inner on the RenderCommand trait (#7224)
# Objective

- Fixes: #7187

Since avoiding the `SRes::into_inner` call does not seem to be possible, this PR tries to at least document its usage.
I am not sure if I explained the lifetime issue correctly, please let me know if something is incorrect.

## Solution

- Add information about the `SRes::into_inner` usage on both `RenderCommand` and `Res`
2023-02-13 18:44:26 +00:00
张林伟
14a7689e1a Derive Debug for State and NextState (#7651)
# Objective

- Derive Debug for State and NextState
2023-02-13 18:20:31 +00:00
JoJoJet
10d0336287 Optimize Iterator::count for event iterators (#7582)
# Objective

Related to #7530.

`EventReader` iterators currently use the default impl for `.count()`, which unnecessarily loops over all unread events.

# Solution

Add specialized impls that mark the `EventReader` as consumed and return the number of unread events.
2023-02-13 18:20:21 +00:00
JoJoJet
a1e4114ebe Rename UnsafeWorldCellEntityRef to UnsafeEntityCell (#7568)
# Objective

Make the name less verbose without sacrificing clarity.

---

## Migration Guide

*Note for maintainers:* This PR has no breaking changes relative to bevy 0.9. Instead of this PR having its own migration guide, we should just edit the changelog for #6404.

The type `UnsafeWorldCellEntityRef` has been renamed to `UnsafeEntityCell`.
2023-02-11 18:50:41 +00:00
JoJoJet
7eb7896cf5 Fix last_changed() and set_last_changed() for MutUntyped (#7619)
# Objective

Continuation of #7560.

`MutUntyped::last_changed` and `set_last_changed` do not behave as described in their docs.

## Solution

Fix them using the same approach that was used for `Mut<>` in #7560.
2023-02-11 18:33:57 +00:00
Chris Juchem
fefe5297ad Fix DetectChanges::last_changed returning the wrong tick (#7560)
# Objective

Make `last_changed` behave as described in its docs.

## Solution

- Return `changed` instead of `last_change_tick`. `last_change_tick` is the system's previous tick and is just used for comparison.
- Update the docs of the similarly named `set_last_changed` (which does correctly interact with `last_change_tick`) to clarify that the two functions touch different data. (I advocate for renaming one or the other if anyone has any good suggestions).

It also might make sense to return a cloned `Tick` instead of `u32`.

---

## Changelog

- Fixed `DetectChanges::last_changed` returning the wrong value.
- Fixed `DetectChangesMut::set_last_changed` not actually updating the `changed` tick. 

## Migration Guide

- The incorrect value that was being returned by `DetectChanges::last_changed` was the previous run tick of the system checking for changed values. If you depended on this value, you can get it from the `SystemChangeTick` `SystemParam` instead.
2023-02-09 17:07:15 +00:00
Chris Juchem
1ca8755cc5 Rename Tick::is_older_than to Tick::is_newer_than (#7561)
# Objective

Clarify what the function is actually calculating.

The `Tick::is_older_than` function is actually calculating whether the tick is newer than the system's `last_change_tick`, not older. As far as I can tell, the engine was using it correctly everywhere already. 

## Solution

- Rename the function.
---

## Changelog

- `Tick::is_older_than` was renamed to `Tick::is_newer_than`. This is not a functional change, since that was what was always being calculated, despite the wrong name.

## Migration Guide

- Replace usages of `Tick::is_older_than` with `Tick::is_newer_than`.
2023-02-09 16:21:22 +00:00
Hennadii Chernyshchyk
1ffeff19f9 Add condition negation (#7559)
# Objective

Closes #7202

## Solution

~~Introduce a `not` helper to pipe conditions. Opened mostly for discussion. Maybe create an extension trait with `not` method? Please, advice.~~
Introduce `not(condition)` condition that inverses the result of the passed.

---

## Changelog

### Added

- `not` condition.
2023-02-08 23:24:36 +00:00