engine/ecs/src/events.rs
2025-02-26 12:22:32 +01:00

88 lines
2.4 KiB
Rust

use std::{
any::{Any, TypeId},
collections::HashMap,
ops::DerefMut,
sync::Arc,
};
use crate::World;
pub struct Events {
events: HashMap<
TypeId, // TypeId of Payload
(
Vec<Box<dyn Any + Send + Sync>>, // Payload
Vec<Arc<dyn Fn(&mut World, &dyn Any) -> anyhow::Result<()> + Send + Sync>>, // Listener on Payload
),
>,
}
impl Default for Events {
fn default() -> Self {
Self {
events: HashMap::new(),
}
}
}
impl Events {
pub(crate) fn take_events(&mut self) -> Self {
Self {
events: self
.events
.iter_mut()
.filter_map(|(type_id, (payload, listener))| {
(!payload.is_empty())
.then(|| (*type_id, (std::mem::take(payload), listener.clone())))
})
.collect(),
}
}
pub fn clear(&mut self) {
for (payloads, listener) in self.events.values_mut() {
payloads.clear();
listener.clear();
}
}
pub fn register_event<T: Any + Send + Sync>(&mut self) {
self.events
.insert(TypeId::of::<T>(), (Vec::new(), Vec::new()));
}
pub fn add_reader<T: Any + Send + Sync, F>(&mut self, f: F)
where
F: Fn(&mut World, &T) -> anyhow::Result<()> + Send + Sync + 'static,
{
match self.events.get_mut(&TypeId::of::<T>()) {
Some((_, listener)) => listener.push(Arc::new(move |world, payload| {
let typed_payload: &T = payload.downcast_ref().unwrap();
f(world, typed_payload)
})),
None => panic!("register event type first!"),
}
}
pub fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
match self.events.get_mut(&TypeId::of::<T>()) {
Some((payloads, _)) => payloads.push(Box::new(payload)),
None => panic!("register event type first!"),
}
}
pub(crate) fn fire_events(&mut self, world: &mut World) -> anyhow::Result<()> {
for (payloads, listeners) in self.events.values_mut() {
for payload in payloads.iter_mut() {
for listener in listeners.iter_mut() {
(listener)(world, payload.deref_mut())?;
}
}
payloads.clear();
}
Ok(())
}
}