diff options
Diffstat (limited to 'ecs/src/system/stateful.rs')
-rw-r--r-- | ecs/src/system/stateful.rs | 127 |
1 files changed, 126 insertions, 1 deletions
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index 7b2b608..e74ef31 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -1,10 +1,18 @@ +use std::mem::transmute; use std::panic::{RefUnwindSafe, UnwindSafe}; use seq_macro::seq; use crate::component::local::SystemWithLocalComponents; use crate::component::Parts as ComponentParts; +use crate::event::Emitted as EmittedEvent; use crate::system::initializable::{Initializable, MaybeInitializableParamTuple}; +use crate::system::observer::{ + Observe, + Observed, + Observer, + WrapperComponent as ObserverWrapperComponent, +}; use crate::system::{Into as IntoSystem, Metadata, Param, System, TypeErased}; use crate::World; @@ -68,9 +76,10 @@ macro_rules! impl_system { } } - impl<Func, #(TParam~I,)*> IntoSystem<fn(#(TParam~I,)*)> + impl<'world, Func, #(TParam~I,)*> IntoSystem<'world, fn(#(TParam~I,)*)> for Func where + #(TParam~I: Param<'world>,)* Func: Fn(#(TParam~I,)*) + Copy + 'static, { type System = Stateful<Func>; @@ -123,3 +132,119 @@ fn init_initializable_params<'world, SystemT, Params>( { Params::init_initializable(system, inputs); } + +macro_rules! impl_observer { + ($c: tt) => { + seq!(I in 0..$c { + impl<'world, ObservedT, Func, #(TParam~I,)*> System< + 'world, + fn(Observe<'world, ObservedT>, #(TParam~I,)*) + > for Stateful<Func> + where + ObservedT: Observed, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + #(TParam~I: Param<'world>,)* + { + type Callbacks = Callbacks; + + fn finish(self) -> (TypeErased, Callbacks) + { + unimplemented!(); + } + } + + impl<'world, ObservedT, Func, #(TParam~I,)*> Initializable< + 'world, + fn(Observe<'world, ObservedT>, #(TParam~I,)*) + > for Stateful<Func> + where + ObservedT: Observed, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + #(TParam~I: Param<'world>,)* + (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> + { + type Inputs = < + (#(TParam~I,)*) as MaybeInitializableParamTuple<'world, Self> + >::Inputs; + + fn initialize(mut self, inputs: Self::Inputs) -> Self + { + init_initializable_params::<_, (#(TParam~I,)*)>(&mut self, inputs); + + self + } + } + + impl<'world, ObservedT, Func, #(TParam~I,)*> Observer< + 'world, + fn(Observe<'world, ObservedT>, #(TParam~I,)*) + > for Stateful<Func> + where + ObservedT: Observed, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + #(TParam~I: Param<'world>,)* + { + type ObservedEvents = ObservedT::Events; + + fn observed_events() -> Self::ObservedEvents + { + ObservedT::events() + } + + fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks) + { + let Self { func, local_components } = self; + + let callbacks = Callbacks { local_components }; + + let wrapper_comp = ObserverWrapperComponent::new( + move |world, metadata, emitted_event| { + // SAFETY: The caller of TypeErased::run ensures the lifetime + // is correct + let world = unsafe { &*std::ptr::from_ref(world) }; + + // SAFETY: The caller of TypeErased::run ensures the lifetime + // is correct + let emitted_event = unsafe { + transmute::<EmittedEvent<'_>, EmittedEvent<'_>>( + emitted_event + ) + }; + + func(Observe::new(world, emitted_event), #({ + TParam~I::new(world, &metadata) + },)*); + }, + ); + + (wrapper_comp, callbacks) + } + } + + impl<'world, Func, ObservedT, #(TParam~I,)*> IntoSystem< + 'world, + fn(Observe<'world, ObservedT>, + #(TParam~I,)*) + > for Func + where + ObservedT: Observed, + #(TParam~I: Param<'world>,)* + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + { + type System = Stateful<Func>; + + fn into_system(self) -> Stateful<Func> + { + Stateful { + func: self, + local_components: Vec::new(), // TODO: Use Vec::with_capacity + } + } + } + }); + }; +} + +seq!(C in 1..16 { + impl_observer!(C); +}); |