Generic system config (#17962)

# Objective
Prevents duplicate implementation between IntoSystemConfigs and
IntoSystemSetConfigs using a generic, adds a NodeType trait for more
config flexibility (opening the door to implement
https://github.com/bevyengine/bevy/issues/14195?).

## Solution
Followed writeup by @ItsDoot:
https://hackmd.io/@doot/rJeefFHc1x

Removes IntoSystemConfigs and IntoSystemSetConfigs, instead using
IntoNodeConfigs with generics.

## Testing
Pending

---

## Showcase
N/A

## Migration Guide
SystemSetConfigs -> NodeConfigs<InternedSystemSet>
SystemConfigs -> NodeConfigs<ScheduleSystem>
IntoSystemSetConfigs -> IntoNodeConfigs<InternedSystemSet, M>
IntoSystemConfigs -> IntoNodeConfigs<ScheduleSystem, M>

---------

Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
newclarityex 2025-03-11 20:12:30 -04:00 committed by GitHub
parent f1331069e7
commit ecccd57417
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 285 additions and 463 deletions

View File

@ -14,8 +14,8 @@ use bevy_ecs::{
event::{event_update_system, EventCursor},
intern::Interned,
prelude::*,
schedule::{ScheduleBuildSettings, ScheduleLabel},
system::{IntoObserverSystem, SystemId, SystemInput},
schedule::{InternedSystemSet, ScheduleBuildSettings, ScheduleLabel},
system::{IntoObserverSystem, ScheduleSystem, SystemId, SystemInput},
};
use bevy_platform_support::collections::HashMap;
use core::{fmt::Debug, num::NonZero, panic::AssertUnwindSafe};
@ -302,7 +302,7 @@ impl App {
pub fn add_systems<M>(
&mut self,
schedule: impl ScheduleLabel,
systems: impl IntoSystemConfigs<M>,
systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
) -> &mut Self {
self.main_mut().add_systems(schedule, systems);
self
@ -330,10 +330,10 @@ impl App {
/// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.
#[track_caller]
pub fn configure_sets(
pub fn configure_sets<M>(
&mut self,
schedule: impl ScheduleLabel,
sets: impl IntoSystemSetConfigs,
sets: impl IntoScheduleConfigs<InternedSystemSet, M>,
) -> &mut Self {
self.main_mut().configure_sets(schedule, sets);
self
@ -1446,7 +1446,7 @@ mod tests {
query::With,
removal_detection::RemovedComponents,
resource::Resource,
schedule::{IntoSystemConfigs, ScheduleLabel},
schedule::{IntoScheduleConfigs, ScheduleLabel},
system::{Commands, Query},
world::{FromWorld, World},
};

View File

@ -3,7 +3,7 @@ use alloc::{vec, vec::Vec};
use bevy_ecs::{
resource::Resource,
schedule::{
ExecutorKind, InternedScheduleLabel, IntoSystemSetConfigs, Schedule, ScheduleLabel,
ExecutorKind, InternedScheduleLabel, IntoScheduleConfigs, Schedule, ScheduleLabel,
SystemSet,
},
system::Local,
@ -316,7 +316,7 @@ impl Plugin for MainSchedulePlugin {
#[cfg(feature = "bevy_debug_stepping")]
{
use bevy_ecs::schedule::{IntoSystemConfigs, Stepping};
use bevy_ecs::schedule::{IntoScheduleConfigs, Stepping};
app.add_systems(Main, Stepping::begin_frame.before(Main::run_main));
}
}

View File

@ -4,8 +4,8 @@ use bevy_ecs::{
error::{DefaultSystemErrorHandler, SystemErrorContext},
event::EventRegistry,
prelude::*,
schedule::{InternedScheduleLabel, ScheduleBuildSettings, ScheduleLabel},
system::{SystemId, SystemInput},
schedule::{InternedScheduleLabel, InternedSystemSet, ScheduleBuildSettings, ScheduleLabel},
system::{ScheduleSystem, SystemId, SystemInput},
};
use bevy_platform_support::collections::{HashMap, HashSet};
use core::fmt::Debug;
@ -212,7 +212,7 @@ impl SubApp {
pub fn add_systems<M>(
&mut self,
schedule: impl ScheduleLabel,
systems: impl IntoSystemConfigs<M>,
systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
) -> &mut Self {
let mut schedules = self.world.resource_mut::<Schedules>();
schedules.add_systems(schedule, systems);
@ -234,10 +234,10 @@ impl SubApp {
/// See [`App::configure_sets`].
#[track_caller]
pub fn configure_sets(
pub fn configure_sets<M>(
&mut self,
schedule: impl ScheduleLabel,
sets: impl IntoSystemSetConfigs,
sets: impl IntoScheduleConfigs<InternedSystemSet, M>,
) -> &mut Self {
let mut schedules = self.world.resource_mut::<Schedules>();
schedules.configure_sets(schedule, sets);

View File

@ -290,7 +290,7 @@ mod tests {
use crate::{AssetApp, Assets};
use bevy_app::{App, AppExit, PostUpdate, Startup, TaskPoolPlugin, Update};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
use bevy_ecs::{
component::Component,
event::EventWriter,

View File

@ -220,7 +220,7 @@ use bevy_app::{App, Plugin, PostUpdate, PreUpdate};
use bevy_ecs::prelude::Component;
use bevy_ecs::{
reflect::AppTypeRegistry,
schedule::{IntoSystemConfigs, IntoSystemSetConfigs, SystemSet},
schedule::{IntoScheduleConfigs, SystemSet},
world::FromWorld,
};
use bevy_platform_support::collections::HashSet;

View File

@ -23,7 +23,7 @@ use bevy_ecs::{
query::{QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -16,7 +16,7 @@ use bevy_ecs::{
prelude::{resource_exists, Without},
query::{Or, QueryState, With},
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Local, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -9,7 +9,7 @@ use crate::{
use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle};
use bevy_ecs::{
component::Component, query::With, reflect::ReflectComponent, schedule::IntoSystemConfigs,
component::Component, query::With, reflect::ReflectComponent, schedule::IntoScheduleConfigs,
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{

View File

@ -11,7 +11,7 @@ use bevy_ecs::{
query::{QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -5,7 +5,7 @@ use bevy_ecs::{
query::{QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut},
};
use bevy_image::{BevyDefault, Image};

View File

@ -46,7 +46,7 @@ use bevy_ecs::{
query::{QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -11,7 +11,7 @@ use bevy_ecs::{
prelude::{Component, Entity, ReflectComponent},
query::{QueryItem, With},
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -11,7 +11,7 @@ use bevy_ecs::{
prelude::Local,
query::With,
resource::Resource,
schedule::{common_conditions::resource_changed, IntoSystemConfigs},
schedule::{common_conditions::resource_changed, IntoScheduleConfigs},
system::{Commands, Query, Res},
};
use bevy_render::view::Visibility;

View File

@ -85,8 +85,8 @@ pub mod prelude {
removal_detection::RemovedComponents,
resource::Resource,
schedule::{
apply_deferred, common_conditions::*, ApplyDeferred, Condition, IntoSystemConfigs,
IntoSystemSet, IntoSystemSetConfigs, Schedule, Schedules, SystemSet,
apply_deferred, common_conditions::*, ApplyDeferred, Condition, IntoScheduleConfigs,
IntoSystemSet, Schedule, Schedules, SystemSet,
},
spawn::{Spawn, SpawnRelated},
system::{

View File

@ -112,7 +112,7 @@ mod tests {
ArchetypeFilter, FilteredAccess, Has, QueryCombinationIter, QueryData,
ReadOnlyQueryData, WorldQuery,
},
schedule::{IntoSystemConfigs, Schedule},
schedule::{IntoScheduleConfigs, Schedule},
storage::{Table, TableRow},
system::{assert_is_system, IntoSystem, Query, System, SystemState},
world::{unsafe_world_cell::UnsafeWorldCell, World},

View File

@ -1267,7 +1267,7 @@ mod tests {
use crate::{
change_detection::ResMut,
component::Component,
schedule::{IntoSystemConfigs, Schedule},
schedule::{IntoScheduleConfigs, Schedule},
system::Local,
world::World,
};

View File

@ -36,61 +36,87 @@ fn ambiguous_with(graph_info: &mut GraphInfo, set: InternedSystemSet) {
}
}
/// Stores data to differentiate different schedulable structs.
pub trait Schedulable {
/// Additional data used to configure independent scheduling. Stored in [`ScheduleConfig`].
type Metadata;
/// Additional data used to configure a schedulable group. Stored in [`ScheduleConfigs`].
type GroupMetadata;
/// Initializes a configuration from this node.
fn into_config(self) -> ScheduleConfig<Self>
where
Self: Sized;
}
impl Schedulable for ScheduleSystem {
type Metadata = GraphInfo;
type GroupMetadata = Chain;
fn into_config(self) -> ScheduleConfig<Self> {
let sets = self.default_system_sets().clone();
ScheduleConfig {
node: self,
metadata: GraphInfo {
hierarchy: sets,
..Default::default()
},
conditions: Vec::new(),
}
}
}
impl Schedulable for InternedSystemSet {
type Metadata = GraphInfo;
type GroupMetadata = Chain;
fn into_config(self) -> ScheduleConfig<Self> {
assert!(
self.system_type().is_none(),
"configuring system type sets is not allowed"
);
ScheduleConfig {
node: self,
metadata: GraphInfo::default(),
conditions: Vec::new(),
}
}
}
/// Stores configuration for a single generic node (a system or a system set)
///
/// The configuration includes the node itself, scheduling metadata
/// (hierarchy: in which sets is the node contained,
/// dependencies: before/after which other nodes should this node run)
/// and the run conditions associated with this node.
pub struct NodeConfig<T> {
pub struct ScheduleConfig<T: Schedulable> {
pub(crate) node: T,
/// Hierarchy and dependency metadata for this node
pub(crate) graph_info: GraphInfo,
pub(crate) metadata: T::Metadata,
pub(crate) conditions: Vec<BoxedCondition>,
}
/// Stores configuration for a single system.
pub type SystemConfig = NodeConfig<ScheduleSystem>;
/// A collections of generic [`NodeConfig`]s.
pub enum NodeConfigs<T> {
/// Configuration for a single node.
NodeConfig(NodeConfig<T>),
/// Single or nested configurations for [`Schedulable`]s.
pub enum ScheduleConfigs<T: Schedulable> {
/// Configuration for a single [`Schedulable`].
ScheduleConfig(ScheduleConfig<T>),
/// Configuration for a tuple of nested `Configs` instances.
Configs {
/// Configuration for each element of the tuple.
configs: Vec<NodeConfigs<T>>,
configs: Vec<ScheduleConfigs<T>>,
/// Run conditions applied to everything in the tuple.
collective_conditions: Vec<BoxedCondition>,
/// See [`Chain`] for usage.
chained: Chain,
/// Metadata to be applied to all elements in the tuple.
metadata: T::GroupMetadata,
},
}
/// A collection of [`SystemConfig`].
pub type SystemConfigs = NodeConfigs<ScheduleSystem>;
impl SystemConfigs {
fn new_system(system: ScheduleSystem) -> Self {
// include system in its default sets
let sets = system.default_system_sets().into_iter().collect();
Self::NodeConfig(SystemConfig {
node: system,
graph_info: GraphInfo {
hierarchy: sets,
..Default::default()
},
conditions: Vec::new(),
})
}
}
impl<T> NodeConfigs<T> {
impl<T: Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>> ScheduleConfigs<T> {
/// Adds a new boxed system set to the systems.
pub fn in_set_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
config.graph_info.hierarchy.push(set);
Self::ScheduleConfig(config) => {
config.metadata.hierarchy.push(set);
}
Self::Configs { configs, .. } => {
for config in configs {
@ -102,9 +128,9 @@ impl<T> NodeConfigs<T> {
fn before_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config
.graph_info
.metadata
.dependencies
.push(Dependency::new(DependencyKind::Before, set));
}
@ -118,9 +144,9 @@ impl<T> NodeConfigs<T> {
fn after_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config
.graph_info
.metadata
.dependencies
.push(Dependency::new(DependencyKind::After, set));
}
@ -134,9 +160,9 @@ impl<T> NodeConfigs<T> {
fn before_ignore_deferred_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config
.graph_info
.metadata
.dependencies
.push(Dependency::new(DependencyKind::Before, set).add_config(IgnoreDeferred));
}
@ -150,9 +176,9 @@ impl<T> NodeConfigs<T> {
fn after_ignore_deferred_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config
.graph_info
.metadata
.dependencies
.push(Dependency::new(DependencyKind::After, set).add_config(IgnoreDeferred));
}
@ -166,7 +192,7 @@ impl<T> NodeConfigs<T> {
fn distributive_run_if_inner<M>(&mut self, condition: impl Condition<M> + Clone) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config.conditions.push(new_condition(condition));
}
Self::Configs { configs, .. } => {
@ -179,8 +205,8 @@ impl<T> NodeConfigs<T> {
fn ambiguous_with_inner(&mut self, set: InternedSystemSet) {
match self {
Self::NodeConfig(config) => {
ambiguous_with(&mut config.graph_info, set);
Self::ScheduleConfig(config) => {
ambiguous_with(&mut config.metadata, set);
}
Self::Configs { configs, .. } => {
for config in configs {
@ -192,8 +218,8 @@ impl<T> NodeConfigs<T> {
fn ambiguous_with_all_inner(&mut self) {
match self {
Self::NodeConfig(config) => {
config.graph_info.ambiguous_with = Ambiguity::IgnoreAll;
Self::ScheduleConfig(config) => {
config.metadata.ambiguous_with = Ambiguity::IgnoreAll;
}
Self::Configs { configs, .. } => {
for config in configs {
@ -209,7 +235,7 @@ impl<T> NodeConfigs<T> {
/// Prefer `run_if` for run conditions whose type is known at compile time.
pub fn run_if_dyn(&mut self, condition: BoxedCondition) {
match self {
Self::NodeConfig(config) => {
Self::ScheduleConfig(config) => {
config.conditions.push(condition);
}
Self::Configs {
@ -223,9 +249,9 @@ impl<T> NodeConfigs<T> {
fn chain_inner(mut self) -> Self {
match &mut self {
Self::NodeConfig(_) => { /* no op */ }
Self::Configs { chained, .. } => {
chained.set_chained();
Self::ScheduleConfig(_) => { /* no op */ }
Self::Configs { metadata, .. } => {
metadata.set_chained();
}
};
self
@ -233,16 +259,16 @@ impl<T> NodeConfigs<T> {
fn chain_ignore_deferred_inner(mut self) -> Self {
match &mut self {
Self::NodeConfig(_) => { /* no op */ }
Self::Configs { chained, .. } => {
chained.set_chained_with_config(IgnoreDeferred);
Self::ScheduleConfig(_) => { /* no op */ }
Self::Configs { metadata, .. } => {
metadata.set_chained_with_config(IgnoreDeferred);
}
}
self
}
}
/// Types that can convert into a [`SystemConfigs`].
/// Types that can convert into a [`ScheduleConfigs`].
///
/// This trait is implemented for "systems" (functions whose arguments all implement
/// [`SystemParam`](crate::system::SystemParam)), or tuples thereof.
@ -252,19 +278,19 @@ impl<T> NodeConfigs<T> {
///
/// This trait should only be used as a bound for trait implementations or as an
/// argument to a function. If system configs need to be returned from a
/// function or stored somewhere, use [`SystemConfigs`] instead of this trait.
/// function or stored somewhere, use [`ScheduleConfigs`] instead of this trait.
///
/// # Examples
///
/// ```
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::{schedule::IntoScheduleConfigs, system::ScheduleSystem};
/// # struct AppMock;
/// # struct Update;
/// # impl AppMock {
/// # pub fn add_systems<M>(
/// # &mut self,
/// # schedule: Update,
/// # systems: impl IntoSystemConfigs<M>,
/// # systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
/// # ) -> &mut Self { self }
/// # }
/// # let mut app = AppMock;
@ -286,16 +312,15 @@ impl<T> NodeConfigs<T> {
message = "`{Self}` does not describe a valid system configuration",
label = "invalid system configuration"
)]
pub trait IntoSystemConfigs<Marker>
where
Self: Sized,
pub trait IntoScheduleConfigs<T: Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>, Marker>:
Sized
{
/// Convert into a [`SystemConfigs`].
fn into_configs(self) -> SystemConfigs;
/// Convert into a [`ScheduleConfigs`].
fn into_configs(self) -> ScheduleConfigs<T>;
/// Add these systems to the provided `set`.
#[track_caller]
fn in_set(self, set: impl SystemSet) -> SystemConfigs {
fn in_set(self, set: impl SystemSet) -> ScheduleConfigs<T> {
self.into_configs().in_set(set)
}
@ -307,7 +332,7 @@ where
///
/// Calling [`.chain`](Self::chain) is often more convenient and ensures that all systems are added to the schedule.
/// Please check the [caveats section of `.after`](Self::after) for details.
fn before<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
fn before<M>(self, set: impl IntoSystemSet<M>) -> ScheduleConfigs<T> {
self.into_configs().before(set)
}
@ -334,7 +359,7 @@ where
/// any ordering calls between them—whether using `.before`, `.after`, or `.chain`—will be silently ignored.
///
/// [`configure_sets`]: https://docs.rs/bevy/latest/bevy/app/struct.App.html#method.configure_sets
fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
fn after<M>(self, set: impl IntoSystemSet<M>) -> ScheduleConfigs<T> {
self.into_configs().after(set)
}
@ -342,7 +367,7 @@ where
///
/// Unlike [`before`](Self::before), this will not cause the systems in
/// `set` to wait for the deferred effects of `self` to be applied.
fn before_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
fn before_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> ScheduleConfigs<T> {
self.into_configs().before_ignore_deferred(set)
}
@ -350,7 +375,7 @@ where
///
/// Unlike [`after`](Self::after), this will not wait for the deferred
/// effects of systems in `set` to be applied.
fn after_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
fn after_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> ScheduleConfigs<T> {
self.into_configs().after_ignore_deferred(set)
}
@ -362,7 +387,7 @@ where
/// Each individual condition will be evaluated at most once (per schedule run),
/// right before the corresponding system prepares to run.
///
/// This is equivalent to calling [`run_if`](IntoSystemConfigs::run_if) on each individual
/// This is equivalent to calling [`run_if`](IntoScheduleConfigs::run_if) on each individual
/// system, as shown below:
///
/// ```
@ -381,10 +406,10 @@ where
/// that all evaluations in a single schedule run will yield the same result. If another
/// system is run inbetween two evaluations it could cause the result of the condition to change.
///
/// Use [`run_if`](IntoSystemSetConfigs::run_if) on a [`SystemSet`] if you want to make sure
/// Use [`run_if`](ScheduleConfigs::run_if) on a [`SystemSet`] if you want to make sure
/// that either all or none of the systems are run, or you don't want to evaluate the run
/// condition for each contained system separately.
fn distributive_run_if<M>(self, condition: impl Condition<M> + Clone) -> SystemConfigs {
fn distributive_run_if<M>(self, condition: impl Condition<M> + Clone) -> ScheduleConfigs<T> {
self.into_configs().distributive_run_if(condition)
}
@ -416,21 +441,21 @@ where
/// is upheld after the first system has run. You need to make sure that no other systems that
/// could invalidate the condition are scheduled inbetween the first and last run system.
///
/// Use [`distributive_run_if`](IntoSystemConfigs::distributive_run_if) if you want the
/// Use [`distributive_run_if`](IntoScheduleConfigs::distributive_run_if) if you want the
/// condition to be evaluated for each individual system, right before one is run.
fn run_if<M>(self, condition: impl Condition<M>) -> SystemConfigs {
fn run_if<M>(self, condition: impl Condition<M>) -> ScheduleConfigs<T> {
self.into_configs().run_if(condition)
}
/// Suppress warnings and errors that would result from these systems having ambiguities
/// (conflicting access but indeterminate order) with systems in `set`.
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> ScheduleConfigs<T> {
self.into_configs().ambiguous_with(set)
}
/// Suppress warnings and errors that would result from these systems having ambiguities
/// (conflicting access but indeterminate order) with any other system.
fn ambiguous_with_all(self) -> SystemConfigs {
fn ambiguous_with_all(self) -> ScheduleConfigs<T> {
self.into_configs().ambiguous_with_all()
}
@ -441,7 +466,7 @@ where
/// If the preceding node on an edge has deferred parameters, an [`ApplyDeferred`](crate::schedule::ApplyDeferred)
/// will be inserted on the edge. If this behavior is not desired consider using
/// [`chain_ignore_deferred`](Self::chain_ignore_deferred) instead.
fn chain(self) -> SystemConfigs {
fn chain(self) -> ScheduleConfigs<T> {
self.into_configs().chain()
}
@ -450,12 +475,14 @@ where
/// Ordering constraints will be applied between the successive elements.
///
/// Unlike [`chain`](Self::chain) this will **not** add [`ApplyDeferred`](crate::schedule::ApplyDeferred) on the edges.
fn chain_ignore_deferred(self) -> SystemConfigs {
fn chain_ignore_deferred(self) -> ScheduleConfigs<T> {
self.into_configs().chain_ignore_deferred()
}
}
impl IntoSystemConfigs<()> for SystemConfigs {
impl<T: Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>> IntoScheduleConfigs<T, ()>
for ScheduleConfigs<T>
{
fn into_configs(self) -> Self {
self
}
@ -496,12 +523,15 @@ impl IntoSystemConfigs<()> for SystemConfigs {
self
}
fn distributive_run_if<M>(mut self, condition: impl Condition<M> + Clone) -> SystemConfigs {
fn distributive_run_if<M>(
mut self,
condition: impl Condition<M> + Clone,
) -> ScheduleConfigs<T> {
self.distributive_run_if_inner(condition);
self
}
fn run_if<M>(mut self, condition: impl Condition<M>) -> SystemConfigs {
fn run_if<M>(mut self, condition: impl Condition<M>) -> ScheduleConfigs<T> {
self.run_if_dyn(new_condition(condition));
self
}
@ -526,49 +556,55 @@ impl IntoSystemConfigs<()> for SystemConfigs {
}
}
/// Marker component to allow for conflicting implementations of [`IntoSystemConfigs`]
/// Marker component to allow for conflicting implementations of [`IntoScheduleConfigs`]
#[doc(hidden)]
pub struct Infallible;
impl<F, Marker> IntoSystemConfigs<(Infallible, Marker)> for F
impl<F, Marker> IntoScheduleConfigs<ScheduleSystem, (Infallible, Marker)> for F
where
F: IntoSystem<(), (), Marker>,
{
fn into_configs(self) -> SystemConfigs {
fn into_configs(self) -> ScheduleConfigs<ScheduleSystem> {
let wrapper = InfallibleSystemWrapper::new(IntoSystem::into_system(self));
SystemConfigs::new_system(Box::new(wrapper))
ScheduleConfigs::ScheduleConfig(ScheduleSystem::into_config(Box::new(wrapper)))
}
}
/// Marker component to allow for conflicting implementations of [`IntoSystemConfigs`]
/// Marker component to allow for conflicting implementations of [`IntoScheduleConfigs`]
#[doc(hidden)]
pub struct Fallible;
impl<F, Marker> IntoSystemConfigs<(Fallible, Marker)> for F
impl<F, Marker> IntoScheduleConfigs<ScheduleSystem, (Fallible, Marker)> for F
where
F: IntoSystem<(), Result, Marker>,
{
fn into_configs(self) -> SystemConfigs {
fn into_configs(self) -> ScheduleConfigs<ScheduleSystem> {
let boxed_system = Box::new(IntoSystem::into_system(self));
SystemConfigs::new_system(boxed_system)
ScheduleConfigs::ScheduleConfig(ScheduleSystem::into_config(boxed_system))
}
}
impl IntoSystemConfigs<()> for BoxedSystem<(), Result> {
fn into_configs(self) -> SystemConfigs {
SystemConfigs::new_system(self)
impl IntoScheduleConfigs<ScheduleSystem, ()> for BoxedSystem<(), Result> {
fn into_configs(self) -> ScheduleConfigs<ScheduleSystem> {
ScheduleConfigs::ScheduleConfig(ScheduleSystem::into_config(self))
}
}
impl<S: SystemSet> IntoScheduleConfigs<InternedSystemSet, ()> for S {
fn into_configs(self) -> ScheduleConfigs<InternedSystemSet> {
ScheduleConfigs::ScheduleConfig(InternedSystemSet::into_config(self.intern()))
}
}
#[doc(hidden)]
pub struct SystemConfigTupleMarker;
pub struct ScheduleConfigTupleMarker;
macro_rules! impl_system_collection {
macro_rules! impl_node_type_collection {
($(#[$meta:meta])* $(($param: ident, $sys: ident)),*) => {
$(#[$meta])*
impl<$($param, $sys),*> IntoSystemConfigs<(SystemConfigTupleMarker, $($param,)*)> for ($($sys,)*)
impl<$($param, $sys),*, T: Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>> IntoScheduleConfigs<T, (ScheduleConfigTupleMarker, $($param,)*)> for ($($sys,)*)
where
$($sys: IntoSystemConfigs<$param>),*
$($sys: IntoScheduleConfigs<T, $param>),*
{
#[expect(
clippy::allow_attributes,
@ -578,12 +614,12 @@ macro_rules! impl_system_collection {
non_snake_case,
reason = "Variable names are provided by the macro caller, not by us."
)]
fn into_configs(self) -> SystemConfigs {
fn into_configs(self) -> ScheduleConfigs<T> {
let ($($sys,)*) = self;
SystemConfigs::Configs {
ScheduleConfigs::Configs {
metadata: Default::default(),
configs: vec![$($sys.into_configs(),)*],
collective_conditions: Vec::new(),
chained: Default::default(),
}
}
}
@ -592,246 +628,9 @@ macro_rules! impl_system_collection {
all_tuples!(
#[doc(fake_variadic)]
impl_system_collection,
impl_node_type_collection,
1,
20,
P,
S
);
/// A [`SystemSet`] with scheduling metadata.
pub type SystemSetConfig = NodeConfig<InternedSystemSet>;
impl SystemSetConfig {
#[track_caller]
pub(super) fn new(set: InternedSystemSet) -> Self {
// system type sets are automatically populated
// to avoid unintentionally broad changes, they cannot be configured
assert!(
set.system_type().is_none(),
"configuring system type sets is not allowed"
);
Self {
node: set,
graph_info: GraphInfo::default(),
conditions: Vec::new(),
}
}
}
/// A collection of [`SystemSetConfig`].
pub type SystemSetConfigs = NodeConfigs<InternedSystemSet>;
/// Types that can convert into a [`SystemSetConfigs`].
///
/// # Usage notes
///
/// This trait should only be used as a bound for trait implementations or as an
/// argument to a function. If system set configs need to be returned from a
/// function or stored somewhere, use [`SystemSetConfigs`] instead of this trait.
#[diagnostic::on_unimplemented(
message = "`{Self}` does not describe a valid system set configuration",
label = "invalid system set configuration"
)]
pub trait IntoSystemSetConfigs
where
Self: Sized,
{
/// Convert into a [`SystemSetConfigs`].
#[doc(hidden)]
fn into_configs(self) -> SystemSetConfigs;
/// Add these system sets to the provided `set`.
#[track_caller]
fn in_set(self, set: impl SystemSet) -> SystemSetConfigs {
self.into_configs().in_set(set)
}
/// Runs before all systems in `set`. If `self` has any systems that produce [`Commands`](crate::system::Commands)
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `set` will see their effect.
///
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
/// this isn't desired, use [`before_ignore_deferred`](Self::before_ignore_deferred) instead.
fn before<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
self.into_configs().before(set)
}
/// Runs after all systems in `set`. If `set` has any systems that produce [`Commands`](crate::system::Commands)
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `self` will see their effect.
///
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
/// this isn't desired, use [`after_ignore_deferred`](Self::after_ignore_deferred) instead.
fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
self.into_configs().after(set)
}
/// Run before all systems in `set`.
///
/// Unlike [`before`](Self::before), this will not cause the systems in `set` to wait for the
/// deferred effects of `self` to be applied.
fn before_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
self.into_configs().before_ignore_deferred(set)
}
/// Run after all systems in `set`.
///
/// Unlike [`after`](Self::after), this may not see the deferred
/// effects of systems in `set` to be applied.
fn after_ignore_deferred<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
self.into_configs().after_ignore_deferred(set)
}
/// Run the systems in this set(s) only if the [`Condition`] is `true`.
///
/// The `Condition` will be evaluated at most once (per schedule run),
/// the first time a system in this set(s) prepares to run.
fn run_if<M>(self, condition: impl Condition<M>) -> SystemSetConfigs {
self.into_configs().run_if(condition)
}
/// Suppress warnings and errors that would result from systems in these sets having ambiguities
/// (conflicting access but indeterminate order) with systems in `set`.
fn ambiguous_with<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
self.into_configs().ambiguous_with(set)
}
/// Suppress warnings and errors that would result from systems in these sets having ambiguities
/// (conflicting access but indeterminate order) with any other system.
fn ambiguous_with_all(self) -> SystemSetConfigs {
self.into_configs().ambiguous_with_all()
}
/// Treat this collection as a sequence of system sets.
///
/// Ordering constraints will be applied between the successive elements.
fn chain(self) -> SystemSetConfigs {
self.into_configs().chain()
}
/// Treat this collection as a sequence of systems.
///
/// Ordering constraints will be applied between the successive elements.
///
/// Unlike [`chain`](Self::chain) this will **not** add [`ApplyDeferred`](crate::schedule::ApplyDeferred) on the edges.
fn chain_ignore_deferred(self) -> SystemSetConfigs {
self.into_configs().chain_ignore_deferred()
}
}
impl IntoSystemSetConfigs for SystemSetConfigs {
fn into_configs(self) -> Self {
self
}
#[track_caller]
fn in_set(mut self, set: impl SystemSet) -> Self {
assert!(
set.system_type().is_none(),
"adding arbitrary systems to a system type set is not allowed"
);
self.in_set_inner(set.intern());
self
}
fn before<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
let set = set.into_system_set();
self.before_inner(set.intern());
self
}
fn after<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
let set = set.into_system_set();
self.after_inner(set.intern());
self
}
fn before_ignore_deferred<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
let set = set.into_system_set();
self.before_ignore_deferred_inner(set.intern());
self
}
fn after_ignore_deferred<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
let set = set.into_system_set();
self.after_ignore_deferred_inner(set.intern());
self
}
fn run_if<M>(mut self, condition: impl Condition<M>) -> SystemSetConfigs {
self.run_if_dyn(new_condition(condition));
self
}
fn ambiguous_with<M>(mut self, set: impl IntoSystemSet<M>) -> Self {
let set = set.into_system_set();
self.ambiguous_with_inner(set.intern());
self
}
fn ambiguous_with_all(mut self) -> Self {
self.ambiguous_with_all_inner();
self
}
fn chain(self) -> Self {
self.chain_inner()
}
fn chain_ignore_deferred(self) -> Self {
self.chain_ignore_deferred_inner()
}
}
impl<S: SystemSet> IntoSystemSetConfigs for S {
fn into_configs(self) -> SystemSetConfigs {
SystemSetConfigs::NodeConfig(SystemSetConfig::new(self.intern()))
}
}
impl IntoSystemSetConfigs for SystemSetConfig {
fn into_configs(self) -> SystemSetConfigs {
SystemSetConfigs::NodeConfig(self)
}
}
macro_rules! impl_system_set_collection {
($(#[$meta:meta])* $($set: ident),*) => {
$(#[$meta])*
impl<$($set: IntoSystemSetConfigs),*> IntoSystemSetConfigs for ($($set,)*)
{
#[expect(
clippy::allow_attributes,
reason = "We are inside a macro, and as such, `non_snake_case` is not guaranteed to apply."
)]
#[allow(
non_snake_case,
reason = "Variable names are provided by the macro caller, not by us."
)]
fn into_configs(self) -> SystemSetConfigs {
let ($($set,)*) = self;
SystemSetConfigs::Configs {
configs: vec![$($set.into_configs(),)*],
collective_conditions: Vec::new(),
chained: Default::default(),
}
}
}
}
}
all_tuples!(
#[doc(fake_variadic)]
impl_system_set_collection,
1,
20,
S
);

View File

@ -312,7 +312,7 @@ mod __rust_begin_short_backtrace {
#[cfg(test)]
mod tests {
use crate::{
prelude::{IntoSystemConfigs, IntoSystemSetConfigs, Resource, Schedule, SystemSet},
prelude::{IntoScheduleConfigs, Resource, Schedule, SystemSet},
schedule::ExecutorKind,
system::{Commands, Res, WithParamWarnPolicy},
world::World,

View File

@ -811,7 +811,7 @@ impl MainThreadExecutor {
mod tests {
use crate::{
prelude::Resource,
schedule::{ExecutorKind, IntoSystemConfigs, Schedule},
schedule::{ExecutorKind, IntoScheduleConfigs, Schedule},
system::Commands,
world::World,
};

View File

@ -62,7 +62,7 @@ pub(crate) enum Ambiguity {
/// Metadata about how the node fits in the schedule graph
#[derive(Default)]
pub(crate) struct GraphInfo {
pub struct GraphInfo {
/// the sets that the node belongs to (hierarchy)
pub(crate) hierarchy: Vec<InternedSystemSet>,
/// the sets that the node depends on (must run before or after)

View File

@ -173,7 +173,7 @@ impl Schedules {
pub fn add_systems<M>(
&mut self,
schedule: impl ScheduleLabel,
systems: impl IntoSystemConfigs<M>,
systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
) -> &mut Self {
self.entry(schedule).add_systems(systems);
@ -182,10 +182,10 @@ impl Schedules {
/// Configures a collection of system sets in the provided schedule, adding any sets that do not exist.
#[track_caller]
pub fn configure_sets(
pub fn configure_sets<M>(
&mut self,
schedule: impl ScheduleLabel,
sets: impl IntoSystemSetConfigs,
sets: impl IntoScheduleConfigs<InternedSystemSet, M>,
) -> &mut Self {
self.entry(schedule).configure_sets(sets);
@ -334,7 +334,10 @@ impl Schedule {
}
/// Add a collection of systems to the schedule.
pub fn add_systems<M>(&mut self, systems: impl IntoSystemConfigs<M>) -> &mut Self {
pub fn add_systems<M>(
&mut self,
systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
) -> &mut Self {
self.graph.process_configs(systems.into_configs(), false);
self
}
@ -372,7 +375,10 @@ impl Schedule {
/// Configures a collection of system sets in this schedule, adding them if they does not exist.
#[track_caller]
pub fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) -> &mut Self {
pub fn configure_sets<M>(
&mut self,
sets: impl IntoScheduleConfigs<InternedSystemSet, M>,
) -> &mut Self {
self.graph.configure_sets(sets);
self
}
@ -825,9 +831,9 @@ impl ScheduleGraph {
&self.conflicting_systems
}
fn process_config<T: ProcessNodeConfig>(
fn process_config<T: ProcessScheduleConfig + Schedulable>(
&mut self,
config: NodeConfig<T>,
config: ScheduleConfig<T>,
collect_nodes: bool,
) -> ProcessConfigsResult {
ProcessConfigsResult {
@ -839,9 +845,11 @@ impl ScheduleGraph {
}
}
fn apply_collective_conditions<T: ProcessNodeConfig>(
fn apply_collective_conditions<
T: ProcessScheduleConfig + Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>,
>(
&mut self,
configs: &mut [NodeConfigs<T>],
configs: &mut [ScheduleConfigs<T>],
collective_conditions: Vec<BoxedCondition>,
) {
if !collective_conditions.is_empty() {
@ -854,7 +862,7 @@ impl ScheduleGraph {
for config in configs.iter_mut() {
config.in_set_inner(set.intern());
}
let mut set_config = SystemSetConfig::new(set.intern());
let mut set_config = InternedSystemSet::into_config(set.intern());
set_config.conditions.extend(collective_conditions);
self.configure_set_inner(set_config).unwrap();
}
@ -867,24 +875,26 @@ impl ScheduleGraph {
/// `process_config` is the function which processes each individual config node and returns a corresponding `NodeId`.
///
/// The fields on the returned [`ProcessConfigsResult`] are:
/// - `nodes`: a vector of all node ids contained in the nested `NodeConfigs`
/// - `nodes`: a vector of all node ids contained in the nested `ScheduleConfigs`
/// - `densely_chained`: a boolean that is true if all nested nodes are linearly chained (with successive `after` orderings) in the order they are defined
#[track_caller]
fn process_configs<T: ProcessNodeConfig>(
fn process_configs<
T: ProcessScheduleConfig + Schedulable<Metadata = GraphInfo, GroupMetadata = Chain>,
>(
&mut self,
configs: NodeConfigs<T>,
configs: ScheduleConfigs<T>,
collect_nodes: bool,
) -> ProcessConfigsResult {
match configs {
NodeConfigs::NodeConfig(config) => self.process_config(config, collect_nodes),
NodeConfigs::Configs {
ScheduleConfigs::ScheduleConfig(config) => self.process_config(config, collect_nodes),
ScheduleConfigs::Configs {
metadata,
mut configs,
collective_conditions,
chained,
} => {
self.apply_collective_conditions(&mut configs, collective_conditions);
let is_chained = matches!(chained, Chain::Chained(_));
let is_chained = matches!(metadata, Chain::Chained(_));
// Densely chained if
// * chained and all configs in the chain are densely chained, or
@ -906,7 +916,7 @@ impl ScheduleGraph {
let current_result = self.process_configs(current, collect_nodes || is_chained);
densely_chained &= current_result.densely_chained;
if let Chain::Chained(chain_options) = &chained {
if let Chain::Chained(chain_options) = &metadata {
// if the current result is densely chained, we only need to chain the first node
let current_nodes = if current_result.densely_chained {
&current_result.nodes[..1]
@ -954,12 +964,15 @@ impl ScheduleGraph {
}
}
/// Add a [`SystemConfig`] to the graph, including its dependencies and conditions.
fn add_system_inner(&mut self, config: SystemConfig) -> Result<NodeId, ScheduleBuildError> {
/// Add a [`ScheduleConfig`] to the graph, including its dependencies and conditions.
fn add_system_inner(
&mut self,
config: ScheduleConfig<ScheduleSystem>,
) -> Result<NodeId, ScheduleBuildError> {
let id = NodeId::System(self.systems.len());
// graph updates are immediate
self.update_graphs(id, config.graph_info)?;
self.update_graphs(id, config.metadata)?;
// system init has to be deferred (need `&mut World`)
self.uninit.push((id, 0));
@ -970,15 +983,18 @@ impl ScheduleGraph {
}
#[track_caller]
fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) {
fn configure_sets<M>(&mut self, sets: impl IntoScheduleConfigs<InternedSystemSet, M>) {
self.process_configs(sets.into_configs(), false);
}
/// Add a single `SystemSetConfig` to the graph, including its dependencies and conditions.
fn configure_set_inner(&mut self, set: SystemSetConfig) -> Result<NodeId, ScheduleBuildError> {
let SystemSetConfig {
/// Add a single `ScheduleConfig` to the graph, including its dependencies and conditions.
fn configure_set_inner(
&mut self,
set: ScheduleConfig<InternedSystemSet>,
) -> Result<NodeId, ScheduleBuildError> {
let ScheduleConfig {
node: set,
graph_info,
metadata,
mut conditions,
} = set;
@ -988,7 +1004,7 @@ impl ScheduleGraph {
};
// graph updates are immediate
self.update_graphs(id, graph_info)?;
self.update_graphs(id, metadata)?;
// system init has to be deferred (need `&mut World`)
let system_set_conditions = &mut self.system_set_conditions[id.index()];
@ -1545,7 +1561,7 @@ impl ScheduleGraph {
/// Values returned by [`ScheduleGraph::process_configs`]
struct ProcessConfigsResult {
/// All nodes contained inside this `process_configs` call's [`NodeConfigs`] hierarchy,
/// All nodes contained inside this `process_configs` call's [`ScheduleConfigs`] hierarchy,
/// if `ancestor_chained` is true
nodes: Vec<NodeId>,
/// True if and only if all nodes are "densely chained", meaning that all nested nodes
@ -1554,20 +1570,20 @@ struct ProcessConfigsResult {
densely_chained: bool,
}
/// Trait used by [`ScheduleGraph::process_configs`] to process a single [`NodeConfig`].
trait ProcessNodeConfig: Sized {
/// Process a single [`NodeConfig`].
fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId;
/// Trait used by [`ScheduleGraph::process_configs`] to process a single [`ScheduleConfig`].
trait ProcessScheduleConfig: Schedulable + Sized {
/// Process a single [`ScheduleConfig`].
fn process_config(schedule_graph: &mut ScheduleGraph, config: ScheduleConfig<Self>) -> NodeId;
}
impl ProcessNodeConfig for ScheduleSystem {
fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId {
impl ProcessScheduleConfig for ScheduleSystem {
fn process_config(schedule_graph: &mut ScheduleGraph, config: ScheduleConfig<Self>) -> NodeId {
schedule_graph.add_system_inner(config).unwrap()
}
}
impl ProcessNodeConfig for InternedSystemSet {
fn process_config(schedule_graph: &mut ScheduleGraph, config: NodeConfig<Self>) -> NodeId {
impl ProcessScheduleConfig for InternedSystemSet {
fn process_config(schedule_graph: &mut ScheduleGraph, config: ScheduleConfig<Self>) -> NodeId {
schedule_graph.configure_set_inner(config).unwrap()
}
}
@ -2058,8 +2074,7 @@ mod tests {
use crate::{
prelude::{ApplyDeferred, Res, Resource},
schedule::{
tests::ResMut, IntoSystemConfigs, IntoSystemSetConfigs, Schedule,
ScheduleBuildSettings, SystemSet,
tests::ResMut, IntoScheduleConfigs, Schedule, ScheduleBuildSettings, SystemSet,
},
system::Commands,
world::World,

View File

@ -342,7 +342,7 @@ mod tests {
removal_detection::RemovedComponents,
resource::Resource,
schedule::{
common_conditions::resource_exists, ApplyDeferred, Condition, IntoSystemConfigs,
common_conditions::resource_exists, ApplyDeferred, Condition, IntoScheduleConfigs,
Schedule,
},
system::{
@ -352,6 +352,8 @@ mod tests {
world::{DeferredWorld, EntityMut, FromWorld, World},
};
use super::ScheduleSystem;
#[derive(Resource, PartialEq, Debug)]
enum SystemRan {
Yes,
@ -390,7 +392,10 @@ mod tests {
system.run((), &mut world);
}
fn run_system<Marker, S: IntoSystemConfigs<Marker>>(world: &mut World, system: S) {
fn run_system<Marker, S: IntoScheduleConfigs<ScheduleSystem, Marker>>(
world: &mut World,
system: S,
) {
let mut schedule = Schedule::default();
schedule.add_systems(system);
schedule.run(world);

View File

@ -30,7 +30,7 @@ use super::IntoSystem;
///
/// Systems are executed in parallel, in opportunistic order; data access is managed automatically.
/// It's possible to specify explicit execution order between specific systems,
/// see [`IntoSystemConfigs`](crate::schedule::IntoSystemConfigs).
/// see [`IntoScheduleConfigs`](crate::schedule::IntoScheduleConfigs).
#[diagnostic::on_unimplemented(message = "`{Self}` is not a system", label = "invalid system")]
pub trait System: Send + Sync + 'static {
/// The system's input.

View File

@ -7,7 +7,7 @@ use bevy_ecs::{
entity::Entity,
query::Without,
reflect::ReflectComponent,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Query, Res},
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};

View File

@ -83,7 +83,7 @@ use bevy_app::{App, FixedFirst, FixedLast, Last, Plugin, RunFixedMainLoop};
use bevy_asset::{weak_handle, Asset, AssetApp, AssetId, Assets, Handle};
use bevy_ecs::{
resource::Resource,
schedule::{IntoSystemConfigs, SystemSet},
schedule::{IntoScheduleConfigs, SystemSet},
system::{Res, ResMut},
};
use bevy_math::Vec4;

View File

@ -14,7 +14,7 @@ use bevy_ecs::{
entity::Entity,
query::Without,
reflect::ReflectComponent,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Query, Res},
};
use bevy_math::{

View File

@ -11,7 +11,7 @@ use bevy_core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT};
use bevy_ecs::{
prelude::Entity,
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -8,11 +8,11 @@ use crate::{
};
use bevy_app::{App, Plugin};
use bevy_core_pipeline::core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::{
prelude::Entity,
resource::Resource,
schedule::IntoScheduleConfigs,
system::{Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -71,7 +71,7 @@ use {
/// Reading and checking against the current set of pressed buttons:
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, Update};
/// # use bevy_ecs::{prelude::{IntoSystemConfigs, Res, Resource, resource_changed}, schedule::Condition};
/// # use bevy_ecs::{prelude::{IntoScheduleConfigs, Res, Resource, resource_changed}, schedule::Condition};
/// # use bevy_input::{ButtonInput, prelude::{KeyCode, MouseButton}};
///
/// fn main() {

View File

@ -6,7 +6,7 @@ use core::hash::Hash;
///
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, Update};
/// # use bevy_ecs::prelude::IntoSystemConfigs;
/// # use bevy_ecs::prelude::IntoScheduleConfigs;
/// # use bevy_input::{common_conditions::input_toggle_active, prelude::KeyCode};
///
/// fn main() {
@ -25,7 +25,7 @@ use core::hash::Hash;
/// you should use a custom resource or a state for that:
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, Update};
/// # use bevy_ecs::prelude::{IntoSystemConfigs, Res, ResMut, Resource};
/// # use bevy_ecs::prelude::{IntoScheduleConfigs, Res, ResMut, Resource};
/// # use bevy_input::{common_conditions::input_just_pressed, prelude::KeyCode};
///
/// #[derive(Resource, Default)]
@ -74,7 +74,7 @@ where
///
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, Update};
/// # use bevy_ecs::prelude::IntoSystemConfigs;
/// # use bevy_ecs::prelude::IntoScheduleConfigs;
/// # use bevy_input::{common_conditions::input_just_pressed, prelude::KeyCode};
/// fn main() {
/// App::new()
@ -104,7 +104,7 @@ where
mod tests {
use super::*;
use crate::prelude::KeyCode;
use bevy_ecs::schedule::{IntoSystemConfigs, Schedule};
use bevy_ecs::schedule::{IntoScheduleConfigs, Schedule};
fn test_system() {}

View File

@ -1763,7 +1763,7 @@ mod tests {
use bevy_app::{App, PreUpdate};
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
fn test_button_axis_settings_filter(
settings: ButtonAxisSettings,

View File

@ -38,7 +38,7 @@ use bevy_core_pipeline::core_3d::graph::Node3d;
use bevy_ecs::{
component::Component,
query::{Changed, QueryItem, With},
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{lifetimeless::Read, Query},
};
use bevy_math::{UVec2, UVec3, Vec3};

View File

@ -25,7 +25,7 @@ use bevy_ecs::{
prelude::ReflectComponent,
query::With,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{Query, Res, ResMut},
};
use bevy_image::Image;

View File

@ -10,7 +10,7 @@ use bevy_ecs::{
query::With,
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Local, Query, Res, ResMut},
};
use bevy_image::Image;

View File

@ -41,7 +41,7 @@ use bevy_ecs::{
reflect::ReflectComponent,
removal_detection::RemovedComponents,
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -69,7 +69,7 @@ use bevy_ecs::{
entity::Entity,
query::Has,
reflect::ReflectComponent,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query},
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};

View File

@ -22,7 +22,7 @@ use bevy_ecs::{
prelude::resource_exists,
query::{Has, Or, QueryState, With, Without},
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -11,7 +11,7 @@ use bevy_ecs::{
query::{Has, QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -17,7 +17,7 @@ use bevy_ecs::{
query::{Has, QueryItem, With},
reflect::ReflectComponent,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{lifetimeless::Read, Commands, Query, Res, ResMut},
world::{FromWorld, World},
};

View File

@ -36,7 +36,9 @@ use bevy_core_pipeline::core_3d::{
graph::{Core3d, Node3d},
prepare_core_3d_depth_textures,
};
use bevy_ecs::{component::Component, reflect::ReflectComponent, schedule::IntoSystemConfigs as _};
use bevy_ecs::{
component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs as _,
};
use bevy_image::Image;
use bevy_math::{
primitives::{Cuboid, Plane3d},

View File

@ -370,7 +370,7 @@ use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
entity::Entity,
resource::Resource,
schedule::{IntoSystemConfigs, IntoSystemSetConfigs, ScheduleLabel, SystemSet},
schedule::{IntoScheduleConfigs, ScheduleLabel, SystemSet},
system::{Commands, In, IntoSystem, ResMut, System, SystemId},
world::World,
};

View File

@ -8,7 +8,7 @@ use bevy_ecs::{
prelude::Entity,
query::{Has, With},
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{Query, Res, ResMut, StaticSystemParam},
world::{FromWorld, World},
};

View File

@ -15,7 +15,7 @@ use crate::{
render_graph::RenderGraph, ExtractSchedule, Render, RenderApp, RenderSet,
};
use bevy_app::{App, Plugin};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
#[derive(Default)]
pub struct CameraPlugin;

View File

@ -6,7 +6,7 @@ use crate::{
use bevy_app::{App, Plugin};
use bevy_ecs::{
prelude::{Component, Entity},
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut},
};
use core::marker::PhantomData;

View File

@ -15,7 +15,7 @@ use async_channel::{Receiver, Sender};
use bevy_app::{App, Plugin};
use bevy_asset::Handle;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
use bevy_ecs::{
change_detection::ResMut,
entity::Entity,

View File

@ -12,7 +12,7 @@ use bevy_asset::AssetId;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{Res, ResMut},
world::{FromWorld, World},
};

View File

@ -1,14 +1,14 @@
use crate::{
render_resource::AsBindGroupError, Extract, ExtractSchedule, MainWorld, Render, RenderApp,
RenderSet,
RenderSet, Res,
};
use bevy_app::{App, Plugin, SubApp};
pub use bevy_asset::RenderAssetUsages;
use bevy_asset::{Asset, AssetEvent, AssetId, Assets};
use bevy_ecs::{
prelude::{Commands, EventReader, IntoSystemConfigs, Res, ResMut, Resource},
schedule::{SystemConfigs, SystemSet},
system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState},
prelude::{Commands, EventReader, IntoScheduleConfigs, ResMut, Resource},
schedule::{ScheduleConfigs, SystemSet},
system::{ScheduleSystem, StaticSystemParam, SystemParam, SystemParamItem, SystemState},
world::{FromWorld, Mut},
};
use bevy_platform_support::collections::{HashMap, HashSet};
@ -132,17 +132,17 @@ impl<A: RenderAsset, AFTER: RenderAssetDependency + 'static> Plugin
// helper to allow specifying dependencies between render assets
pub trait RenderAssetDependency {
fn register_system(render_app: &mut SubApp, system: SystemConfigs);
fn register_system(render_app: &mut SubApp, system: ScheduleConfigs<ScheduleSystem>);
}
impl RenderAssetDependency for () {
fn register_system(render_app: &mut SubApp, system: SystemConfigs) {
fn register_system(render_app: &mut SubApp, system: ScheduleConfigs<ScheduleSystem>) {
render_app.add_systems(Render, system);
}
}
impl<A: RenderAsset> RenderAssetDependency for A {
fn register_system(render_app: &mut SubApp, system: SystemConfigs) {
fn register_system(render_app: &mut SubApp, system: ScheduleConfigs<ScheduleSystem>) {
render_app.add_systems(Render, system.after(prepare_assets::<A>));
}
}

View File

@ -14,7 +14,7 @@ use bevy_ecs::{
reflect::ReflectComponent,
removal_detection::RemovedComponents,
resource::Resource,
schedule::IntoSystemConfigs as _,
schedule::IntoScheduleConfigs as _,
system::{Query, Res, ResMut},
};
use bevy_math::{vec4, FloatOrd, Vec4};

View File

@ -26,7 +26,7 @@ pub mod serde;
/// Rusty Object Notation, a crate used to serialize and deserialize bevy scenes.
pub use bevy_asset::ron;
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
pub use components::*;
pub use dynamic_scene::*;
pub use dynamic_scene_builder::*;

View File

@ -1,5 +1,5 @@
use bevy_app::{App, MainScheduleOrder, Plugin, PreStartup, PreUpdate, SubApp};
use bevy_ecs::{event::Events, schedule::IntoSystemConfigs, world::FromWorld};
use bevy_ecs::{event::Events, schedule::IntoScheduleConfigs, world::FromWorld};
use bevy_utils::once;
use log::warn;

View File

@ -171,7 +171,7 @@ pub fn state_changed<S: States>(current_state: Option<Res<State<S>>>) -> bool {
#[cfg(test)]
mod tests {
use bevy_ecs::schedule::{Condition, IntoSystemConfigs, Schedule};
use bevy_ecs::schedule::{Condition, IntoScheduleConfigs, Schedule};
use crate::prelude::*;
use bevy_state_macros::States;

View File

@ -1,7 +1,7 @@
use bevy_ecs::{
event::EventWriter,
prelude::Schedule,
schedule::{IntoSystemConfigs, IntoSystemSetConfigs},
schedule::IntoScheduleConfigs,
system::{Commands, IntoSystem, ResMut},
};

View File

@ -1,6 +1,6 @@
use bevy_ecs::{
event::{EventReader, EventWriter},
schedule::{IntoSystemConfigs, IntoSystemSetConfigs, Schedule},
schedule::{IntoScheduleConfigs, Schedule},
system::{Commands, IntoSystem, Res, ResMut},
};
use variadics_please::all_tuples;

View File

@ -21,8 +21,8 @@ use core::hash::Hash;
///
/// ```
/// use bevy_state::prelude::*;
/// use bevy_ecs::prelude::IntoSystemConfigs;
/// use bevy_ecs::system::ResMut;
/// use bevy_ecs::prelude::IntoScheduleConfigs;
/// use bevy_ecs::system::{ResMut, ScheduleSystem};
///
///
/// #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
@ -46,7 +46,7 @@ use core::hash::Hash;
///
/// # struct AppMock;
/// # impl AppMock {
/// # fn add_systems<S, M>(&mut self, schedule: S, systems: impl IntoSystemConfigs<M>) {}
/// # fn add_systems<S, M>(&mut self, schedule: S, systems: impl IntoScheduleConfigs<ScheduleSystem, M>) {}
/// # }
/// # struct Update;
/// # let mut app = AppMock;

View File

@ -2,7 +2,7 @@ use core::{marker::PhantomData, mem};
use bevy_ecs::{
event::{Event, EventReader, EventWriter},
schedule::{IntoSystemSetConfigs, Schedule, ScheduleLabel, Schedules, SystemSet},
schedule::{IntoScheduleConfigs, Schedule, ScheduleLabel, Schedules, SystemSet},
system::{Commands, In, ResMut},
world::World,
};

View File

@ -20,6 +20,7 @@ use crate::state::{StateTransitionEvent, States};
/// ```
/// use bevy_state::prelude::*;
/// use bevy_ecs::prelude::*;
/// use bevy_ecs::system::ScheduleSystem;
///
/// #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
/// #[states(scoped_entities)]
@ -44,7 +45,7 @@ use crate::state::{StateTransitionEvent, States};
/// # impl AppMock {
/// # fn init_state<S>(&mut self) {}
/// # fn enable_state_scoped_entities<S>(&mut self) {}
/// # fn add_systems<S, M>(&mut self, schedule: S, systems: impl IntoSystemConfigs<M>) {}
/// # fn add_systems<S, M>(&mut self, schedule: S, systems: impl IntoScheduleConfigs<ScheduleSystem, M>) {}
/// # }
/// # struct Update;
/// # let mut app = AppMock;

View File

@ -371,7 +371,7 @@ mod tests {
use bevy_app::{App, Update};
use bevy_asset::{load_internal_binary_asset, Handle};
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
use crate::{detect_text_needs_rerender, TextIterScratch};

View File

@ -7,7 +7,7 @@ use core::time::Duration;
///
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::on_timer;
/// fn main() {
@ -47,7 +47,7 @@ pub fn on_timer(duration: Duration) -> impl FnMut(Res<Time>) -> bool + Clone {
///
/// ```no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::on_real_timer;
/// fn main() {
@ -87,7 +87,7 @@ pub fn on_real_timer(duration: Duration) -> impl FnMut(Res<Time<Real>>) -> bool
///
/// ```rust,no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::once_after_delay;
/// fn main() {
@ -117,7 +117,7 @@ pub fn once_after_delay(duration: Duration) -> impl FnMut(Res<Time>) -> bool + C
///
/// ```rust,no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::once_after_delay;
/// fn main() {
@ -147,7 +147,7 @@ pub fn once_after_real_delay(duration: Duration) -> impl FnMut(Res<Time<Real>>)
///
/// ```rust,no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::repeating_after_delay;
/// fn main() {
@ -177,7 +177,7 @@ pub fn repeating_after_delay(duration: Duration) -> impl FnMut(Res<Time>) -> boo
///
/// ```rust,no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::IntoSystemConfigs;
/// # use bevy_ecs::schedule::IntoScheduleConfigs;
/// # use core::time::Duration;
/// # use bevy_time::common_conditions::repeating_after_real_delay;
/// fn main() {
@ -209,7 +209,7 @@ pub fn repeating_after_real_delay(
///
/// ```rust,no_run
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, Update};
/// # use bevy_ecs::schedule::{common_conditions::not, IntoSystemConfigs};
/// # use bevy_ecs::schedule::{common_conditions::not, IntoScheduleConfigs};
/// # use bevy_time::common_conditions::paused;
/// fn main() {
/// App::new()
@ -238,7 +238,7 @@ pub fn paused(time: Res<Time<Virtual>>) -> bool {
#[cfg(test)]
mod tests {
use super::*;
use bevy_ecs::schedule::{IntoSystemConfigs, Schedule};
use bevy_ecs::schedule::{IntoScheduleConfigs, Schedule};
fn test_system() {}

View File

@ -1,6 +1,6 @@
use crate::systems::{mark_dirty_trees, propagate_parent_transforms, sync_simple_transforms};
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
use bevy_ecs::schedule::{IntoSystemConfigs, IntoSystemSetConfigs, SystemSet};
use bevy_ecs::schedule::{IntoScheduleConfigs, SystemSet};
/// Set enum for the systems relating to transform propagation
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]

View File

@ -9,7 +9,7 @@ use bevy_app::{App, Plugin, PostUpdate};
use bevy_ecs::{
prelude::{DetectChanges, Entity},
query::{Changed, Without},
schedule::IntoSystemConfigs,
schedule::IntoScheduleConfigs,
system::{Commands, Query},
world::Ref,
};

View File

@ -225,7 +225,7 @@ mod tests {
use bevy_core_pipeline::core_2d::Camera2d;
use bevy_ecs::event::Events;
use bevy_ecs::hierarchy::ChildOf;
use bevy_ecs::schedule::IntoSystemConfigs;
use bevy_ecs::schedule::IntoScheduleConfigs;
use bevy_ecs::schedule::Schedule;
use bevy_ecs::world::World;
use bevy_image::Image;