pub use self::comp::Component;
pub use self::entity::{CreateIterAtomic, Entities, EntitiesRes, Entity, Generation, Index};
pub use self::lazy::{LazyBuilder, LazyUpdate};
use self::entity::Allocator;
use std::borrow::Borrow;
use shred::{Fetch, FetchMut, MetaTable, Read, Resource, Resources, SystemData};
use error::WrongGeneration;
use storage::{AnyStorage, DenseVecStorage, MaskedStorage};
use storage::{ReadStorage, WriteStorage};
mod comp;
mod entity;
mod lazy;
#[cfg(test)]
mod tests;
pub struct CreateIter<'a>(FetchMut<'a, EntitiesRes>);
impl<'a> Iterator for CreateIter<'a> {
type Item = Entity;
fn next(&mut self) -> Option<Entity> {
Some(self.0.alloc.allocate())
}
}
pub struct EntityBuilder<'a> {
pub entity: Entity,
pub world: &'a World,
}
impl<'a> EntityBuilder<'a> {
#[inline]
pub fn with<T: Component>(self, c: T) -> Self {
{
let mut storage = self.world.write_storage();
storage.insert(self.entity, c);
}
self
}
#[inline]
pub fn build(self) -> Entity {
self.entity
}
}
pub struct World {
pub res: Resources,
}
impl World {
pub fn new() -> World {
Default::default()
}
pub fn register<T: Component>(&mut self)
where
T::Storage: Default,
{
self.register_with_storage::<_, T>(Default::default);
}
pub fn register_with_storage<F, T>(&mut self, storage: F)
where
F: FnOnce() -> T::Storage,
T: Component,
{
Self::register_with_storage_internal::<F, T>(&mut self.res, storage);
}
pub(crate) fn register_with_storage_internal<F, T>(res: &mut Resources, storage: F)
where
F: FnOnce() -> T::Storage,
T: Component,
{
res.entry()
.or_insert_with(move || MaskedStorage::<T>::new(storage()));
res.fetch_mut::<MetaTable<AnyStorage>>()
.register(&*res.fetch::<MaskedStorage<T>>());
}
pub fn system_data<'a, T>(&'a self) -> T
where
T: SystemData<'a>,
{
SystemData::fetch(&self.res)
}
pub fn add_resource<T: Resource>(&mut self, res: T) {
if self.res.has_value::<T>() {
*self.res.fetch_mut() = res;
} else {
self.res.insert(res);
}
}
pub fn read_storage<T: Component>(&self) -> ReadStorage<T> {
use shred::SystemData;
SystemData::fetch(&self.res)
}
pub fn write_storage<T: Component>(&self) -> WriteStorage<T> {
use shred::SystemData;
SystemData::fetch(&self.res)
}
pub fn read_resource<T: Resource>(&self) -> Fetch<T> {
self.res.fetch()
}
pub fn write_resource<T: Resource>(&self) -> FetchMut<T> {
self.res.fetch_mut()
}
pub fn entities(&self) -> Read<EntitiesRes> {
Read::fetch(&self.res)
}
fn entities_mut(&self) -> FetchMut<EntitiesRes> {
self.write_resource()
}
pub fn create_entity(&mut self) -> EntityBuilder {
self.create_entity_unchecked()
}
pub fn create_entity_unchecked(&self) -> EntityBuilder {
let entity = self.entities_mut().alloc.allocate();
EntityBuilder {
entity,
world: self,
}
}
pub fn create_iter(&mut self) -> CreateIter {
CreateIter(self.entities_mut())
}
pub fn delete_entity(&mut self, entity: Entity) -> Result<(), WrongGeneration> {
self.delete_entities(&[entity])
}
pub fn delete_entities(&mut self, delete: &[Entity]) -> Result<(), WrongGeneration> {
self.delete_components(delete);
self.entities_mut().alloc.kill(delete)
}
pub fn delete_all(&mut self) {
use join::Join;
let entities: Vec<_> = (&*self.entities()).join().collect();
self.delete_entities(&entities).expect(
"Bug: previously collected entities are not valid \
even though access should be exclusive",
);
}
pub fn is_alive(&self, e: Entity) -> bool {
assert!(e.gen().is_alive(), "Generation is dead");
let alloc: &Allocator = &self.entities().alloc;
alloc
.generations
.get(e.id() as usize)
.map(|&x| x == e.gen())
.unwrap_or(false)
}
pub fn maintain(&mut self) {
let deleted = self.entities_mut().alloc.merge();
self.delete_components(&deleted);
self.write_resource::<LazyUpdate>().maintain(&*self);
}
fn delete_components(&mut self, delete: &[Entity]) {
for storage in self.any_storages().iter_mut(&self.res) {
storage.drop(delete);
}
}
pub fn add_bundle<B>(&mut self, bundle: B)
where
B: Bundle,
{
bundle.add_to_world(self);
}
fn any_storages(&self) -> FetchMut<MetaTable<AnyStorage>> {
self.res.fetch_mut::<MetaTable<AnyStorage>>()
}
}
unsafe impl Send for World {}
unsafe impl Sync for World {}
impl Borrow<Resources> for World {
fn borrow(&self) -> &Resources {
&self.res
}
}
impl Component for World {
type Storage = DenseVecStorage<Self>;
}
impl Default for World {
fn default() -> Self {
let mut res = Resources::new();
res.insert(EntitiesRes::default());
res.insert(LazyUpdate::default());
res.insert(MetaTable::<AnyStorage>::new());
World { res }
}
}
pub trait Bundle {
fn add_to_world(self, world: &mut World);
}