Skip to content

System param config #19208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
}
}

fn configurate(state: &mut Self::State, meta: &mut #path::system::SystemMeta, config: &mut dyn core::any::Any) {
<#fields_alias::<'_, '_, #punctuated_generic_idents> as #path::system::SystemParam>::configurate(&mut state.state, meta, config)
}

fn apply(state: &mut Self::State, system_meta: &#path::system::SystemMeta, world: &mut #path::world::World) {
<#fields_alias::<'_, '_, #punctuated_generic_idents> as #path::system::SystemParam>::apply(&mut state.state, system_meta, world);
}
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_ecs/src/system/adapter_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ where
self.system.initialize(world);
}

#[inline]
fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.system.configurate(config);
}

fn check_change_tick(&mut self, change_tick: crate::component::Tick) {
self.system.check_change_tick(change_tick);
}
Expand Down
11 changes: 11 additions & 0 deletions crates/bevy_ecs/src/system/combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ where
.extend(self.b.component_access_set().clone());
}

#[inline]
fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.a.configurate(config);
self.b.configurate(config);
}

fn check_change_tick(&mut self, change_tick: Tick) {
self.a.check_change_tick(change_tick);
self.b.check_change_tick(change_tick);
Expand Down Expand Up @@ -434,6 +440,11 @@ where
.extend(self.b.component_access_set().clone());
}

fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.a.configurate(config);
self.b.configurate(config);
}

fn check_change_tick(&mut self, change_tick: Tick) {
self.a.check_change_tick(change_tick);
self.b.check_change_tick(change_tick);
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,12 @@ where
fn set_last_run(&mut self, last_run: Tick) {
self.system_meta.last_run = last_run;
}

#[inline]
fn configurate(&mut self, config: &mut dyn core::any::Any) {
let param_state = &mut self.state.as_mut().expect(Self::ERROR_UNINITIALIZED).param;
F::Param::configurate(param_state, &mut self.system_meta, config);
}
}

/// SAFETY: `F`'s param is [`ReadOnlySystemParam`], so this system will only read from the world.
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_ecs/src/system/observer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ where
fn default_system_sets(&self) -> Vec<crate::schedule::InternedSystemSet> {
self.observer.default_system_sets()
}

#[inline]
fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.observer.configurate(config);
}
}

#[cfg(test)]
Expand Down
13 changes: 13 additions & 0 deletions crates/bevy_ecs/src/system/schedule_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ impl<S: System<In = ()>> System for InfallibleSystemWrapper<S> {
self.0.initialize(world);
}

#[inline]
fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.0.configurate(config);
}

#[inline]
fn check_change_tick(&mut self, change_tick: Tick) {
self.0.check_change_tick(change_tick);
Expand Down Expand Up @@ -216,6 +221,10 @@ where
fn set_last_run(&mut self, last_run: Tick) {
self.system.set_last_run(last_run);
}

fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.system.configurate(config);
}
}

/// Constructed in [`IntoSystem::with_input_from`].
Expand Down Expand Up @@ -326,6 +335,10 @@ where
fn set_last_run(&mut self, last_run: Tick) {
self.system.set_last_run(last_run);
}

fn configurate(&mut self, config: &mut dyn core::any::Any) {
self.system.configurate(config);
}
}

/// Type alias for a `BoxedSystem` that a `Schedule` can store.
Expand Down
8 changes: 7 additions & 1 deletion crates/bevy_ecs/src/system/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
clippy::module_inception,
reason = "This instance of module inception is being discussed; see #17353."
)]
use core::fmt::Debug;
use core::{any::Any, fmt::Debug};
use log::warn;
use thiserror::Error;

Expand Down Expand Up @@ -145,6 +145,12 @@ pub trait System: Send + Sync + 'static {
/// Initialize the system.
fn initialize(&mut self, _world: &mut World);

/// Provides a mechanism for custom system implementations to interact with custom schedule build passes.
///
/// Implementations **must** ensure that if the provided `config` argument cannot be downcasted to the
/// expected type, the function behaves as a no-op.
fn configurate(&mut self, _config: &mut dyn Any) {}

/// Checks any [`Tick`]s stored on this system and wraps their value if they get too old.
///
/// This method must be called periodically to ensure that change detection behaves correctly.
Expand Down
48 changes: 48 additions & 0 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ pub unsafe trait SystemParam: Sized {
/// and creates a new instance of this param's [`State`](SystemParam::State).
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State;

/// Configurate the system param.
/// This method will be called by [`System::configurate`](super::System::configurate) in order for all [`SystemParam`]s of a system.
/// Implementations should respond to configs that they recognize by calling `downcast_mut`
fn configurate(_state: &mut Self::State, _meta: &mut SystemMeta, _config: &mut dyn Any) {}

/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
///
Expand Down Expand Up @@ -658,6 +663,18 @@ macro_rules! impl_param_set {
($($param,)*)
}

#[expect(
clippy::allow_attributes,
reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
)]
#[allow(
non_snake_case,
reason = "Certain variable names are provided by the caller, not by us."
)]
fn configurate(($($param,)*): &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
($($param::configurate($param, meta, config),)*);
}

fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
<($($param,)*) as SystemParam>::apply(state, system_meta, world);
}
Expand Down Expand Up @@ -1655,6 +1672,10 @@ unsafe impl<T: SystemParam> SystemParam for Option<T> {
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
T::queue(state, system_meta, world);
}

fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
T::configurate(state, meta, config);
}
}

// SAFETY: Delegates to `T`, which ensures the safety requirements are met
Expand Down Expand Up @@ -1688,6 +1709,9 @@ unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
T::queue(state, system_meta, world);
}
fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
T::configurate(state, meta, config);
}
}

// SAFETY: Delegates to `T`, which ensures the safety requirements are met
Expand Down Expand Up @@ -1785,6 +1809,9 @@ unsafe impl<T: SystemParam> SystemParam for When<T> {
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
T::queue(state, system_meta, world);
}
fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
T::configurate(state, meta, config);
}
}

// SAFETY: Delegates to `T`, which ensures the safety requirements are met
Expand Down Expand Up @@ -1841,6 +1868,12 @@ unsafe impl<T: SystemParam> SystemParam for Vec<T> {
T::queue(state, system_meta, world.reborrow());
}
}

fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
for state in state {
T::configurate(state, meta, config);
}
}
}

// SAFETY: When initialized with `init_state`, `get_param` returns an empty `Vec` and does no access.
Expand Down Expand Up @@ -1881,6 +1914,12 @@ unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {
T::queue(state, system_meta, world.reborrow());
}
}

fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
for state in state {
T::configurate(state, meta, config);
}
}
}

impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
Expand Down Expand Up @@ -1944,6 +1983,11 @@ macro_rules! impl_system_param_tuple {
(($($param::init_state(world, system_meta),)*))
}

#[inline]
fn configurate(($($param,)*): &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
(($($param::configurate($param, meta, config),)*));
}

#[inline]
fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
$($param::apply($param, system_meta, world);)*
Expand Down Expand Up @@ -2113,6 +2157,10 @@ unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_,
P::init_state(world, system_meta)
}

fn configurate(state: &mut Self::State, meta: &mut SystemMeta, config: &mut dyn Any) {
P::configurate(state, meta, config);
}

fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
P::apply(state, system_meta, world);
}
Expand Down