diff --git a/ecs/src/updates.rs b/ecs/src/updates.rs index 0b656c8..601b208 100644 --- a/ecs/src/updates.rs +++ b/ecs/src/updates.rs @@ -18,30 +18,24 @@ use crate::*; use update_macros::{implement_pair_update, implement_single_update}; macro_rules! impl_singleton_update { - // without resources - ( $($var:ident $(,)?)+ ) => { - impl CreateArchetype<( $( $var, )+ ), (), Func, Filter> for Archetype + // single without resources + ( $s:ident, ) => { + impl CreateArchetype<$s, (), Func, Filter> for Archetype where - Func: Fn(&mut Commands, Query<( $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, + Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static, - $( - $var: EntityComponent + ComponentDebug, - )+ + $s: EntityComponent + ComponentDebug, { paste::item! { fn create(f: Func) -> Self { - $( - Filter::verify_dedup::<$var>(); - )+ + Filter::verify_dedup::<$s>(); Self { check_entity: Box::new({ move |entity| { - $( - if !entity.components.contains::<$var>() { - return false; - } - )+ + if !entity.components.contains::<$s>() { + return false; + } if !Filter::check(entity) { return false; @@ -52,11 +46,9 @@ macro_rules! impl_singleton_update { }), create_callback: Box::new(move |entity| { - $( - let [< $var:lower >] = UnsafeComponentStore::from( - entity.get_component::<$var>()? - ); - )+ + let [< $s:lower >] = UnsafeComponentStore::from( + entity.get_component::<$s>()? + ); let e = entity.as_entity(); let f = f.clone(); @@ -64,7 +56,7 @@ macro_rules! impl_singleton_update { Ok(Box::new(move |commands, _world| { let query = Query { entity: e, - c: unsafe { ($([< $var:lower >].as_mut(),)+) }, + c: unsafe { [< $s:lower >].as_mut() }, filter: PhantomData, }; @@ -78,12 +70,10 @@ macro_rules! impl_singleton_update { } } - impl AddUpdates<( $( $var, )+ ), (), Func, Filter> for Updates + impl AddUpdates<$s, (), Func, Filter> for Updates where - $( - $var: EntityComponent + ComponentDebug, - )+ - Func: Fn(& mut Commands, Query<( $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, + $s: EntityComponent + ComponentDebug, + Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static { fn add_update( @@ -98,12 +88,10 @@ macro_rules! impl_singleton_update { } } - impl AddUpdates<( $( $var, )+ ), (), Func, Filter> for WorldBuilder + impl AddUpdates<$s, (), Func, Filter> for WorldBuilder where - $( - $var: EntityComponent + ComponentDebug, - )+ - Func: Fn(& mut Commands, Query<( $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, + $s: EntityComponent + ComponentDebug, + Func: Fn(&mut Commands, Query<&mut $s, Filter>) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static { fn add_update( @@ -116,21 +104,125 @@ macro_rules! impl_singleton_update { } } }; - // with resources - ( $($var:ident $(,)?)+ [$($res:ident $(,)?)+] ) => { - impl CreateArchetype<( $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Archetype + // single with resources + ( $s:ident, [$($res:ident $(,)?)+] ) => { + impl CreateArchetype<$s, ( $( $res, )+ ), Func, Filter> for Archetype where - Func: Fn(&mut Commands, Query<( $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Func: Fn(&mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static, - $( - $var: EntityComponent + ComponentDebug, - )+ + $s: EntityComponent + ComponentDebug, $( $res: ResourceTrait, )+ { paste::item! { fn create(f: Func) -> Self { + Filter::verify_dedup::<$s>(); + + Self { + check_entity: Box::new({ + move |entity| { + if !entity.components.contains::<$s>() { + return false; + } + + if !Filter::check(entity) { + return false; + } + + true + } + }), + + create_callback: Box::new(move |entity| { + let [< $s:lower >] = UnsafeComponentStore::from( + entity.get_component::<$s>()? + ); + + let e = entity.as_entity(); + let f = f.clone(); + + Ok(Box::new(move |commands, world| { + let ( + $( + [< $res:lower _var >], + )+ + ): ( + $( + &mut $res, + )+ + ) = world.resources.get_mut()?; + + let query = Query { + entity: e, + c: unsafe { [< $s:lower >].as_mut() }, + filter: PhantomData, + }; + + f(commands, query, $([< $res:lower _var >],)+) + })) + }), + + entities: IndexMap::new(), + } + } + } + } + + impl AddUpdates<$s, ( $( $res, )+ ), Func, Filter> for Updates + where + $s: EntityComponent + ComponentDebug, + $( + $res: ResourceTrait, + )+ + Func: Fn(& mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + paste::item! { + self.add(name, priority, Update::Single(Archetype::create(func))) + } + } + } + + impl AddUpdates<$s, ( $( $res, )+ ), Func, Filter> for WorldBuilder + where + $s: EntityComponent + ComponentDebug, + $( + $res: ResourceTrait, + )+ + Func: Fn(& mut Commands, Query<&mut $s, Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + self.updates.add_update(name, priority, func) + } + } + }; + // without resources + ( $s:ident, $($var:ident $(,)?)+ ) => { + impl CreateArchetype<( $s, $( $var, )+ ), (), Func, Filter> for Archetype + where + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static, + $s: EntityComponent + ComponentDebug, + $( + $var: EntityComponent + ComponentDebug, + )+ + { + paste::item! { + fn create(f: Func) -> Self { + Filter::verify_dedup::<$s>(); $( Filter::verify_dedup::<$var>(); )+ @@ -138,6 +230,10 @@ macro_rules! impl_singleton_update { Self { check_entity: Box::new({ move |entity| { + if !entity.components.contains::<$s>() { + return false; + } + $( if !entity.components.contains::<$var>() { return false; @@ -153,6 +249,10 @@ macro_rules! impl_singleton_update { }), create_callback: Box::new(move |entity| { + let [< $s:lower >] = UnsafeComponentStore::from( + entity.get_component::<$s>()? + ); + $( let [< $var:lower >] = UnsafeComponentStore::from( entity.get_component::<$var>()? @@ -162,25 +262,14 @@ macro_rules! impl_singleton_update { let e = entity.as_entity(); let f = f.clone(); - Ok(Box::new(move |commands, world| { - - let ( - $( - [< $res:lower _var >], - )+ - ): ( - $( - &mut $res, - )+ - ) = world.resources.get_mut()?; - + Ok(Box::new(move |commands, _world| { let query = Query { entity: e, - c: unsafe { ($([< $var:lower >].as_mut(),)+) }, + c: unsafe { ( [< $s:lower >].as_mut(), $([< $var:lower >].as_mut(),)+) }, filter: PhantomData, }; - f(commands, query, $([< $res:lower _var >],)+) + f(commands, query) })) }), @@ -190,15 +279,13 @@ macro_rules! impl_singleton_update { } } - impl AddUpdates<( $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Updates + impl AddUpdates<( $s, $( $var, )+ ), (), Func, Filter> for Updates where + $s: EntityComponent + ComponentDebug, $( $var: EntityComponent + ComponentDebug, )+ - $( - $res: ResourceTrait, - )+ - Func: Fn(& mut Commands, Query<( $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static { fn add_update( @@ -213,15 +300,142 @@ macro_rules! impl_singleton_update { } } - impl AddUpdates<( $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for WorldBuilder + impl AddUpdates<( $s, $( $var, )+ ), (), Func, Filter> for WorldBuilder where + $s: EntityComponent + ComponentDebug, + $( + $var: EntityComponent + ComponentDebug, + )+ + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + self.updates.add_update(name, priority, func) + } + } + }; + // with resources + ( $s:ident, $($var:ident $(,)?)+ [$($res:ident $(,)?)+] ) => { + impl CreateArchetype<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Archetype + where + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static, + $s: EntityComponent + ComponentDebug, $( $var: EntityComponent + ComponentDebug, )+ $( $res: ResourceTrait, )+ - Func: Fn(& mut Commands, Query<( $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + { + paste::item! { + fn create(f: Func) -> Self { + Filter::verify_dedup::<$s>(); + $( + Filter::verify_dedup::<$var>(); + )+ + + Self { + check_entity: Box::new({ + move |entity| { + if !entity.components.contains::<$s>() { + return false; + } + + $( + if !entity.components.contains::<$var>() { + return false; + } + )+ + + if !Filter::check(entity) { + return false; + } + + true + } + }), + + create_callback: Box::new(move |entity| { + let [< $s:lower >] = UnsafeComponentStore::from( + entity.get_component::<$s>()? + ); + + $( + let [< $var:lower >] = UnsafeComponentStore::from( + entity.get_component::<$var>()? + ); + )+ + + let e = entity.as_entity(); + let f = f.clone(); + + Ok(Box::new(move |commands, world| { + let ( + $( + [< $res:lower _var >], + )+ + ): ( + $( + &mut $res, + )+ + ) = world.resources.get_mut()?; + + let query = Query { + entity: e, + c: unsafe { ( [< $s:lower >].as_mut(), $([< $var:lower >].as_mut(),)+ ) }, + filter: PhantomData, + }; + + f(commands, query, $([< $res:lower _var >],)+) + })) + }), + + entities: IndexMap::new(), + } + } + } + } + + impl AddUpdates<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for Updates + where + $s: EntityComponent + ComponentDebug, + $( + $var: EntityComponent + ComponentDebug, + )+ + $( + $res: ResourceTrait, + )+ + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, + Filter: CheckFilter + 'static + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + paste::item! { + self.add(name, priority, Update::Single(Archetype::create(func))) + } + } + } + + impl AddUpdates<( $s, $( $var, )+ ), ( $( $res, )+ ), Func, Filter> for WorldBuilder + where + $s: EntityComponent + ComponentDebug, + $( + $var: EntityComponent + ComponentDebug, + )+ + $( + $res: ResourceTrait, + )+ + Func: Fn(&mut Commands, Query<( &mut $s, $( &mut $var, )+ ), Filter>, $(&mut $res,)+) -> Result<()> + Send + Sync + Clone + 'static, Filter: CheckFilter + 'static { fn add_update( @@ -372,7 +586,7 @@ macro_rules! impl_pair_update { $( $lhs_big: EntityComponent + ComponentDebug, )+ - Func: Fn(& mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static, + Func: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LhsFilter>, Query<( $( &mut $rhs_big, )+ ), RhsFilter>) -> Result<()> + Send + Sync + Clone + 'static, LhsFilter: CheckFilter + 'static, RhsFilter: CheckFilter + 'static {