diff options
Diffstat (limited to 'engine-ecs/src/system/observer.rs')
| -rw-r--r-- | engine-ecs/src/system/observer.rs | 107 |
1 files changed, 24 insertions, 83 deletions
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>; |
