# 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>
# Objective
`ScheduleGraph` currently stores run conditions in a
`Option<Vec<BoxedCondition>>`. The `Option` is unnecessary, since we can
just use an empty vector instead of `None`.
# Objective
- Fixes#7659
## Solution
The idea of anonymous system sets or "implicit hidden organizational
sets" was briefly mentioned by @cart here:
https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449.
- `Schedule::add_systems` creates an implicit, anonymous system set of
all systems in `SystemConfigs`.
- All dependencies and conditions from the `SystemConfigs` are now
applied to the implicit system set, instead of being applied to each
individual system. This should not change the behavior, AFAIU, because
`before`, `after`, `run_if` and `ambiguous_with` are transitive
properties from a set to its members.
- The newly added `AnonymousSystemSet` stores the names of its members
to provide better error messages.
- The names are stored in a reference counted slice, allowing fast
clones of the `AnonymousSystemSet`.
- However, only the pointer of the slice is used for hash and equality
operations
- This ensures that two `AnonymousSystemSet` are not equal, even if they
have the same members / member names.
- So two identical `add_systems` calls will produce two different
`AnonymousSystemSet`s.
- Clones of the same `AnonymousSystemSet` will be equal.
## Drawbacks
If my assumptions are correct, the observed behavior should stay the
same. But the number of system sets in the `Schedule` will increase with
each `add_systems` call. If this has negative performance implications,
`add_systems` could be changed to only create the implicit system set if
necessary / when a run condition was added.
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
With the removal of base sets, some variants of `ScheduleBuildError` can
never occur and should be removed.
## Solution
- Remove the obsolete variants of `ScheduleBuildError`.
- Also fix a doc comment which mentioned base sets.
---
## Changelog
### Removed
- Remove `ScheduleBuildError::SystemInMultipleBaseSets` and
`ScheduleBuildError::SetInMultipleBaseSets`.
# Objective
The `ScheduleBuildError` type has a `Display` implementation which beautifully formats the error. However, schedule build errors are currently reported using `unwrap()`, which uses the `Debug` implementation and makes the error message look unfished.
## Solution
Use `unwrap_or_else` so we can customize the formatting of the error message.
# 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`.
# 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>
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
# 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>
…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
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
# 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`.
# 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.
# 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.
# 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
# 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.
# 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.
* Add mutated tracker on resources and ChangedRes query for added or mutated resources.
* ResMut:::new() now takes a reference to a 'mutated' flag in its archetype.
* Change FetchResource so that get() returns an Option. Systems using Resources will only be called if all fetched Resources are Some(). This is done to implement ChangedRes, which is Some iff the Resource has been changed.
* Add OrRes for a logical or in tuples of Resource queries.
* Separate resource query get() in is_some() and get() methods for clarity
* Remove unneeded unsafe
* Change ResMut::new()