use std::{marker::PhantomData, cell::{Ref, RefMut, RefCell}, any::{TypeId, Any}, rc::Rc};
use super::{Entities};
pub struct AutoQuery<'a, T: Any>
{
entities: &'a Entities,
phantom: PhantomData<T>,
}
impl<'a, T: 'static> AutoQuery<'a, T> {
pub fn new(entities: &'a Entities) -> Self {
Self {
entities,
phantom: PhantomData
}
}
pub fn len(&self) -> usize {
let typeid = TypeId::of::<T>();
let selfmap = self.entities.bit_masks.get(&typeid).unwrap();
self.entities.map.iter().fold(0, |aggr, bitmask| {
if bitmask & selfmap == *selfmap {
aggr + 1
} else {
aggr
}
})
}
}
impl<'a, T: 'static> std::iter::IntoIterator for AutoQuery<'a, T> {
type IntoIter = AutoQueryIntoIterator<'a, T>;
type Item = Ref<'a, T>;
fn into_iter(self) -> Self::IntoIter {
let typeid = TypeId::of::<T>();
let selfmap = self.entities.bit_masks.get(&typeid).unwrap();
let all_components = self.entities.components.get(&typeid).unwrap();
let components = all_components.into_iter().enumerate()
.map(|(ind, c)| {
if (self.entities.map[ind] & selfmap == *selfmap) && c.is_some() {
Some(c.as_ref().unwrap())
} else {
None
}
})
.flatten()
.collect::<Vec<&Rc<RefCell<dyn Any>>>>();
AutoQueryIntoIterator {
components: components.into_iter()
.map(|c| {
let component = c.as_ref();
let borrow = component.borrow();
Ref::map(borrow, |any| {
any.downcast_ref::<T>().unwrap()
})
})
.collect::<Vec<Ref<T>>>()
}
}
}
pub struct AutoQueryIntoIterator<'a, T> {
components: Vec<Ref<'a, T>>,
}
impl<'a, T: 'static> std::iter::Iterator for AutoQueryIntoIterator<'a, T> {
type Item = Ref<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
self.components.pop()
}
}
pub struct AutoQueryMut<'a, T: Any>
{
entities: &'a Entities,
phantom: PhantomData<T>,
}
impl<'a, T: 'static> AutoQueryMut<'a, T> {
pub fn new(entities: &'a Entities) -> Self {
Self {
entities,
phantom: PhantomData
}
}
}
impl<'a, T: 'static> std::iter::IntoIterator for AutoQueryMut<'a, T> {
type IntoIter = AutoQueryMutIntoIterator<'a, T>;
type Item = RefMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
let typeid = TypeId::of::<T>();
let components = self.entities.components.get(&typeid).unwrap();
AutoQueryMutIntoIterator {
components: components.into_iter()
.flatten()
.map(|c| {
let component = c.as_ref();
let borrow = component.borrow_mut();
RefMut::map(borrow, |any| {
any.downcast_mut::<T>().unwrap()
})
})
.collect::<Vec<RefMut<T>>>()
}
}
}
pub struct AutoQueryMutIntoIterator<'a, T> {
components: Vec<RefMut<'a, T>>,
}
impl<'a, T: 'static> std::iter::Iterator for AutoQueryMutIntoIterator<'a, T> {
type Item = RefMut<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
self.components.pop()
}
}