Remove the config api (#3633)

# Objective

- Fix the ugliness of the `config` api. 
- Supercedes #2440, #2463, #2491

## Solution

- Since #2398, capturing closure systems have worked.
- Use those instead where we needed config before
- Remove the rest of the config api. 
- Related: #2777
This commit is contained in:
Daniel McNab 2022-02-25 03:10:59 +00:00
parent 519148275d
commit c1a4a2f6c5
7 changed files with 107 additions and 284 deletions

View File

@ -4,7 +4,7 @@ use bevy_ecs::{
component::ComponentId, component::ComponentId,
query::Access, query::Access,
schedule::ShouldRun, schedule::ShouldRun,
system::{ConfigurableSystem, IntoSystem, Local, Res, ResMut, System}, system::{IntoSystem, Res, ResMut, System},
world::World, world::World,
}; };
use bevy_utils::HashMap; use bevy_utils::HashMap;
@ -79,7 +79,9 @@ impl Default for FixedTimestep {
fn default() -> Self { fn default() -> Self {
Self { Self {
state: LocalFixedTimestepState::default(), state: LocalFixedTimestepState::default(),
internal_system: Box::new(IntoSystem::into_system(Self::prepare_system)), internal_system: Box::new(IntoSystem::into_system(Self::prepare_system(
Default::default(),
))),
} }
} }
} }
@ -116,18 +118,18 @@ impl FixedTimestep {
} }
fn prepare_system( fn prepare_system(
mut state: Local<LocalFixedTimestepState>, mut state: LocalFixedTimestepState,
time: Res<Time>, ) -> impl FnMut(Res<Time>, ResMut<FixedTimesteps>) -> ShouldRun {
mut fixed_timesteps: ResMut<FixedTimesteps>, move |time, mut fixed_timesteps| {
) -> ShouldRun { let should_run = state.update(&time);
let should_run = state.update(&time); if let Some(ref label) = state.label {
if let Some(ref label) = state.label { let res_state = fixed_timesteps.fixed_timesteps.get_mut(label).unwrap();
let res_state = fixed_timesteps.fixed_timesteps.get_mut(label).unwrap(); res_state.step = state.step;
res_state.step = state.step; res_state.accumulator = state.accumulator;
res_state.accumulator = state.accumulator; }
}
should_run should_run
}
} }
} }
@ -202,8 +204,9 @@ impl System for FixedTimestep {
} }
fn initialize(&mut self, world: &mut World) { fn initialize(&mut self, world: &mut World) {
self.internal_system = self.internal_system = Box::new(IntoSystem::into_system(Self::prepare_system(
Box::new(Self::prepare_system.config(|c| c.0 = Some(self.state.clone()))); self.state.clone(),
)));
self.internal_system.initialize(world); self.internal_system.initialize(world);
if let Some(ref label) = self.state.label { if let Some(ref label) = self.state.label {
let mut fixed_timesteps = world.get_resource_mut::<FixedTimesteps>().unwrap(); let mut fixed_timesteps = world.get_resource_mut::<FixedTimesteps>().unwrap();

View File

@ -222,8 +222,7 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
unsafe impl<#(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamState for QuerySetState<(#(QueryState<#query, #filter>,)*)> unsafe impl<#(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamState for QuerySetState<(#(QueryState<#query, #filter>,)*)>
where #(#filter::Fetch: FilterFetch,)* where #(#filter::Fetch: FilterFetch,)*
{ {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, config: Self::Config) -> Self {
#( #(
let mut #query = QueryState::<#query, #filter>::new(world); let mut #query = QueryState::<#query, #filter>::new(world);
assert_component_access_compatibility( assert_component_access_compatibility(
@ -255,8 +254,6 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
.extend(&#query.archetype_component_access); .extend(&#query.archetype_component_access);
)* )*
} }
fn default_config() {}
} }
impl<'w, 's, #(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamFetch<'w, 's> for QuerySetState<(#(QueryState<#query, #filter>,)*)> impl<'w, 's, #(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamFetch<'w, 's> for QuerySetState<(#(QueryState<#query, #filter>,)*)>
@ -389,10 +386,9 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
} }
unsafe impl<TSystemParamState: #path::system::SystemParamState, #punctuated_generics> #path::system::SystemParamState for #fetch_struct_name<TSystemParamState, #punctuated_generic_idents> { unsafe impl<TSystemParamState: #path::system::SystemParamState, #punctuated_generics> #path::system::SystemParamState for #fetch_struct_name<TSystemParamState, #punctuated_generic_idents> {
type Config = TSystemParamState::Config; fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self {
fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta, config: Self::Config) -> Self {
Self { Self {
state: TSystemParamState::init(world, system_meta, config), state: TSystemParamState::init(world, system_meta),
marker: std::marker::PhantomData, marker: std::marker::PhantomData,
} }
} }
@ -401,10 +397,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
self.state.new_archetype(archetype, system_meta) self.state.new_archetype(archetype, system_meta)
} }
fn default_config() -> TSystemParamState::Config {
TSystemParamState::default_config()
}
fn apply(&mut self, world: &mut #path::world::World) { fn apply(&mut self, world: &mut #path::world::World) {
self.state.apply(world) self.state.apply(world)
} }

View File

@ -33,8 +33,8 @@ pub mod prelude {
Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage, Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage,
}, },
system::{ system::{
Commands, ConfigurableSystem, In, IntoChainSystem, IntoExclusiveSystem, IntoSystem, Commands, In, IntoChainSystem, IntoExclusiveSystem, IntoSystem, Local, NonSend,
Local, NonSend, NonSendMut, Query, QuerySet, RemovedComponents, Res, ResMut, System, NonSendMut, Query, QuerySet, RemovedComponents, Res, ResMut, System,
}, },
world::{FromWorld, Mut, World}, world::{FromWorld, Mut, World},
}; };

View File

@ -3,7 +3,7 @@ use crate::{
RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun, RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun,
SystemSet, SystemSet,
}, },
system::{ConfigurableSystem, In, IntoChainSystem, Local, Res, ResMut}, system::{In, IntoChainSystem, Local, Res, ResMut},
}; };
use std::{any::TypeId, fmt::Debug, hash::Hash}; use std::{any::TypeId, fmt::Debug, hash::Hash};
use thiserror::Error; use thiserror::Error;
@ -98,23 +98,22 @@ impl<T> State<T>
where where
T: StateData, T: StateData,
{ {
pub fn on_update(s: T) -> RunCriteriaDescriptor { pub fn on_update(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, pred: Local<Option<T>>| { let pred_clone = pred.clone();
state.stack.last().unwrap() == pred.as_ref().unwrap() && state.transition.is_none() (move |state: Res<State<T>>| {
state.stack.last().unwrap() == &pred && state.transition.is_none()
}) })
.config(|(_, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::Update.into_label(s)) .label_discard_if_duplicate(StateCallback::Update.into_label(pred_clone))
} }
pub fn on_inactive_update(s: T) -> RunCriteriaDescriptor { pub fn on_inactive_update(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, mut is_inactive: Local<bool>, pred: Local<Option<T>>| match &state let pred_clone = pred.clone();
.transition (move |state: Res<State<T>>, mut is_inactive: Local<bool>| match &state.transition {
{
Some(StateTransition::Pausing(ref relevant, _)) Some(StateTransition::Pausing(ref relevant, _))
| Some(StateTransition::Resuming(_, ref relevant)) => { | Some(StateTransition::Resuming(_, ref relevant)) => {
if relevant == pred.as_ref().unwrap() { if relevant == &pred {
*is_inactive = !*is_inactive; *is_inactive = !*is_inactive;
} }
false false
@ -122,31 +121,29 @@ where
Some(_) => false, Some(_) => false,
None => *is_inactive, None => *is_inactive,
}) })
.config(|(_, _, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::InactiveUpdate.into_label(s)) .label_discard_if_duplicate(StateCallback::InactiveUpdate.into_label(pred_clone))
} }
pub fn on_in_stack_update(s: T) -> RunCriteriaDescriptor { pub fn on_in_stack_update(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, mut is_in_stack: Local<bool>, pred: Local<Option<T>>| match &state let pred_clone = pred.clone();
.transition (move |state: Res<State<T>>, mut is_in_stack: Local<bool>| match &state.transition {
{
Some(StateTransition::Entering(ref relevant, _)) Some(StateTransition::Entering(ref relevant, _))
| Some(StateTransition::ExitingToResume(_, ref relevant)) => { | Some(StateTransition::ExitingToResume(_, ref relevant)) => {
if relevant == pred.as_ref().unwrap() { if relevant == &pred {
*is_in_stack = !*is_in_stack; *is_in_stack = !*is_in_stack;
} }
false false
} }
Some(StateTransition::ExitingFull(_, ref relevant)) => { Some(StateTransition::ExitingFull(_, ref relevant)) => {
if relevant == pred.as_ref().unwrap() { if relevant == &pred {
*is_in_stack = !*is_in_stack; *is_in_stack = !*is_in_stack;
} }
false false
} }
Some(StateTransition::Startup) => { Some(StateTransition::Startup) => {
if state.stack.last().unwrap() == pred.as_ref().unwrap() { if state.stack.last().unwrap() == &pred {
*is_in_stack = !*is_in_stack; *is_in_stack = !*is_in_stack;
} }
false false
@ -154,78 +151,75 @@ where
Some(_) => false, Some(_) => false,
None => *is_in_stack, None => *is_in_stack,
}) })
.config(|(_, _, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::InStackUpdate.into_label(s)) .label_discard_if_duplicate(StateCallback::InStackUpdate.into_label(pred_clone))
} }
pub fn on_enter(s: T) -> RunCriteriaDescriptor { pub fn on_enter(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, pred: Local<Option<T>>| { let pred_clone = pred.clone();
(move |state: Res<State<T>>| {
state state
.transition .transition
.as_ref() .as_ref()
.map_or(false, |transition| match transition { .map_or(false, |transition| match transition {
StateTransition::Entering(_, entering) => entering == pred.as_ref().unwrap(), StateTransition::Entering(_, entering) => entering == &pred,
StateTransition::Startup => { StateTransition::Startup => state.stack.last().unwrap() == &pred,
state.stack.last().unwrap() == pred.as_ref().unwrap()
}
_ => false, _ => false,
}) })
}) })
.config(|(_, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::Enter.into_label(s)) .label_discard_if_duplicate(StateCallback::Enter.into_label(pred_clone))
} }
pub fn on_exit(s: T) -> RunCriteriaDescriptor { pub fn on_exit(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, pred: Local<Option<T>>| { let pred_clone = pred.clone();
(move |state: Res<State<T>>| {
state state
.transition .transition
.as_ref() .as_ref()
.map_or(false, |transition| match transition { .map_or(false, |transition| match transition {
StateTransition::ExitingToResume(exiting, _) StateTransition::ExitingToResume(exiting, _)
| StateTransition::ExitingFull(exiting, _) => exiting == pred.as_ref().unwrap(), | StateTransition::ExitingFull(exiting, _) => exiting == &pred,
_ => false, _ => false,
}) })
}) })
.config(|(_, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::Exit.into_label(s)) .label_discard_if_duplicate(StateCallback::Exit.into_label(pred_clone))
} }
pub fn on_pause(s: T) -> RunCriteriaDescriptor { pub fn on_pause(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, pred: Local<Option<T>>| { let pred_clone = pred.clone();
(move |state: Res<State<T>>| {
state state
.transition .transition
.as_ref() .as_ref()
.map_or(false, |transition| match transition { .map_or(false, |transition| match transition {
StateTransition::Pausing(pausing, _) => pausing == pred.as_ref().unwrap(), StateTransition::Pausing(pausing, _) => pausing == &pred,
_ => false, _ => false,
}) })
}) })
.config(|(_, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::Pause.into_label(s)) .label_discard_if_duplicate(StateCallback::Pause.into_label(pred_clone))
} }
pub fn on_resume(s: T) -> RunCriteriaDescriptor { pub fn on_resume(pred: T) -> RunCriteriaDescriptor {
(|state: Res<State<T>>, pred: Local<Option<T>>| { let pred_clone = pred.clone();
(move |state: Res<State<T>>| {
state state
.transition .transition
.as_ref() .as_ref()
.map_or(false, |transition| match transition { .map_or(false, |transition| match transition {
StateTransition::Resuming(_, resuming) => resuming == pred.as_ref().unwrap(), StateTransition::Resuming(_, resuming) => resuming == &pred,
_ => false, _ => false,
}) })
}) })
.config(|(_, pred)| *pred = Some(Some(s.clone())))
.chain(should_run_adapter::<T>) .chain(should_run_adapter::<T>)
.after(DriverLabel::of::<T>()) .after(DriverLabel::of::<T>())
.label_discard_if_duplicate(StateCallback::Resume.into_label(s)) .label_discard_if_duplicate(StateCallback::Resume.into_label(pred_clone))
} }
pub fn on_update_set(s: T) -> SystemSet { pub fn on_update_set(s: T) -> SystemSet {

View File

@ -141,16 +141,8 @@ pub struct SystemState<Param: SystemParam> {
impl<Param: SystemParam> SystemState<Param> { impl<Param: SystemParam> SystemState<Param> {
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
let config = <Param::Fetch as SystemParamState>::default_config();
Self::with_config(world, config)
}
pub fn with_config(
world: &mut World,
config: <Param::Fetch as SystemParamState>::Config,
) -> Self {
let mut meta = SystemMeta::new::<Param>(); let mut meta = SystemMeta::new::<Param>();
let param_state = <Param::Fetch as SystemParamState>::init(world, &mut meta, config); let param_state = <Param::Fetch as SystemParamState>::init(world, &mut meta);
Self { Self {
meta, meta,
param_state, param_state,
@ -407,73 +399,11 @@ where
func: F, func: F,
param_state: Option<Param::Fetch>, param_state: Option<Param::Fetch>,
system_meta: SystemMeta, system_meta: SystemMeta,
config: Option<<Param::Fetch as SystemParamState>::Config>,
// NOTE: PhantomData<fn()-> T> gives this safe Send/Sync impls // NOTE: PhantomData<fn()-> T> gives this safe Send/Sync impls
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
marker: PhantomData<fn() -> (In, Out, Marker)>, marker: PhantomData<fn() -> (In, Out, Marker)>,
} }
impl<In, Out, Param: SystemParam, Marker, F> FunctionSystem<In, Out, Param, Marker, F> {
/// Gives mutable access to the systems config via a callback. This is useful to set up system
/// [`Local`](crate::system::Local)s.
///
/// # Examples
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let world = &mut World::default();
/// fn local_is_42(local: Local<usize>) {
/// assert_eq!(*local, 42);
/// }
/// let mut system = local_is_42.config(|config| config.0 = Some(42));
/// system.initialize(world);
/// system.run((), world);
/// ```
#[must_use]
pub fn config(
mut self,
f: impl FnOnce(&mut <Param::Fetch as SystemParamState>::Config),
) -> Self {
f(self.config.as_mut().unwrap());
self
}
}
/// Provides `my_system.config(...)` API.
pub trait ConfigurableSystem<In, Out, Param: SystemParam, Marker>:
IntoSystem<In, Out, (IsFunctionSystem, Param, Marker)>
{
/// See [`FunctionSystem::config()`](crate::system::FunctionSystem::config).
fn config(
self,
f: impl FnOnce(&mut <Param::Fetch as SystemParamState>::Config),
) -> Self::System;
}
impl<In, Out, Param: SystemParam, Marker, F> ConfigurableSystem<In, Out, Param, Marker> for F
where
In: 'static,
Out: 'static,
Param: SystemParam + 'static,
Marker: 'static,
F: SystemParamFunction<In, Out, Param, Marker>
+ IntoSystem<
In,
Out,
(IsFunctionSystem, Param, Marker),
System = FunctionSystem<In, Out, Param, Marker, F>,
> + Send
+ Sync
+ 'static,
{
fn config(
self,
f: impl FnOnce(&mut <<Param as SystemParam>::Fetch as SystemParamState>::Config),
) -> Self::System {
IntoSystem::into_system(self).config(f)
}
}
pub struct IsFunctionSystem; pub struct IsFunctionSystem;
impl<In, Out, Param, Marker, F> IntoSystem<In, Out, (IsFunctionSystem, Param, Marker)> for F impl<In, Out, Param, Marker, F> IntoSystem<In, Out, (IsFunctionSystem, Param, Marker)> for F
@ -489,7 +419,6 @@ where
FunctionSystem { FunctionSystem {
func, func,
param_state: None, param_state: None,
config: Some(<Param::Fetch as SystemParamState>::default_config()),
system_meta: SystemMeta::new::<F>(), system_meta: SystemMeta::new::<F>(),
marker: PhantomData, marker: PhantomData,
} }
@ -558,7 +487,6 @@ where
self.param_state = Some(<Param::Fetch as SystemParamState>::init( self.param_state = Some(<Param::Fetch as SystemParamState>::init(
world, world,
&mut self.system_meta, &mut self.system_meta,
self.config.take().unwrap(),
)); ));
} }

View File

@ -103,8 +103,8 @@ mod tests {
query::{Added, Changed, Or, QueryState, With, Without}, query::{Added, Changed, Or, QueryState, With, Without},
schedule::{Schedule, Stage, SystemStage}, schedule::{Schedule, Stage, SystemStage},
system::{ system::{
ConfigurableSystem, IntoExclusiveSystem, IntoSystem, Local, NonSend, NonSendMut, Query, IntoExclusiveSystem, IntoSystem, Local, NonSend, NonSendMut, Query, QuerySet,
QuerySet, RemovedComponents, Res, ResMut, System, SystemState, RemovedComponents, Res, ResMut, System, SystemState,
}, },
world::{FromWorld, World}, world::{FromWorld, World},
}; };
@ -525,21 +525,6 @@ mod tests {
assert_eq!(world.get_resource::<NSystems>().unwrap().0, 2); assert_eq!(world.get_resource::<NSystems>().unwrap().0, 2);
} }
#[test]
fn configure_system_local() {
let mut world = World::default();
world.insert_resource(false);
fn sys(local: Local<usize>, mut modified: ResMut<bool>) {
assert_eq!(*local, 42);
*modified = true;
}
run_system(&mut world, sys.config(|config| config.0 = Some(42)));
// ensure the system actually ran
assert!(*world.get_resource::<bool>().unwrap());
}
#[test] #[test]
fn world_collections_system() { fn world_collections_system() {
let mut world = World::default(); let mut world = World::default();

View File

@ -60,25 +60,11 @@ pub type SystemParamItem<'w, 's, P> = <<P as SystemParam>::Fetch as SystemParamF
/// Additionally, it is the implementor's responsibility to ensure there is no /// Additionally, it is the implementor's responsibility to ensure there is no
/// conflicting access across all [`SystemParam`]'s. /// conflicting access across all [`SystemParam`]'s.
pub unsafe trait SystemParamState: Send + Sync + 'static { pub unsafe trait SystemParamState: Send + Sync + 'static {
/// Values of this type can be used to adjust the behavior of the fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self;
/// system parameter. For instance, this can be used to pass
/// values from a `Plugin` to a `System`, or to control the
/// behavior of the `System`.
///
/// The default configuration of the parameter is set by
/// [`SystemParamState::default_config`]. To change it, invoke
/// [`FunctionSystem::config`](super::FunctionSystem::config) when
/// creating the system.
///
/// See [`FunctionSystem::config`](super::FunctionSystem::config)
/// for more information and examples.
type Config: Send + Sync;
fn init(world: &mut World, system_meta: &mut SystemMeta, config: Self::Config) -> Self;
#[inline] #[inline]
fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {} fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {}
#[inline] #[inline]
fn apply(&mut self, _world: &mut World) {} fn apply(&mut self, _world: &mut World) {}
fn default_config() -> Self::Config;
} }
/// A [`SystemParamFetch`] that only reads a given [`World`]. /// A [`SystemParamFetch`] that only reads a given [`World`].
@ -122,9 +108,7 @@ unsafe impl<Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParamState f
where where
F::Fetch: FilterFetch, F::Fetch: FilterFetch,
{ {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
let state = QueryState::new(world); let state = QueryState::new(world);
assert_component_access_compatibility( assert_component_access_compatibility(
&system_meta.name, &system_meta.name,
@ -149,8 +133,6 @@ where
.archetype_component_access .archetype_component_access
.extend(&self.archetype_component_access); .extend(&self.archetype_component_access);
} }
fn default_config() {}
} }
impl<'w, 's, Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParamFetch<'w, 's> impl<'w, 's, Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParamFetch<'w, 's>
@ -295,9 +277,7 @@ impl<'a, T: Resource> SystemParam for Res<'a, T> {
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
// conflicts with any prior access, a panic will occur. // conflicts with any prior access, a panic will occur.
unsafe impl<T: Resource> SystemParamState for ResState<T> { unsafe impl<T: Resource> SystemParamState for ResState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
let component_id = world.initialize_resource::<T>(); let component_id = world.initialize_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access_mut(); let combined_access = system_meta.component_access_set.combined_access_mut();
assert!( assert!(
@ -320,8 +300,6 @@ unsafe impl<T: Resource> SystemParamState for ResState<T> {
marker: PhantomData, marker: PhantomData,
} }
} }
fn default_config() {}
} }
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState<T> { impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState<T> {
@ -364,13 +342,9 @@ impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
unsafe impl<T: Resource> ReadOnlySystemParamFetch for OptionResState<T> {} unsafe impl<T: Resource> ReadOnlySystemParamFetch for OptionResState<T> {}
unsafe impl<T: Resource> SystemParamState for OptionResState<T> { unsafe impl<T: Resource> SystemParamState for OptionResState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self(ResState::init(world, system_meta))
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self(ResState::init(world, system_meta, ()))
} }
fn default_config() {}
} }
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState<T> { impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState<T> {
@ -407,9 +381,7 @@ impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
// conflicts with any prior access, a panic will occur. // conflicts with any prior access, a panic will occur.
unsafe impl<T: Resource> SystemParamState for ResMutState<T> { unsafe impl<T: Resource> SystemParamState for ResMutState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
let component_id = world.initialize_resource::<T>(); let component_id = world.initialize_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access_mut(); let combined_access = system_meta.component_access_set.combined_access_mut();
if combined_access.has_write(component_id) { if combined_access.has_write(component_id) {
@ -435,8 +407,6 @@ unsafe impl<T: Resource> SystemParamState for ResMutState<T> {
marker: PhantomData, marker: PhantomData,
} }
} }
fn default_config() {}
} }
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState<T> { impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState<T> {
@ -478,13 +448,9 @@ impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
} }
unsafe impl<T: Resource> SystemParamState for OptionResMutState<T> { unsafe impl<T: Resource> SystemParamState for OptionResMutState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self(ResMutState::init(world, system_meta))
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self(ResMutState::init(world, system_meta, ()))
} }
fn default_config() {}
} }
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState<T> { impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState<T> {
@ -519,17 +485,13 @@ unsafe impl ReadOnlySystemParamFetch for CommandQueue {}
// SAFE: only local state is accessed // SAFE: only local state is accessed
unsafe impl SystemParamState for CommandQueue { unsafe impl SystemParamState for CommandQueue {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Default::default() Default::default()
} }
fn apply(&mut self, world: &mut World) { fn apply(&mut self, world: &mut World) {
self.apply(world); self.apply(world);
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for CommandQueue { impl<'w, 's> SystemParamFetch<'w, 's> for CommandQueue {
@ -557,9 +519,7 @@ impl<'w, 's> SystemParam for &'w World {
} }
unsafe impl<'w, 's> SystemParamState for WorldState { unsafe impl<'w, 's> SystemParamState for WorldState {
type Config = (); fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
if !system_meta if !system_meta
@ -584,8 +544,6 @@ unsafe impl<'w, 's> SystemParamState for WorldState {
WorldState WorldState
} }
fn default_config() -> Self::Config {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for WorldState { impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
@ -626,6 +584,22 @@ impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
/// // Note how the read local is still 0 due to the locals not being shared. /// // Note how the read local is still 0 due to the locals not being shared.
/// assert_eq!(read_system.run((), world), 0); /// assert_eq!(read_system.run((), world), 0);
/// ``` /// ```
///
/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
/// To add configuration to a system, convert a capturing closure into the system instead:
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # use bevy_ecs::system::assert_is_system;
/// struct Config(u32);
/// struct Myu32Wrapper(u32);
/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<Myu32Wrapper>) {
/// move |mut val| val.0 = value.0
/// }
///
/// // .add_system(reset_to_system(my_config))
/// # assert_is_system(reset_to_system(Config(10)));
/// ```
pub struct Local<'a, T: Resource>(&'a mut T); pub struct Local<'a, T: Resource>(&'a mut T);
// SAFE: Local only accesses internal state // SAFE: Local only accesses internal state
@ -665,14 +639,8 @@ impl<'a, T: Resource + FromWorld> SystemParam for Local<'a, T> {
// SAFE: only local state is accessed // SAFE: only local state is accessed
unsafe impl<T: Resource + FromWorld> SystemParamState for LocalState<T> { unsafe impl<T: Resource + FromWorld> SystemParamState for LocalState<T> {
type Config = Option<T>; fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
Self(T::from_world(world))
fn init(world: &mut World, _system_meta: &mut SystemMeta, config: Self::Config) -> Self {
Self(config.unwrap_or_else(|| T::from_world(world)))
}
fn default_config() -> Option<T> {
None
} }
} }
@ -751,16 +719,12 @@ impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> {
// SAFE: no component access. removed component entity collections can be read in parallel and are // SAFE: no component access. removed component entity collections can be read in parallel and are
// never mutably borrowed during system execution // never mutably borrowed during system execution
unsafe impl<T: Component> SystemParamState for RemovedComponentsState<T> { unsafe impl<T: Component> SystemParamState for RemovedComponentsState<T> {
type Config = (); fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self { Self {
component_id: world.init_component::<T>(), component_id: world.init_component::<T>(),
marker: PhantomData, marker: PhantomData,
} }
} }
fn default_config() {}
} }
impl<'w, 's, T: Component> SystemParamFetch<'w, 's> for RemovedComponentsState<T> { impl<'w, 's, T: Component> SystemParamFetch<'w, 's> for RemovedComponentsState<T> {
@ -858,9 +822,7 @@ impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
// SAFE: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // SAFE: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
// NonSend conflicts with any prior access, a panic will occur. // NonSend conflicts with any prior access, a panic will occur.
unsafe impl<T: 'static> SystemParamState for NonSendState<T> { unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
system_meta.set_non_send(); system_meta.set_non_send();
let component_id = world.initialize_non_send_resource::<T>(); let component_id = world.initialize_non_send_resource::<T>();
@ -885,8 +847,6 @@ unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
marker: PhantomData, marker: PhantomData,
} }
} }
fn default_config() {}
} }
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState<T> { impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState<T> {
@ -931,13 +891,9 @@ impl<'w, T: 'static> SystemParam for Option<NonSend<'w, T>> {
unsafe impl<T: 'static> ReadOnlySystemParamFetch for OptionNonSendState<T> {} unsafe impl<T: 'static> ReadOnlySystemParamFetch for OptionNonSendState<T> {}
unsafe impl<T: 'static> SystemParamState for OptionNonSendState<T> { unsafe impl<T: 'static> SystemParamState for OptionNonSendState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self(NonSendState::init(world, system_meta))
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self(NonSendState::init(world, system_meta, ()))
} }
fn default_config() {}
} }
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendState<T> { impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendState<T> {
@ -975,9 +931,7 @@ impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
// SAFE: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // SAFE: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
// NonSendMut conflicts with any prior access, a panic will occur. // NonSendMut conflicts with any prior access, a panic will occur.
unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> { unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
system_meta.set_non_send(); system_meta.set_non_send();
let component_id = world.initialize_non_send_resource::<T>(); let component_id = world.initialize_non_send_resource::<T>();
@ -1005,8 +959,6 @@ unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
marker: PhantomData, marker: PhantomData,
} }
} }
fn default_config() {}
} }
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState<T> { impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState<T> {
@ -1049,13 +1001,9 @@ impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
} }
unsafe impl<T: 'static> SystemParamState for OptionNonSendMutState<T> { unsafe impl<T: 'static> SystemParamState for OptionNonSendMutState<T> {
type Config = (); fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self(NonSendMutState::init(world, system_meta))
fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self(NonSendMutState::init(world, system_meta, ()))
} }
fn default_config() {}
} }
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState<T> { impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState<T> {
@ -1094,13 +1042,9 @@ pub struct ArchetypesState;
// SAFE: no component value access // SAFE: no component value access
unsafe impl SystemParamState for ArchetypesState { unsafe impl SystemParamState for ArchetypesState {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self Self
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for ArchetypesState { impl<'w, 's> SystemParamFetch<'w, 's> for ArchetypesState {
@ -1129,13 +1073,9 @@ pub struct ComponentsState;
// SAFE: no component value access // SAFE: no component value access
unsafe impl SystemParamState for ComponentsState { unsafe impl SystemParamState for ComponentsState {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self Self
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for ComponentsState { impl<'w, 's> SystemParamFetch<'w, 's> for ComponentsState {
@ -1164,13 +1104,9 @@ pub struct EntitiesState;
// SAFE: no component value access // SAFE: no component value access
unsafe impl SystemParamState for EntitiesState { unsafe impl SystemParamState for EntitiesState {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self Self
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for EntitiesState { impl<'w, 's> SystemParamFetch<'w, 's> for EntitiesState {
@ -1199,13 +1135,9 @@ pub struct BundlesState;
// SAFE: no component value access // SAFE: no component value access
unsafe impl SystemParamState for BundlesState { unsafe impl SystemParamState for BundlesState {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self Self
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for BundlesState { impl<'w, 's> SystemParamFetch<'w, 's> for BundlesState {
@ -1239,13 +1171,9 @@ impl SystemParam for SystemChangeTick {
pub struct SystemChangeTickState {} pub struct SystemChangeTickState {}
unsafe impl SystemParamState for SystemChangeTickState { unsafe impl SystemParamState for SystemChangeTickState {
type Config = (); fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
fn init(_world: &mut World, _system_meta: &mut SystemMeta, _config: Self::Config) -> Self {
Self {} Self {}
} }
fn default_config() {}
} }
impl<'w, 's> SystemParamFetch<'w, 's> for SystemChangeTickState { impl<'w, 's> SystemParamFetch<'w, 's> for SystemChangeTickState {
@ -1295,11 +1223,9 @@ macro_rules! impl_system_param_tuple {
/// SAFE: implementors of each `SystemParamState` in the tuple have validated their impls /// SAFE: implementors of each `SystemParamState` in the tuple have validated their impls
#[allow(non_snake_case)] #[allow(non_snake_case)]
unsafe impl<$($param: SystemParamState),*> SystemParamState for ($($param,)*) { unsafe impl<$($param: SystemParamState),*> SystemParamState for ($($param,)*) {
type Config = ($(<$param as SystemParamState>::Config,)*);
#[inline] #[inline]
fn init(_world: &mut World, _system_meta: &mut SystemMeta, config: Self::Config) -> Self { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
let ($($param,)*) = config; (($($param::init(_world, _system_meta),)*))
(($($param::init(_world, _system_meta, $param),)*))
} }
#[inline] #[inline]
@ -1313,11 +1239,6 @@ macro_rules! impl_system_param_tuple {
let ($($param,)*) = self; let ($($param,)*) = self;
$($param.apply(_world);)* $($param.apply(_world);)*
} }
#[allow(clippy::unused_unit)]
fn default_config() -> ($(<$param as SystemParamState>::Config,)*) {
($(<$param as SystemParamState>::default_config(),)*)
}
} }
}; };
} }