use super::{
registry::{Ref, RefMut},
Component, Components, Entities, Entity, EntityId, Resources,
};
use crate::collections::Cons;
use alloc::vec::Vec;
use core::any::Any;
pub trait Archetypes: Entities + Components + Resources + Sized {
#[inline]
fn register_archetype<E: Entity + Any, C: Cons>(&mut self)
where
(E, C): RegisterArchetype<Self>,
{
<(E, C)>::register(self);
}
#[inline]
fn storage<'a, E, C: Cons>(&'a self) -> <(E, C) as ArchetypeStorage<'a, Self>>::Storage
where
(E, C): ArchetypeStorage<'a, Self>,
{
<(E, C)>::storage(self)
}
#[inline]
fn insert_archetype<E: Entity + Any, C: Cons>(&self, entity: E, components: C) -> EntityId<E>
where
Self: Any,
C: InsertComponents<Self, E>,
{
self.resource::<Archetype<Self, E>>()
.insert(self, entity, components)
}
#[inline]
fn remove_archetype<E: Entity + Any>(&self, key: &EntityId<E>)
where
Self: Any,
{
self.resource::<Archetype<Self, E>>().remove(self, key)
}
}
impl<T: Entities + Components + Resources> Archetypes for T {}
pub struct Archetype<R: Entities + Components, E: Entity> {
drop: Vec<fn(&R, &EntityId<E>)>,
}
impl<R: Entities + Components, E: Entity + Any> Archetype<R, E> {
#[inline]
pub fn new() -> Self {
Self {
drop: Default::default(),
}
}
pub fn register_component<C: Component<E> + Any>(&mut self) {
use crate::collections::MapMut;
self.drop.push(|r, e| {
r.components_mut::<E, C>().remove(e);
});
}
pub fn insert<C: Cons>(&self, registry: &R, entity: E, components: C) -> EntityId<E>
where
C: InsertComponents<R, E>,
{
use crate::collections::Arena;
let key = registry.entities_mut::<E>().insert(entity);
components.insert(registry, key);
key
}
pub fn remove(&self, registry: &R, key: &EntityId<E>) {
use crate::collections::Arena;
for drop in &self.drop {
drop(registry, key);
}
registry.entities_mut::<E>().remove(key);
}
}
pub trait RegisterArchetype<R: Entities + Components + Resources> {
fn register(registry: &mut R);
}
impl<R: Entities + Components + Resources + Any, E: Entity + Any> RegisterArchetype<R> for (E, ()) {
#[inline(always)]
fn register(registry: &mut R) {
registry.register_entity::<E>();
registry.register_resource(Archetype::<R, E>::new());
}
}
impl<
R: Entities + Components + Resources + Any,
E: Entity + Any,
C: Component<E> + Any,
Tail: Cons,
> RegisterArchetype<R> for (E, (C, Tail))
where
(E, Tail): RegisterArchetype<R>,
{
#[inline(always)]
fn register(registry: &mut R) {
<(E, Tail)>::register(registry);
registry.register_component::<E, C>();
registry
.resource_mut::<Archetype<R, E>>()
.register_component::<C>();
}
}
pub trait ArchetypeStorage<'a, R: Entities + Components> {
type Storage: Cons;
fn storage(registry: &'a R) -> Self::Storage;
}
impl<'a, R: Entities + Components, E: Entity + Any, C: Cons> ArchetypeStorage<'a, R> for (&'a E, C)
where
(E, C): ComponentsStorage<'a, R>,
{
type Storage = (
Ref<'a, E::Storage>,
<(E, C) as ComponentsStorage<'a, R>>::Storage,
);
#[inline(always)]
fn storage(registry: &'a R) -> Self::Storage {
(registry.entities::<E>(), <(E, C)>::components(registry))
}
}
impl<'a, R: Entities + Components, E: Entity + Any, C: Cons> ArchetypeStorage<'a, R>
for (&'a mut E, C)
where
(E, C): ComponentsStorage<'a, R>,
{
type Storage = (
RefMut<'a, E::Storage>,
<(E, C) as ComponentsStorage<'a, R>>::Storage,
);
#[inline(always)]
fn storage(registry: &'a R) -> Self::Storage {
(registry.entities_mut::<E>(), <(E, C)>::components(registry))
}
}
pub trait ComponentsStorage<'a, R: Components> {
type Storage: Cons;
fn components(registry: &'a R) -> Self::Storage;
}
impl<'a, R: Components, E: Entity + Any> ComponentsStorage<'a, R> for (E, ()) {
type Storage = ();
#[inline(always)]
fn components(_registry: &'a R) -> Self::Storage {
()
}
}
impl<'a, R: Components, E: Entity + Any, C: Component<E> + Any, Tail: Cons> ComponentsStorage<'a, R>
for (E, (&'a C, Tail))
where
(E, Tail): ComponentsStorage<'a, R>,
{
type Storage = (
Ref<'a, C::Storage>,
<(E, Tail) as ComponentsStorage<'a, R>>::Storage,
);
#[inline(always)]
fn components(registry: &'a R) -> Self::Storage {
(
registry.components::<E, C>(),
<(E, Tail)>::components(registry),
)
}
}
impl<'a, R: Components, E: Entity + Any, C: Component<E> + Any, Tail: Cons> ComponentsStorage<'a, R>
for (E, (&'a mut C, Tail))
where
(E, Tail): ComponentsStorage<'a, R>,
{
type Storage = (
RefMut<'a, C::Storage>,
<(E, Tail) as ComponentsStorage<'a, R>>::Storage,
);
#[inline(always)]
fn components(registry: &'a R) -> Self::Storage {
(
registry.components_mut::<E, C>(),
<(E, Tail)>::components(registry),
)
}
}
pub trait InsertComponents<R: Components, E: Entity>: Sized {
#[inline(always)]
fn insert(self, _registry: &R, _key: EntityId<E>) {}
}
impl<'a, R: Components, E: Entity> InsertComponents<R, E> for () {}
impl<'a, R: Components, E: Entity + Any, C: Component<E> + Any, Tail: Cons> InsertComponents<R, E>
for (C, Tail)
where
Tail: InsertComponents<R, E>,
{
#[inline(always)]
fn insert(self, registry: &R, key: EntityId<E>) {
use crate::collections::MapMut;
registry.components_mut::<E, C>().insert(key, self.0);
self.1.insert(registry, key);
}
}