From c728605684e58243f6e5fa5a9a82b824ceb6b477 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Tue, 8 Apr 2025 20:04:08 +0200 Subject: [PATCH] Implement single queries for tuple entities --- ecs/src/updates.rs | 276 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/ecs/src/updates.rs b/ecs/src/updates.rs index 601b208..a30284d 100644 --- a/ecs/src/updates.rs +++ b/ecs/src/updates.rs @@ -451,6 +451,282 @@ macro_rules! impl_singleton_update { } macro_rules! impl_pair_update { + // lhs single + ( + $lhs_id: expr, + ( [$lhs_little: ident: $lhs_big: ident]$(,)? ), + $rhs_id: expr, + ( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ ) + ) => { + impl ArchetypePair { + paste::item! { + pub fn [] + (f: F) -> Self + where + F: Fn(&mut Commands, Query<&mut $lhs_big, LeftFilter>, Query<( $( &mut $rhs_big, )+ ), RightFilter>) -> Result<()> + Send + Sync + Clone + 'static, + LeftFilter: CheckFilter + 'static, + RightFilter: CheckFilter + 'static, + $( + $rhs_big: EntityComponent + ComponentDebug, + )+ + $lhs_big: EntityComponent + ComponentDebug, + { + LeftFilter::verify_dedup::<$lhs_big>(); + + $( + RightFilter::verify_dedup::<$rhs_big>(); + )+ + + Self { + check_left_entity: Box::new({ + move |entity| { + if !entity.components.contains::<$lhs_big>() { + return false; + } + + if !LeftFilter::check(entity) { + return false; + } + + true + } + }), + check_right_entity: Box::new({ + move |entity| { + $( + if !entity.components.contains::<$rhs_big>() { + return false; + } + )+ + + if !RightFilter::check(entity) { + return false; + } + + true + } + }), + + create_callback: Box::new(move |lhs_entity, rhs_entity| { + let $lhs_little = UnsafeComponentStore::from( + lhs_entity.get_component::<$lhs_big>()? + ); + + $( + let $rhs_little = UnsafeComponentStore::from( + rhs_entity.get_component::<$rhs_big>()? + ); + )+ + + let lhs_e = lhs_entity.as_entity(); + let rhs_e = rhs_entity.as_entity(); + let f = f.clone(); + + Ok(Box::new(move |commands| { + let lhs_query = Query { + entity: lhs_e, + c: unsafe { $lhs_little.as_mut() }, + filter: PhantomData, + }; + + let rhs_query = Query { + entity: rhs_e, + c: unsafe { ($($rhs_little.as_mut(),)+) }, + filter: PhantomData, + }; + + f(commands, lhs_query, rhs_query ) + })) + }), + + entities: IndexMap::new(), + } + } + } + } + + impl AddUpdates<( $lhs_big, ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for Updates + where + $( + $rhs_big: EntityComponent + ComponentDebug, + )+ + $lhs_big: EntityComponent + ComponentDebug, + 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 + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + paste::item! { + self.add(name, priority, Update::Pair(ArchetypePair::[](func)))?; + } + + Ok(()) + } + } + + impl AddUpdates<( $lhs_big, ($($rhs_big,)+) ), (), Func, (LhsFilter, RhsFilter)> for WorldBuilder + where + $( + $rhs_big: EntityComponent + ComponentDebug, + )+ + $lhs_big: EntityComponent + ComponentDebug, + 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 + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + self.updates.add_update(name, priority, func) + } + } + }; + // rhs_single + ( + $lhs_id: expr, + ( $([$lhs_little: ident: $lhs_big: ident]$(,)?)+ ), + $rhs_id: expr, + ( [$rhs_little: ident: $rhs_big: ident]$(,)? ) + ) => { + impl ArchetypePair { + paste::item! { + pub fn [] + (f: F) -> Self + where + F: Fn(&mut Commands, Query<( $( &mut $lhs_big, )+ ), LeftFilter>, Query<&mut $rhs_big, RightFilter>) -> Result<()> + Send + Sync + Clone + 'static, + LeftFilter: CheckFilter + 'static, + RightFilter: CheckFilter + 'static, + $rhs_big: EntityComponent + ComponentDebug, + $( + $lhs_big: EntityComponent + ComponentDebug, + )+ + { + $( + LeftFilter::verify_dedup::<$lhs_big>(); + )+ + + RightFilter::verify_dedup::<$rhs_big>(); + + Self { + check_left_entity: Box::new({ + move |entity| { + $( + if !entity.components.contains::<$lhs_big>() { + return false; + } + )+ + + if !LeftFilter::check(entity) { + return false; + } + + true + } + }), + check_right_entity: Box::new({ + move |entity| { + if !entity.components.contains::<$rhs_big>() { + return false; + } + + if !RightFilter::check(entity) { + return false; + } + + true + } + }), + + create_callback: Box::new(move |lhs_entity, rhs_entity| { + $( + let $lhs_little = UnsafeComponentStore::from( + lhs_entity.get_component::<$lhs_big>()? + ); + )+ + + let $rhs_little = UnsafeComponentStore::from( + rhs_entity.get_component::<$rhs_big>()? + ); + + let lhs_e = lhs_entity.as_entity(); + let rhs_e = rhs_entity.as_entity(); + let f = f.clone(); + + Ok(Box::new(move |commands| { + let lhs_query = Query { + entity: lhs_e, + c: unsafe { ($($lhs_little.as_mut(),)+) }, + filter: PhantomData, + }; + + let rhs_query = Query { + entity: rhs_e, + c: unsafe { $rhs_little.as_mut() }, + filter: PhantomData, + }; + + f(commands, lhs_query, rhs_query ) + })) + }), + + entities: IndexMap::new(), + } + } + } + } + + impl AddUpdates<( ($( $lhs_big, )+), $rhs_big ), (), Func, (LhsFilter, RhsFilter)> for Updates + where + $rhs_big: EntityComponent + ComponentDebug, + $( + $lhs_big: EntityComponent + ComponentDebug, + )+ + 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 + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + paste::item! { + self.add(name, priority, Update::Pair(ArchetypePair::[](func)))?; + } + + Ok(()) + } + } + + impl AddUpdates<( ($( $lhs_big, )+), $rhs_big ), (), Func, (LhsFilter, RhsFilter)> for WorldBuilder + where + $rhs_big: EntityComponent + ComponentDebug, + $( + $lhs_big: EntityComponent + ComponentDebug, + )+ + 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 + { + fn add_update( + &mut self, + name: &str, + priority: u32, + func: Func, + ) -> Result<()> { + self.updates.add_update(name, priority, func) + } + } + }; ( $lhs_id: expr, ( $([$lhs_little: ident: $lhs_big: ident]$(,)?)+ ),