use crate::cache::WorldInfoCache;
use crate::*;
use private::SealedComponentGroup;
#[macro_export]
macro_rules! expr {
($x:expr) => {
$x
};
}
#[macro_export]
macro_rules! tuple_index {
($tuple:expr, $idx:tt) => {
expr!($tuple.$idx)
};
}
pub trait ComponentGroup<'c>: Sized + 'static {
type RefTuple: 'c;
type MutRefTuple: 'c;
fn populate(target: &mut impl TermBuilder);
unsafe fn fill_descriptor(world: *mut ecs_world_t, desc: &mut ecs_filter_desc_t);
unsafe fn iter_as_ref_tuple(it: &ecs_iter_t, i: isize) -> Self::RefTuple;
unsafe fn iter_as_mut_tuple(it: &ecs_iter_t, i: isize) -> Self::MutRefTuple;
}
impl<'c, T: Component + SealedComponentGroup> ComponentGroup<'c> for T {
type RefTuple = &'c T;
type MutRefTuple = &'c mut T;
fn populate(target: &mut impl TermBuilder) {
let world = target.world();
let term = target.current_term();
term.id = WorldInfoCache::get_component_id_for_type::<T>(world)
.expect("Component type not registered!");
target.next_term();
}
unsafe fn fill_descriptor(world: *mut ecs_world_t, desc: &mut ecs_filter_desc_t) {
desc.terms[0].id = WorldInfoCache::get_component_id_for_type::<T>(world)
.expect("Component type not registered!");
}
unsafe fn iter_as_ref_tuple(it: &ecs_iter_t, i: isize) -> Self::RefTuple {
ecs_field::<T>(it, 1).offset(i).as_ref().unwrap()
}
unsafe fn iter_as_mut_tuple(it: &ecs_iter_t, i: isize) -> Self::MutRefTuple {
ecs_field::<T>(it, 1).offset(i).as_mut().unwrap()
}
}
macro_rules! impl_component_tuple {
($len:expr, $(($elem:ident, $elem_idx:tt)), *) => {
impl<'s, $($elem),*> ComponentGroup<'s> for ($($elem), *)
where $( $elem : Component /*+ SealedComponentGroup*/ ),*
{
type RefTuple = ($(&'s $elem),*);
type MutRefTuple = ($(&'s mut $elem),*);
fn populate(target: &mut impl TermBuilder) {
let world = target.world();
$(
let term = target.current_term();
term.id = WorldInfoCache::get_component_id_for_type::<$elem>(world).expect("Component type not registered!");
target.next_term();
)*
}
unsafe fn fill_descriptor(world: *mut ecs_world_t, desc: &mut ecs_filter_desc_t) {
$(
desc.terms[$elem_idx].id = WorldInfoCache::get_component_id_for_type::<$elem>(world).expect("Component type not registered!");
)*
}
unsafe fn iter_as_ref_tuple(it: &ecs_iter_t, i: isize) -> Self::RefTuple {
($(
&*((ecs_field::<$elem>(it, $elem_idx + 1)) as *mut $elem).offset(i as isize).as_ref().unwrap(),
)*)
}
unsafe fn iter_as_mut_tuple(it: &ecs_iter_t, i: isize) -> Self::MutRefTuple {
($(
&mut *((ecs_field::<$elem>(it, $elem_idx + 1)) as *mut $elem).offset(i as isize).as_mut().unwrap(),
)*)
}
}
}
}
impl_component_tuple!(8, (T1, 0), (T2, 1), (T3, 2), (T4, 3), (T5, 4), (T6, 5), (T7, 6), (T8, 7));
impl_component_tuple!(7, (T1, 0), (T2, 1), (T3, 2), (T4, 3), (T5, 4), (T6, 5), (T7, 6));
impl_component_tuple!(6, (T1, 0), (T2, 1), (T3, 2), (T4, 3), (T5, 4), (T6, 5));
impl_component_tuple!(5, (T1, 0), (T2, 1), (T3, 2), (T4, 3), (T5, 4));
impl_component_tuple!(4, (T1, 0), (T2, 1), (T3, 2), (T4, 3));
impl_component_tuple!(3, (T1, 0), (T2, 1), (T3, 2));
impl_component_tuple!(2, (T1, 0), (T2, 1));
mod private {
pub trait SealedComponentGroup {}
}