diff options
Diffstat (limited to 'engine-ecs/src/system')
| -rw-r--r-- | engine-ecs/src/system/initializable.rs | 4 | ||||
| -rw-r--r-- | engine-ecs/src/system/observer.rs | 107 | ||||
| -rw-r--r-- | engine-ecs/src/system/stateful.rs | 86 |
3 files changed, 67 insertions, 130 deletions
diff --git a/engine-ecs/src/system/initializable.rs b/engine-ecs/src/system/initializable.rs index b6ec8e8..fa925e0 100644 --- a/engine-ecs/src/system/initializable.rs +++ b/engine-ecs/src/system/initializable.rs @@ -2,11 +2,11 @@ use std::marker::PhantomData; use seq_macro::seq; -use crate::system::{Input, Param as SystemParam, System}; +use crate::system::{Input, Param as SystemParam}; use crate::tuple::{Reduce as TupleReduce, ReduceElement as TupleReduceElement, Tuple}; /// A initializable system. -pub trait Initializable<'world, Impl>: System<'world, Impl> +pub trait Initializable<'world, Impl> { type Inputs; diff --git a/engine-ecs/src/system/observer.rs b/engine-ecs/src/system/observer.rs index 1ad7496..e5345cd 100644 --- a/engine-ecs/src/system/observer.rs +++ b/engine-ecs/src/system/observer.rs @@ -7,15 +7,13 @@ use std::slice::Iter as SliceIter; use seq_macro::seq; use crate::entity::Handle as EntityHandle; -use crate::error::Error; use crate::event::Emitted as EmittedEvent; use crate::pair::Pair; use crate::system::{ - Metadata, + Callbacks, NoCallbacks, Param, ReturnValue as SystemReturnValue, - System, TypeErased as TypeErasedSystem, }; use crate::uid::Uid; @@ -46,13 +44,14 @@ where } /// Observer system. -pub trait Observer<'world, Impl>: System<'world, Impl> +pub trait Observer<'world, Impl> { + type Callbacks: Callbacks; type ObservedEvents: Array<Pair<Uid, Uid>>; fn observed_events() -> Self::ObservedEvents; - fn finish_observer(self) -> (WrapperComponent, Self::Callbacks); + fn finish_observer(self) -> (TypeErasedSystem, Self::Callbacks); } pub struct Observe<'world, ObservedT: Observed> @@ -155,36 +154,17 @@ impl<'world, ObservedT: Observed> EventMatch<'world, ObservedT> macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { - impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System< - 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret - > for Func - where - ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, - Ret: SystemReturnValue, - #(TParam~I: Param<'world, Input = ()>,)* - { - type Callbacks = NoCallbacks; - - fn finish(self) -> (TypeErasedSystem, NoCallbacks) - { - const { - panic!("Observers cannot be used as regular systems"); - } - } - } - impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Observer< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Func where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static, Ret: SystemReturnValue, #(TParam~I: Param<'world, Input = ()>,)* { + type Callbacks = NoCallbacks; type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents @@ -192,16 +172,24 @@ macro_rules! impl_observer { ObservedT::events() } - fn finish_observer(self) -> (WrapperComponent, NoCallbacks) + fn finish_observer(self) -> (TypeErasedSystem, NoCallbacks) { - #[allow(unused)] + #![allow(unused)] - let wrapper_comp = WrapperComponent::new( - move |world, metadata, emitted_event| { + crate::util::const_assert!( + size_of::<Func>() == 0, + "System function is not zero-sized (not function pointer)" + ); + + let system = TypeErasedSystem { + run: |world, metadata, emitted_event| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; + let emitted_event = + emitted_event.expect("No event info passed to observer"); + // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let emitted_event = unsafe { @@ -210,14 +198,16 @@ macro_rules! impl_observer { ) }; - self(Observe::new(world, emitted_event), #({ + let func = unsafe { std::mem::zeroed::<Func>() }; + + func(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) },)*).into_result() }, - type_name::<Func>() - ); + name: type_name::<Func>() + }; - (wrapper_comp, NoCallbacks) + (system, NoCallbacks) } } }); @@ -227,52 +217,3 @@ macro_rules! impl_observer { seq!(C in 0..16 { impl_observer!(C); }); - -#[derive(Component)] -pub struct WrapperComponent -{ - run: Box<RunFn>, - name: &'static str, -} - -impl WrapperComponent -{ - pub fn new( - run: impl Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error> + 'static, - name: &'static str, - ) -> Self - { - Self { run: Box::new(run), name } - } - - /// Runs the observer system. - /// - /// # Safety - /// `world` must live at least as long as the [`World`] the system belongs to. - pub unsafe fn run( - &self, - world: &World, - metadata: Metadata, - emitted_event: EmittedEvent<'_>, - ) -> Result<(), Error> - { - (self.run)(world, metadata, emitted_event) - } - - pub fn name(&self) -> &'static str - { - self.name - } -} - -impl Debug for WrapperComponent -{ - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - formatter - .debug_struct("WrapperComponent") - .finish_non_exhaustive() - } -} - -type RunFn = dyn Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error>; diff --git a/engine-ecs/src/system/stateful.rs b/engine-ecs/src/system/stateful.rs index b73baeb..c9354c3 100644 --- a/engine-ecs/src/system/stateful.rs +++ b/engine-ecs/src/system/stateful.rs @@ -1,4 +1,5 @@ use std::any::type_name; +use std::marker::PhantomData; use std::mem::transmute; use seq_macro::seq; @@ -7,12 +8,7 @@ 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::observer::{Observe, Observed, Observer}; use crate::system::{ Into as IntoSystem, Metadata, @@ -24,10 +20,10 @@ use crate::system::{ use crate::World; /// A stateful system. -pub struct Stateful<Func> +pub struct Stateful<Func: Copy + 'static> { - func: Func, local_components: Vec<ComponentParts>, + _pd: PhantomData<Func>, } macro_rules! impl_system { @@ -36,7 +32,7 @@ macro_rules! impl_system { impl<'world, Func, Ret, #(TParam~I,)*> System<'world, fn(#(TParam~I,)*) -> Ret> for Stateful<Func> where - Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world, Input: 'static>,)* { @@ -44,22 +40,29 @@ macro_rules! impl_system { fn finish(self) -> (TypeErased, Self::Callbacks) { - let Self { func, local_components } = self; + crate::util::const_assert!( + size_of::<Func>() == 0, + "System function is not zero-sized (not function pointer)" + ); + + let Self { local_components, .. } = self; let callbacks = Callbacks { local_components }; let type_erased = TypeErased { - run: Box::new(move |world, metadata| { + run: |world, metadata, _| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; + let func = unsafe { std::mem::zeroed::<Func>() }; + func(#({ TParam~I::new(&world, &metadata) },)*); Ok(()) - }), + }, name: type_name::<Func>() }; @@ -71,7 +74,7 @@ macro_rules! impl_system { impl<'world, Func, Ret, #(TParam~I,)*> Initializable<'world, fn(#(TParam~I,)*) -> Ret> for Stateful<Func> where - Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world, Input: 'static>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> @@ -91,7 +94,7 @@ macro_rules! impl_system { impl<'world, Func, Ret, #(TParam~I,)*> IntoSystem<'world, fn(#(TParam~I,)*) -> Ret> for Func where - Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world>,)* { @@ -100,8 +103,8 @@ macro_rules! impl_system { fn into_system(self) -> Self::System { Self::System { - func: self, local_components: Vec::new(), // TODO: Use Vec::with_capacity + _pd: PhantomData } } } @@ -113,7 +116,7 @@ seq!(C in 1..16 { impl_system!(C); }); -impl<Func> SystemWithLocalComponents for Stateful<Func> +impl<Func: Copy + 'static> SystemWithLocalComponents for Stateful<Func> { fn add_local_component(&mut self, component_parts: ComponentParts) { @@ -149,31 +152,13 @@ fn init_initializable_params<'world, SystemT, Params>( macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { - impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System< - 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret - > for Stateful<Func> - where - ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, - Ret: ReturnValue, - #(TParam~I: Param<'world>,)* - { - type Callbacks = Callbacks; - - fn finish(self) -> (TypeErased, Callbacks) - { - unimplemented!(); - } - } - impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Initializable< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Stateful<Func> where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> @@ -196,10 +181,11 @@ macro_rules! impl_observer { > for Stateful<Func> where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world>,)* { + type Callbacks = Callbacks; type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents @@ -207,20 +193,28 @@ macro_rules! impl_observer { ObservedT::events() } - fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks) + fn finish_observer(self) -> (TypeErased, Callbacks) { #![allow(unused)] - let Self { func, local_components } = self; + crate::util::const_assert!( + size_of::<Func>() == 0, + "System function is not zero-sized (not function pointer)" + ); + + let Self { local_components, .. } = self; let callbacks = Callbacks { local_components }; - let wrapper_comp = ObserverWrapperComponent::new( - move |world, metadata, emitted_event| { + let system = TypeErased { + run: |world, metadata, emitted_event| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; + let emitted_event = + emitted_event.expect("No event info passed to observer"); + // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let emitted_event = unsafe { @@ -229,14 +223,16 @@ macro_rules! impl_observer { ) }; + let func = unsafe { std::mem::zeroed::<Func>() }; + func(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) },)*).into_result() }, - type_name::<Func>() - ); + name: type_name::<Func>() + }; - (wrapper_comp, callbacks) + (system, callbacks) } } @@ -246,7 +242,7 @@ macro_rules! impl_observer { > for Func where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static, Ret: ReturnValue, #(TParam~I: Param<'world>,)* { @@ -255,8 +251,8 @@ macro_rules! impl_observer { fn into_system(self) -> Stateful<Func> { Stateful { - func: self, local_components: Vec::new(), // TODO: Use Vec::with_capacity + _pd: PhantomData } } } |
