diff --git a/ecs/src/events.rs b/ecs/src/events.rs index 4580c2e..8b64b6a 100644 --- a/ecs/src/events.rs +++ b/ecs/src/events.rs @@ -8,7 +8,7 @@ use std::{ use crate::World; pub struct Events { - events: HashMap< + pub(crate) events: HashMap< TypeId, // TypeId of Payload ( Vec>, // Payload @@ -51,20 +51,6 @@ impl Events { .insert(TypeId::of::(), (Vec::new(), Vec::new())); } - pub fn add_reader(&mut self, f: F) - where - F: Fn(&mut World, &T) -> anyhow::Result<()> + Send + Sync + 'static, - { - match self.events.get_mut(&TypeId::of::()) { - 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(&mut self, payload: T) { match self.events.get_mut(&TypeId::of::()) { Some((payloads, _)) => payloads.push(Box::new(payload)), @@ -93,3 +79,10 @@ impl Events { Ok(()) } } + +pub trait EventReader +where + P: Any + Send + Sync, +{ + fn add_reader(&mut self, func: Func); +} diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index b2ec2b1..db18648 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -10,7 +10,7 @@ mod updates; mod world; 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::type_map::{ ComponentCreateInfo, ComponentDebug, ComponentNotFoundError, EntityComponent, TypeMap, diff --git a/ecs/src/updates.rs b/ecs/src/updates.rs index b8a957e..f77f29a 100644 --- a/ecs/src/updates.rs +++ b/ecs/src/updates.rs @@ -292,4 +292,4 @@ impl_update_filter!(Nonuple, [R, r], [S, s], [T, t], [U, u], [V, v], [W, w], #[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]); -implement_updates!(5, 5); +implement_updates!(2, 2); diff --git a/update_macros/src/update.rs b/update_macros/src/update.rs index 4821c33..931487d 100644 --- a/update_macros/src/update.rs +++ b/update_macros/src/update.rs @@ -448,6 +448,59 @@ impl ToTokens for Update { self.updates.add_update(priority, func) } } + + impl EventReader 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::

()) { + 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![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); }