use crate::component::ComponentVec;
use crate::entity;
pub struct World<S> {
storage: S,
entity_allocator: entity::Allocator,
}
impl<S> World<S> {
#[must_use]
#[inline]
pub fn new() -> Self
where
S: Default,
{
World {
entity_allocator: entity::Allocator::new(),
storage: S::default(),
}
}
#[must_use]
#[inline]
pub fn storage(&self) -> &S {
&self.storage
}
#[must_use]
#[inline]
pub fn storage_mut(&mut self) -> &mut S {
&mut self.storage
}
#[must_use]
#[inline]
pub fn spawn(&mut self) -> entity::Entity {
self.entity_allocator.alloc()
}
#[inline]
pub fn spawn_with<T>(&mut self, value: T) -> entity::Entity
where
Self: InsertMany<T>,
{
let entity = self.entity_allocator.alloc();
_ = self.insert_many(entity, value);
entity
}
#[inline]
pub fn despawn(&mut self, entity: entity::Entity) -> Result<(), entity::Error>
where
S: RemoveAll,
{
self.storage.remove_all(entity);
self.entity_allocator.free(entity)
}
#[inline]
pub fn despawn_all<T>(&mut self) -> Result<(), entity::Error>
where
S: RemoveAll + AsRef<ComponentVec<T>>,
{
while let Some((e, _)) = self.storage.as_ref().iter().next() {
self.despawn(e)?;
}
Ok(())
}
#[inline]
pub fn despawn_entities<'a, I>(&'a mut self, entities: I) -> Result<(), entity::Error>
where
S: RemoveAll,
I: IntoIterator<Item = &'a entity::Entity>,
{
for &entity in entities {
self.despawn(entity)?;
}
Ok(())
}
#[must_use]
#[inline]
pub fn get<T>(&self, entity: entity::Entity) -> Option<&T>
where
S: AsRef<ComponentVec<T>>,
{
self.storage.as_ref().get(entity)
}
#[must_use]
#[inline]
pub fn get_mut<T>(&mut self, entity: entity::Entity) -> Option<&mut T>
where
S: AsMut<ComponentVec<T>>,
{
self.storage.as_mut().get_mut(entity)
}
#[inline]
pub fn insert<T>(&mut self, entity: entity::Entity, value: T) -> Option<T>
where
S: AsMut<ComponentVec<T>>,
{
self.storage.as_mut().insert(entity, value)
}
#[inline]
pub fn remove<T>(&mut self, entity: entity::Entity) -> Option<T>
where
S: AsMut<ComponentVec<T>>,
{
self.storage.as_mut().remove(entity)
}
}
impl<S> Default for World<S>
where
S: Default,
{
#[inline]
fn default() -> World<S> {
World::new()
}
}
pub trait RemoveAll {
fn remove_all(&mut self, entity: entity::Entity);
}
pub trait InsertMany<T> {
type Output;
fn insert_many(&mut self, entity: entity::Entity, value: T) -> Self::Output;
}
impl<S> InsertMany<()> for World<S> {
type Output = ();
#[inline]
fn insert_many(&mut self, _entity: entity::Entity, _value: ()) -> Self::Output {}
}
macro_rules! impl_insert_many {
($($T:ident),*) => {
impl<S, $($T),*> InsertMany<($($T),*,)> for World<S>
where
$(
S: AsMut<$crate::ComponentVec<$T>>,
)*
{
type Output = ($(Option<$T>,)*);
#[inline]
fn insert_many(&mut self, entity: entity::Entity, value: ($($T),*,)) -> Self::Output {
#![allow(non_snake_case)]
let ($($T),*,) = value;
($(
self.insert(entity, $T),
)*)
}
}
};
}
macro_rules! expand {
($macro:ident, $head:ident) => {
$macro!{$head}
};
($macro:ident, $head:ident, $($tail:ident),*) => {
$macro!{$head, $($tail),*}
expand!{$macro, $($tail),*}
};
}
expand!(impl_insert_many, A, B, C, D, E, F, G);
#[macro_export]
macro_rules! spawn {
($world:ident, $($component:expr),* $(,)?) => {{
let entity = $world.spawn();
$(
$world.insert(entity, $component);
)*
entity
}};
}
#[macro_export]
macro_rules! derive_storage {
($( $tokens:tt )*) => {
$( $tokens )*
$crate::internal_derive_storage! { $( $tokens )* }
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! internal_derive_storage {
(
$( #[$_meta:meta] )*
$_vis:vis struct $name:ident {
$(
$( #[$_meta_field:meta] )*
$_vis_field:vis $field:ident : $type:ty,
)*
}
) => {
impl $crate::world::RemoveAll for $name {
#[inline]
fn remove_all(&mut self, entity: $crate::entity::Entity) {
$(
self.$field.remove(entity);
)*
}
}
$(
impl AsRef<$type> for $name {
#[inline]
fn as_ref(&self) -> &$type {
&self.$field
}
}
impl AsMut<$type> for $name {
#[inline]
fn as_mut(&mut self) -> &mut $type {
&mut self.$field
}
}
)*
};
}