use std::fmt::Debug; use std::marker::PhantomData; use std::mem::transmute; use std::slice::Iter as SliceIter; use ecs_macros::Component; use seq_macro::seq; use crate::component::Component; use crate::entity::Handle as EntityHandle; use crate::event::Emitted as EmittedEvent; use crate::pair::Pair; use crate::system::{ Metadata, NoCallbacks, Param, System, TypeErased as TypeErasedSystem, }; use crate::uid::Uid; use crate::util::Array; use crate::World; pub trait Observed { type Events: Array>; fn events() -> Self::Events; } impl Observed for Pair where Relation: Component, Target: Component, { type Events = [Pair; 1]; fn events() -> Self::Events { [Pair::new::(Target::id())] } } /// Observer system. pub trait Observer<'world, Impl>: System<'world, Impl> { type ObservedEvents: Array>; fn observed_events() -> Self::ObservedEvents; fn finish_observer(self) -> (WrapperComponent, Self::Callbacks); } pub struct Observe<'world, ObservedT: Observed> { _pd: PhantomData, world: &'world World, emitted_event: EmittedEvent<'world>, } impl<'world, ObservedT: Observed> Observe<'world, ObservedT> { pub fn new(world: &'world World, emitted_event: EmittedEvent<'world>) -> Self { Self { _pd: PhantomData, world, emitted_event, } } #[must_use] pub fn event(&self) -> Uid { self.emitted_event.event } } impl Observe<'_, ObservedT> { #[must_use] pub fn iter(&self) -> ObserveIter<'_> { ObserveIter { world: self.world, inner: self.emitted_event.match_ids.iter(), } } } impl<'a, ObservedT: Observed> IntoIterator for &'a Observe<'_, ObservedT> { type IntoIter = ObserveIter<'a>; type Item = EntityHandle<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } pub struct ObserveIter<'observe> { world: &'observe World, inner: SliceIter<'observe, Uid>, } impl<'observe> Iterator for ObserveIter<'observe> { type Item = EntityHandle<'observe>; fn next(&mut self) -> Option { let target = *self.inner.next()?; self.world.get_entity(target) } } 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 Func where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world, Input = ()>,)* { type Callbacks = NoCallbacks; fn finish(self) -> (TypeErasedSystem, NoCallbacks) { unimplemented!(); } } impl<'world, ObservedT, Func, #(TParam~I,)*> Observer< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) > for Func where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world, Input = ()>,)* { type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents { ObservedT::events() } fn finish_observer(self) -> (WrapperComponent, NoCallbacks) { let wrapper_comp = WrapperComponent { run: Box::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<'_>>( emitted_event ) }; self(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) },)*); }), }; (wrapper_comp, NoCallbacks) } } }); }; } seq!(C in 1..16 { impl_observer!(C); }); impl<'world, ObservedT, Func> System<'world, fn(Observe<'world, ObservedT>)> for Func where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>) + Copy + 'static, { type Callbacks = NoCallbacks; fn finish(self) -> (TypeErasedSystem, NoCallbacks) { const { panic!("Observers cannot be used as regular systems"); } } } impl<'world, ObservedT, Func> Observer<'world, fn(Observe<'world, ObservedT>)> for Func where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>) + Copy + 'static, { type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents { ObservedT::events() } fn finish_observer(self) -> (WrapperComponent, NoCallbacks) { let wrapper_comp = WrapperComponent { run: Box::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<'_>>(emitted_event) }; self(Observe::new(world, emitted_event)); }), }; (wrapper_comp, NoCallbacks) } } #[derive(Component)] pub struct WrapperComponent { run: Box, } impl WrapperComponent { pub fn new(run: impl Fn(&World, Metadata, EmittedEvent<'_>) + 'static) -> Self { Self { run: Box::new(run) } } /// 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<'_>, ) { (self.run)(world, metadata, emitted_event); } } 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<'_>);