use std::any::type_name; use std::fmt::Debug; use std::marker::PhantomData; use std::mem::transmute; use std::slice::Iter as SliceIter; use seq_macro::seq; use crate::entity::Handle as EntityHandle; use crate::event::Emitted as EmittedEvent; use crate::pair::Pair; use crate::system::{ Callbacks, NoCallbacks, Param, ReturnValue as SystemReturnValue, TypeErased as TypeErasedSystem, }; use crate::uid::Uid; use crate::util::Array; use crate::{Component, 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::builder() .relation::() .target::() .build()] } } /// Observer system. pub trait Observer<'world, Impl> { type Callbacks: Callbacks; type ObservedEvents: Array>; fn observed_events() -> Self::ObservedEvents; fn finish_observer(self) -> (TypeErasedSystem, 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<'_, ObservedT> { ObserveIter { world: self.world, inner: self.emitted_event.match_ids.iter(), _pd: PhantomData, } } } impl<'a, ObservedT: Observed> IntoIterator for &'a Observe<'_, ObservedT> { type IntoIter = ObserveIter<'a, ObservedT>; type Item = ::Item; fn into_iter(self) -> Self::IntoIter { self.iter() } } pub struct ObserveIter<'observe, ObservedT: Observed> { world: &'observe World, inner: SliceIter<'observe, Uid>, _pd: PhantomData, } impl<'observe, ObservedT: Observed> Iterator for ObserveIter<'observe, ObservedT> { type Item = EventMatch<'observe, ObservedT>; fn next(&mut self) -> Option { let match_id = *self.inner.next()?; Some(EventMatch { world: self.world, id: match_id, _pd: PhantomData, }) } } /// A event match. #[derive(Debug)] pub struct EventMatch<'world, ObservedT: Observed> { world: &'world World, id: Uid, _pd: PhantomData, } impl<'world, ObservedT: Observed> EventMatch<'world, ObservedT> { #[must_use] pub fn entity_id(&self) -> Uid { self.id } /// Attempts to get the entity with the id of this match. #[must_use] pub fn try_get_entity(&self) -> Option> { self.world.get_entity(self.id) } } macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { 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 + Copy + 'static, Ret: SystemReturnValue, #(TParam~I: Param<'world, Input = ()>,)* { type Callbacks = NoCallbacks; type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents { ObservedT::events() } fn finish_observer(self) -> (TypeErasedSystem, NoCallbacks) { #![allow(unused)] crate::util::const_assert!( size_of::() == 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 { transmute::, EmittedEvent<'_>>( emitted_event ) }; let func = unsafe { std::mem::zeroed::() }; func(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) },)*).into_result() }, name: type_name::() }; (system, NoCallbacks) } } }); }; } seq!(C in 0..16 { impl_observer!(C); });