use std::{
collections::HashMap,
any::{Any, TypeId},
};
use crate::entity::Entities;
#[derive(Default)]
pub struct Events {
channels: HashMap<TypeId, Box<dyn ErasedEventChannel>>,
}
impl Events {
pub fn register<TEvent, TEventHandler>(&mut self, handler: TEventHandler)
where
TEvent: 'static,
TEventHandler: EventHandler<TEvent> + 'static,
{
let id = TypeId::of::<TEvent>();
self.channels
.entry(id)
.or_insert(EventChannel::<TEvent>::new_box())
.as_any_mut()
.downcast_mut::<EventChannel<TEvent>>()
.map(|c| c.register(handler));
}
pub fn trigger<TEvent>(&self, event: &TEvent, entities: &mut Entities)
where
TEvent: 'static,
{
let id = TypeId::of::<TEvent>();
self.channels
.get(&id)
.map(|c| c.as_any())
.and_then(|c| c.downcast_ref::<EventChannel<TEvent>>())
.map(|c| c.trigger(event, entities));
}
}
pub trait EventHandler<T> {
fn trigger(&self, event: &T, entities: &mut Entities);
}
impl<TFunc, TEvent> EventHandler<TEvent> for TFunc
where
TFunc: Fn(&TEvent, &mut Entities),
{
fn trigger(&self, event: &TEvent, entities: &mut Entities) {
self(event, entities)
}
}
struct EventChannel<T> {
handlers: Vec<Box<dyn EventHandler<T>>>,
}
impl<T> EventChannel<T> {
pub fn new() -> Self {
let handlers = vec![];
Self { handlers }
}
pub fn new_box() -> Box<Self> {
let this = Self::new();
Box::new(this)
}
pub fn register<TEventHandler>(&mut self, handler: TEventHandler)
where
TEventHandler: EventHandler<T> + 'static,
{
let handler = Box::new(handler);
self.handlers.push(handler);
}
pub fn trigger(&self, event: &T, entities: &mut Entities) {
self.handlers
.iter()
.for_each(|h| h.trigger(event, entities))
}
}
trait ErasedEventChannel {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T> ErasedEventChannel for EventChannel<T>
where
T: 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}