use std::{any::TypeId, collections::HashMap, hash::Hash};
use crate::component::{ComponentChannel, ComponentMap, ErasedComponentChannel};
#[derive(Default)]
pub struct Entities {
components: HashMap<TypeId, Box<dyn ErasedComponentChannel>>,
}
impl Entities {
pub fn spawn<T>(&mut self, component: T)
where
T: 'static,
{
let id = TypeId::of::<T>();
self.components
.entry(id)
.or_insert(ComponentChannel::<T>::new_box())
.as_any_mut()
.downcast_mut::<ComponentChannel<T>>()
.map(|c| c.push(component));
}
pub fn spawn_indexed<TKey, TValue>(&mut self, key: TKey, component: TValue)
where
TKey: Eq + Hash + 'static,
TValue: 'static,
{
let id = TypeId::of::<(TKey, TValue)>();
self.components
.entry(id)
.or_insert(ComponentMap::<TKey, TValue>::new_box())
.as_any_mut()
.downcast_mut::<ComponentMap<TKey, TValue>>()
.map(|c| c.insert(key, component));
}
pub fn query<'c, T: 'static>(&'c self) -> QueryRef<'c, T> {
let id = TypeId::of::<T>();
let channel = self.components
.get(&id)
.map(|c| c.as_any())
.and_then(|c| c.downcast_ref::<ComponentChannel::<T>>());
QueryRef::<T>::from_channel(channel)
}
pub fn query_mut<'c, T: 'static>(&'c mut self) -> QueryMut<'c, T> {
let id = TypeId::of::<T>();
let channel = self.components
.get_mut(&id)
.map(|c| c.as_any_mut())
.and_then(|c| c.downcast_mut::<ComponentChannel::<T>>());
QueryMut::<T>::from_channel(channel)
}
pub fn query_disjoint_mut<'c, const N: usize>(&'c mut self, component_ids: [&TypeId; N]) -> QueryDisjointMut<'c> {
let channels = self.components
.get_disjoint_mut(component_ids)
.into_iter()
.filter_map(|c| c);
let channel_ids = component_ids
.into_iter()
.cloned();
let channels_map = channel_ids
.zip(channels)
.collect::<HashMap<TypeId, &mut Box<dyn ErasedComponentChannel>>>();
QueryDisjointMut::from_channels(channels_map)
}
pub fn query_indexed<'c, TKey, TValue>(&'c self) -> QueryIndexedRef<'c, TKey, TValue>
where
TKey: Eq + Hash + 'static,
TValue: 'static,
{
let id = TypeId::of::<(TKey, TValue)>();
let channel = self.components
.get(&id)
.map(|c| c.as_any())
.and_then(|c| c.downcast_ref::<ComponentMap<TKey, TValue>>());
QueryIndexedRef::from_channel(channel)
}
pub fn query_indexed_mut<'c, TKey, TValue>(&'c mut self) -> QueryIndexedMut<'c, TKey, TValue>
where
TKey: Eq + Hash + 'static,
TValue: 'static,
{
let id = TypeId::of::<(TKey, TValue)>();
let channel = self.components
.get_mut(&id)
.map(|c| c.as_any_mut())
.and_then(|c| c.downcast_mut::<ComponentMap<TKey, TValue>>());
QueryIndexedMut::from_channel(channel)
}
}
pub struct QueryRef<'c, T> {
channel: Option<&'c ComponentChannel<T>>
}
impl<'c, T> QueryRef<'c, T> {
const fn from_channel(channel: Option<&'c ComponentChannel<T>>) -> Self {
Self { channel }
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.channel
.iter()
.flat_map(|c| c.iter())
}
pub fn first(&self) -> Option<&T> {
self.iter()
.next()
}
}
pub struct QueryMut<'c, T> {
channel: Option<&'c mut ComponentChannel<T>>,
}
impl<'c, T> QueryMut<'c, T> {
const fn from_channel(channel: Option<&'c mut ComponentChannel<T>>) -> Self {
Self { channel }
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.channel
.iter_mut()
.flat_map(|c| c.iter_mut())
}
pub fn first_mut(&mut self) -> Option<&mut T> {
self.iter_mut()
.next()
}
}
pub struct QueryDisjointMut<'c> {
channels: HashMap<TypeId, &'c mut Box<dyn ErasedComponentChannel>>,
}
impl<'c> QueryDisjointMut<'c> {
const fn from_channels(channels: HashMap<TypeId, &'c mut Box<dyn ErasedComponentChannel>>) -> Self {
Self { channels }
}
pub fn iter_mut<T: 'static>(&mut self) -> impl Iterator<Item = &mut T> {
let id = TypeId::of::<T>();
self.channels
.get_mut(&id)
.map(|c| c.as_any_mut())
.and_then(|a| a.downcast_mut::<ComponentChannel<T>>())
.into_iter()
.flat_map(|c| c.iter_mut())
}
pub fn first_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.iter_mut()
.next()
}
}
pub struct QueryIndexedRef<'c, TKey, TValue> {
channel: Option<&'c ComponentMap<TKey, TValue>>,
}
impl<'c, TKey, TValue> QueryIndexedRef<'c, TKey, TValue>
where
TKey: Eq + Hash,
{
pub const fn from_channel(channel: Option<&'c ComponentMap<TKey, TValue>>) -> Self {
Self { channel }
}
pub fn get(&self, key: &TKey) -> Option<&'c TValue> {
self.channel.and_then(|c| c.get(key))
}
pub fn iter(&self) -> impl Iterator<Item = (&'c TKey, &'c TValue)> {
self.channel
.iter()
.flat_map(|c| c.iter())
}
}
pub struct QueryIndexedMut<'c, TKey, TValue> {
channel: Option<&'c mut ComponentMap<TKey, TValue>>,
}
impl<'c, TKey, TValue> QueryIndexedMut<'c, TKey, TValue>
where
TKey: Eq + Hash,
{
pub const fn from_channel(channel: Option<&'c mut ComponentMap<TKey, TValue>>) -> Self {
Self { channel }
}
pub fn get_mut(&'c mut self, key: &TKey) -> Option<&'c mut TValue> {
self.channel
.as_mut()
.and_then(|c| c.get_mut(key))
}
pub fn iter_mut(&'c mut self) -> impl Iterator<Item = (&'c TKey, &'c mut TValue)> {
self.channel
.iter_mut()
.flat_map(|c| c.iter_mut())
}
}