Also create generic event system
This commit is contained in:
parent
ca4a040d20
commit
0113a68914
4 changed files with 63 additions and 17 deletions
|
@ -8,7 +8,7 @@ use std::{
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
pub struct Events {
|
pub struct Events {
|
||||||
events: HashMap<
|
pub(crate) events: HashMap<
|
||||||
TypeId, // TypeId of Payload
|
TypeId, // TypeId of Payload
|
||||||
(
|
(
|
||||||
Vec<Box<dyn Any + Send + Sync>>, // Payload
|
Vec<Box<dyn Any + Send + Sync>>, // Payload
|
||||||
|
@ -51,20 +51,6 @@ impl Events {
|
||||||
.insert(TypeId::of::<T>(), (Vec::new(), Vec::new()));
|
.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) {
|
pub fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
|
||||||
match self.events.get_mut(&TypeId::of::<T>()) {
|
match self.events.get_mut(&TypeId::of::<T>()) {
|
||||||
Some((payloads, _)) => payloads.push(Box::new(payload)),
|
Some((payloads, _)) => payloads.push(Box::new(payload)),
|
||||||
|
@ -93,3 +79,10 @@ impl Events {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait EventReader<P, T, R, Func, Filter>
|
||||||
|
where
|
||||||
|
P: Any + Send + Sync,
|
||||||
|
{
|
||||||
|
fn add_reader(&mut self, func: Func);
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ mod updates;
|
||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
pub use crate::entity::{Entity, EntityComponentDisjointMut, EntityNotFoundError, EntityObject};
|
pub use crate::entity::{Entity, EntityComponentDisjointMut, EntityNotFoundError, EntityObject};
|
||||||
pub use crate::events::Events;
|
pub use crate::events::{EventReader, Events};
|
||||||
pub use crate::resources::Resources;
|
pub use crate::resources::Resources;
|
||||||
pub use crate::type_map::{
|
pub use crate::type_map::{
|
||||||
ComponentCreateInfo, ComponentDebug, ComponentNotFoundError, EntityComponent, TypeMap,
|
ComponentCreateInfo, ComponentDebug, ComponentNotFoundError, EntityComponent, TypeMap,
|
||||||
|
|
|
@ -292,4 +292,4 @@ impl_update_filter!(Nonuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w],
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
impl_update_filter!(Decuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z], [A, a]);
|
impl_update_filter!(Decuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], [X, x], [Y, y], [Z, z], [A, a]);
|
||||||
|
|
||||||
implement_updates!(5, 5);
|
implement_updates!(2, 2);
|
||||||
|
|
|
@ -448,6 +448,59 @@ impl ToTokens for Update {
|
||||||
self.updates.add_update(priority, func)
|
self.updates.add_update(priority, func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P, Func, #filter_type_impls #query_type_impls #resource_type_impls> EventReader<P, #query_types, #resource_types, Func, #filter_types> for Events
|
||||||
|
where
|
||||||
|
Func: Fn(&P, &mut Commands, #( #queries, )* #resources ) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
|
#filter_requirements
|
||||||
|
#component_requirements
|
||||||
|
#reource_requirement
|
||||||
|
P: std::any::Any + Send + Sync,
|
||||||
|
{
|
||||||
|
fn add_reader(&mut self, func: Func) {
|
||||||
|
match self.events.get_mut(&TypeId::of::<P>()) {
|
||||||
|
Some((_, listener)) => listener.push(std::sync::Arc::new(move |world, payload| {
|
||||||
|
let typed_payload: &P = payload.downcast_ref().unwrap();
|
||||||
|
let mut commands = Commands::new(world.now());
|
||||||
|
|
||||||
|
#resource_store
|
||||||
|
|
||||||
|
let mut complying_entities: Vec<Vec<&EntityObject>> = vec![Vec::new(); #query_count];
|
||||||
|
|
||||||
|
for entity in world.entities.values() {
|
||||||
|
let mut comply_queries = Vec::new();
|
||||||
|
|
||||||
|
#( #check_entities )*
|
||||||
|
|
||||||
|
if !comply_queries.is_empty() {
|
||||||
|
comply_queries
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|q| complying_entities[q].push(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if one of the queries could not be fullfilled
|
||||||
|
for queryable_entities in complying_entities.iter() {
|
||||||
|
if queryable_entities.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for entities in complying_entities.into_iter().multi_cartesian_product() {
|
||||||
|
#( #component_stores )*
|
||||||
|
#( #query_structs )*
|
||||||
|
|
||||||
|
func(typed_payload, &mut commands, #( #query_idents, )* #( #resource_idents, )*)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.apply_deferred(world)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})),
|
||||||
|
None => panic!("register event type first!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue