| @@ -0,0 +1,42 @@ | |||||
| use proc_macro2::TokenStream; | |||||
| use syn::{ | |||||
| parse::{Parse, ParseStream, Result}, | |||||
| DeriveInput, Path, | |||||
| }; | |||||
| pub fn execute(ast: &DeriveInput) -> TokenStream { | |||||
| let name = &ast.ident; | |||||
| let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); | |||||
| let storage = ast | |||||
| .attrs | |||||
| .iter() | |||||
| .find(|attr| attr.path.segments[0].ident == "storage") | |||||
| .map(|attr| { | |||||
| syn::parse2::<StorageAttribute>(attr.tokens.clone()) | |||||
| .unwrap() | |||||
| .storage | |||||
| }) | |||||
| .unwrap_or_else(|| parse_quote!(DenseVecStorage)); | |||||
| quote! { | |||||
| impl #impl_generics async_ecs::component::Component for #name #ty_generics #where_clause { | |||||
| type Storage = #storage<Self>; | |||||
| } | |||||
| } | |||||
| } | |||||
| struct StorageAttribute { | |||||
| storage: Path, | |||||
| } | |||||
| impl Parse for StorageAttribute { | |||||
| fn parse(input: ParseStream) -> Result<Self> { | |||||
| let content; | |||||
| let _parenthesized_token = parenthesized!(content in input); | |||||
| Ok(StorageAttribute { | |||||
| storage: content.parse()?, | |||||
| }) | |||||
| } | |||||
| } | |||||
| @@ -7,6 +7,7 @@ extern crate quote; | |||||
| #[macro_use] | #[macro_use] | ||||
| extern crate syn; | extern crate syn; | ||||
| mod component; | |||||
| mod system_data; | mod system_data; | ||||
| use proc_macro::TokenStream; | use proc_macro::TokenStream; | ||||
| @@ -19,3 +20,12 @@ pub fn system_data(input: TokenStream) -> TokenStream { | |||||
| gen.into() | gen.into() | ||||
| } | } | ||||
| #[proc_macro_derive(Component, attributes(storage))] | |||||
| pub fn component(input: TokenStream) -> TokenStream { | |||||
| let ast = syn::parse(input).unwrap(); | |||||
| let gen = component::execute(&ast); | |||||
| gen.into() | |||||
| } | |||||
| @@ -73,7 +73,8 @@ fn gen_identifiers(fields: &Punctuated<Field, Comma>) -> Vec<Ident> { | |||||
| fn constrain_system_data_types(clause: &mut WhereClause, fetch_lt: &Lifetime, tys: &[Type]) { | fn constrain_system_data_types(clause: &mut WhereClause, fetch_lt: &Lifetime, tys: &[Type]) { | ||||
| for ty in tys.iter() { | for ty in tys.iter() { | ||||
| let where_predicate: WherePredicate = parse_quote!(#ty : async_ecs::system::SystemData< #fetch_lt >); | |||||
| let where_predicate: WherePredicate = | |||||
| parse_quote!(#ty : async_ecs::system::SystemData< #fetch_lt >); | |||||
| clause.predicates.push(where_predicate); | clause.predicates.push(where_predicate); | ||||
| } | } | ||||
| } | } | ||||
| @@ -7,6 +7,8 @@ edition = "2018" | |||||
| [dependencies] | [dependencies] | ||||
| async-ecs-derive = "0.1" | async-ecs-derive = "0.1" | ||||
| env_logger = "0.8" | env_logger = "0.8" | ||||
| hashbrown = "0.9" | |||||
| hibitset = "0.6" | |||||
| log = "0.4" | log = "0.4" | ||||
| mopa = "0.2" | mopa = "0.2" | ||||
| rand = "0.7" | rand = "0.7" | ||||
| @@ -0,0 +1,7 @@ | |||||
| use std::any::Any; | |||||
| use crate::storage::Storage; | |||||
| pub trait Component: Any + Sized { | |||||
| type Storage: Storage<Self> + Any + Send + Sync; | |||||
| } | |||||
| @@ -0,0 +1,2 @@ | |||||
| #[derive(Default)] | |||||
| pub struct Entities; | |||||
| @@ -1,4 +1,10 @@ | |||||
| pub mod resources; | |||||
| pub mod component; | |||||
| pub mod entity; | |||||
| pub mod resource; | |||||
| pub mod storage; | |||||
| pub mod system; | pub mod system; | ||||
| pub mod world; | |||||
| pub use resources::Resources; | |||||
| pub use resource::Resources; | |||||
| pub use storage::VecStorage; | |||||
| pub use world::World; | |||||
| @@ -1,10 +1,14 @@ | |||||
| use log::info; | use log::info; | ||||
| use async_ecs::{VecStorage, World}; | |||||
| use async_ecs_derive::Component; | |||||
| use rand::random; | |||||
| /* | /* | ||||
| use std::time::{Duration, Instant}; | use std::time::{Duration, Instant}; | ||||
| use async_ecs::Resources; | use async_ecs::Resources; | ||||
| use rand::random; | |||||
| */ | */ | ||||
| fn main() { | fn main() { | ||||
| @@ -15,12 +19,12 @@ fn main() { | |||||
| info!("Application started!"); | info!("Application started!"); | ||||
| /* | |||||
| let mut resources = Resources::new(); | |||||
| resources.register::<Position>(); | |||||
| resources.register::<Velocity>(); | |||||
| resources.register::<Acceleration>(); | |||||
| let mut world = World::default(); | |||||
| world.register::<Position>(); | |||||
| world.register::<Velocity>(); | |||||
| world.register::<Acceleration>(); | |||||
| /* | |||||
| for _ in 0..ENTITY_COUNT { | for _ in 0..ENTITY_COUNT { | ||||
| resources | resources | ||||
| .create_entity() | .create_entity() | ||||
| @@ -61,7 +65,6 @@ fn main() { | |||||
| */ | */ | ||||
| } | } | ||||
| /* | |||||
| const ENTITY_COUNT: usize = 3_000_000; | const ENTITY_COUNT: usize = 3_000_000; | ||||
| const REPEAT_COUNT: u32 = 100; | const REPEAT_COUNT: u32 = 100; | ||||
| @@ -115,7 +118,7 @@ impl Acceleration { | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* | |||||
| impl<'a> System<'a> for Move { | impl<'a> System<'a> for Move { | ||||
| type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>); | type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>); | ||||
| @@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut}; | |||||
| use std::sync::atomic::{AtomicUsize, Ordering}; | use std::sync::atomic::{AtomicUsize, Ordering}; | ||||
| #[derive(Debug)] | #[derive(Debug)] | ||||
| pub struct TrustCell<T> { | |||||
| pub struct Cell<T> { | |||||
| flag: AtomicUsize, | flag: AtomicUsize, | ||||
| inner: UnsafeCell<T>, | inner: UnsafeCell<T>, | ||||
| } | } | ||||
| @@ -37,11 +37,11 @@ macro_rules! borrow_panic { | |||||
| }}; | }}; | ||||
| } | } | ||||
| /* TrustCell */ | |||||
| /* Cell */ | |||||
| impl<T> TrustCell<T> { | |||||
| impl<T> Cell<T> { | |||||
| pub fn new(inner: T) -> Self { | pub fn new(inner: T) -> Self { | ||||
| TrustCell { | |||||
| Cell { | |||||
| flag: AtomicUsize::new(0), | flag: AtomicUsize::new(0), | ||||
| inner: UnsafeCell::new(inner), | inner: UnsafeCell::new(inner), | ||||
| } | } | ||||
| @@ -236,7 +236,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn allow_multiple_reads() { | fn allow_multiple_reads() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let a = cell.borrow(); | let a = cell.borrow(); | ||||
| let b = cell.borrow(); | let b = cell.borrow(); | ||||
| @@ -246,7 +246,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn allow_clone_reads() { | fn allow_clone_reads() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let a = cell.borrow(); | let a = cell.borrow(); | ||||
| let b = a.clone(); | let b = a.clone(); | ||||
| @@ -256,7 +256,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn allow_single_write() { | fn allow_single_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| { | { | ||||
| let mut a = cell.borrow_mut(); | let mut a = cell.borrow_mut(); | ||||
| @@ -270,7 +270,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| #[should_panic(expected = "but it was already borrowed mutably")] | #[should_panic(expected = "but it was already borrowed mutably")] | ||||
| fn panic_write_and_read() { | fn panic_write_and_read() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let mut a = cell.borrow_mut(); | let mut a = cell.borrow_mut(); | ||||
| *a = 7; | *a = 7; | ||||
| @@ -281,7 +281,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| #[should_panic(expected = "but it was already borrowed")] | #[should_panic(expected = "but it was already borrowed")] | ||||
| fn panic_write_and_write() { | fn panic_write_and_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let mut a = cell.borrow_mut(); | let mut a = cell.borrow_mut(); | ||||
| *a = 7; | *a = 7; | ||||
| @@ -292,7 +292,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| #[should_panic(expected = "but it was already borrowed")] | #[should_panic(expected = "but it was already borrowed")] | ||||
| fn panic_read_and_write() { | fn panic_read_and_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let _a = cell.borrow(); | let _a = cell.borrow(); | ||||
| @@ -301,7 +301,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn try_write_and_read() { | fn try_write_and_read() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let mut a = cell.try_borrow_mut().unwrap(); | let mut a = cell.try_borrow_mut().unwrap(); | ||||
| *a = 7; | *a = 7; | ||||
| @@ -313,7 +313,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn try_write_and_write() { | fn try_write_and_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let mut a = cell.try_borrow_mut().unwrap(); | let mut a = cell.try_borrow_mut().unwrap(); | ||||
| *a = 7; | *a = 7; | ||||
| @@ -325,7 +325,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn try_read_and_write() { | fn try_read_and_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let _a = cell.try_borrow().unwrap(); | let _a = cell.try_borrow().unwrap(); | ||||
| @@ -334,7 +334,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn cloned_borrow_does_not_allow_write() { | fn cloned_borrow_does_not_allow_write() { | ||||
| let cell = TrustCell::new(5); | |||||
| let cell = Cell::new(5); | |||||
| let a = cell.borrow(); | let a = cell.borrow(); | ||||
| let b = a.clone(); | let b = a.clone(); | ||||
| @@ -402,7 +402,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_map_box() { | fn ref_map_box() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let r: Ref<'_, Box<usize>> = cell.borrow(); | let r: Ref<'_, Box<usize>> = cell.borrow(); | ||||
| assert_eq!(&**r, &10); | assert_eq!(&**r, &10); | ||||
| @@ -413,7 +413,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_map_preserves_flag() { | fn ref_map_preserves_flag() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let r: Ref<'_, Box<usize>> = cell.borrow(); | let r: Ref<'_, Box<usize>> = cell.borrow(); | ||||
| assert_eq!(cell.flag.load(Ordering::SeqCst), 1); | assert_eq!(cell.flag.load(Ordering::SeqCst), 1); | ||||
| @@ -423,7 +423,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_map_retains_borrow() { | fn ref_map_retains_borrow() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let _r: Ref<'_, usize> = cell.borrow().map(Box::as_ref); | let _r: Ref<'_, usize> = cell.borrow().map(Box::as_ref); | ||||
| assert_eq!(cell.flag.load(Ordering::SeqCst), 1); | assert_eq!(cell.flag.load(Ordering::SeqCst), 1); | ||||
| @@ -434,7 +434,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_map_drops_borrow() { | fn ref_map_drops_borrow() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let r: Ref<'_, usize> = cell.borrow().map(Box::as_ref); | let r: Ref<'_, usize> = cell.borrow().map(Box::as_ref); | ||||
| @@ -445,7 +445,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_mut_map_box() { | fn ref_mut_map_box() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| { | { | ||||
| let mut r: RefMut<'_, Box<usize>> = cell.borrow_mut(); | let mut r: RefMut<'_, Box<usize>> = cell.borrow_mut(); | ||||
| @@ -459,7 +459,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_mut_map_preserves_flag() { | fn ref_mut_map_preserves_flag() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let r: RefMut<'_, Box<usize>> = cell.borrow_mut(); | let r: RefMut<'_, Box<usize>> = cell.borrow_mut(); | ||||
| assert_eq!(cell.flag.load(Ordering::SeqCst), std::usize::MAX); | assert_eq!(cell.flag.load(Ordering::SeqCst), std::usize::MAX); | ||||
| @@ -470,7 +470,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| #[should_panic(expected = "but it was already borrowed")] | #[should_panic(expected = "but it was already borrowed")] | ||||
| fn ref_mut_map_retains_mut_borrow() { | fn ref_mut_map_retains_mut_borrow() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let _rr: RefMut<'_, usize> = cell.borrow_mut().map(Box::as_mut); | let _rr: RefMut<'_, usize> = cell.borrow_mut().map(Box::as_mut); | ||||
| @@ -479,7 +479,7 @@ mod tests { | |||||
| #[test] | #[test] | ||||
| fn ref_mut_map_drops_borrow() { | fn ref_mut_map_drops_borrow() { | ||||
| let cell = TrustCell::new(Box::new(10)); | |||||
| let cell = Cell::new(Box::new(10)); | |||||
| let r: RefMut<'_, usize> = cell.borrow_mut().map(Box::as_mut); | let r: RefMut<'_, usize> = cell.borrow_mut().map(Box::as_mut); | ||||
| @@ -0,0 +1,41 @@ | |||||
| use std::marker::PhantomData; | |||||
| use hashbrown::hash_map::{DefaultHashBuilder, Entry as HbEntry}; | |||||
| use super::{cell::Cell, RefMut, Resource, ResourceId}; | |||||
| pub struct Entry<'a, T: 'a> { | |||||
| inner: Inner<'a>, | |||||
| marker: PhantomData<T>, | |||||
| } | |||||
| pub type Inner<'a> = HbEntry<'a, ResourceId, Cell<Box<dyn Resource>>, DefaultHashBuilder>; | |||||
| impl<'a, T> Entry<'a, T> | |||||
| where | |||||
| T: Resource + 'a, | |||||
| { | |||||
| pub fn new(inner: Inner<'a>) -> Self { | |||||
| Self { | |||||
| inner, | |||||
| marker: PhantomData, | |||||
| } | |||||
| } | |||||
| pub fn or_insert(self, v: T) -> RefMut<'a, T> { | |||||
| self.or_insert_with(move || v) | |||||
| } | |||||
| pub fn or_insert_with<F>(self, f: F) -> RefMut<'a, T> | |||||
| where | |||||
| F: FnOnce() -> T, | |||||
| { | |||||
| let inner = self.inner.or_insert_with(move || Cell::new(Box::new(f()))); | |||||
| let inner = inner.borrow_mut().map(Box::as_mut); | |||||
| RefMut { | |||||
| inner, | |||||
| phantom: PhantomData, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,17 +1,19 @@ | |||||
| pub mod cell; | pub mod cell; | ||||
| pub mod entry; | |||||
| use std::any::TypeId; | use std::any::TypeId; | ||||
| use std::collections::HashMap; | |||||
| use std::marker::PhantomData; | use std::marker::PhantomData; | ||||
| use std::ops::{Deref, DerefMut}; | use std::ops::{Deref, DerefMut}; | ||||
| use hashbrown::HashMap; | |||||
| use mopa::Any; | use mopa::Any; | ||||
| use cell::{Ref as CellRef, RefMut as CellRefMut, TrustCell}; | |||||
| use cell::{Cell, Ref as CellRef, RefMut as CellRefMut}; | |||||
| use entry::Entry; | |||||
| #[derive(Default)] | #[derive(Default)] | ||||
| pub struct Resources { | pub struct Resources { | ||||
| resources: HashMap<ResourceId, TrustCell<Box<dyn Resource>>>, | |||||
| resources: HashMap<ResourceId, Cell<Box<dyn Resource>>>, | |||||
| } | } | ||||
| #[derive(Debug, Hash, Eq, PartialEq)] | #[derive(Debug, Hash, Eq, PartialEq)] | ||||
| @@ -47,12 +49,19 @@ macro_rules! fetch_panic { | |||||
| /* Resources */ | /* Resources */ | ||||
| impl Resources { | impl Resources { | ||||
| pub fn entry<R>(&mut self) -> Entry<R> | |||||
| where | |||||
| R: Resource, | |||||
| { | |||||
| Entry::new(self.resources.entry(ResourceId::new::<R>())) | |||||
| } | |||||
| pub fn insert<R>(&mut self, r: R) | pub fn insert<R>(&mut self, r: R) | ||||
| where | where | ||||
| R: Resource, | R: Resource, | ||||
| { | { | ||||
| self.resources | self.resources | ||||
| .insert(ResourceId::new::<R>(), TrustCell::new(Box::new(r))); | |||||
| .insert(ResourceId::new::<R>(), Cell::new(Box::new(r))); | |||||
| } | } | ||||
| pub fn remove<R>(&mut self) -> Option<R> | pub fn remove<R>(&mut self) -> Option<R> | ||||
| @@ -61,7 +70,7 @@ impl Resources { | |||||
| { | { | ||||
| self.resources | self.resources | ||||
| .remove(&ResourceId::new::<R>()) | .remove(&ResourceId::new::<R>()) | ||||
| .map(TrustCell::into_inner) | |||||
| .map(Cell::into_inner) | |||||
| .map(|x: Box<dyn Resource>| x.downcast()) | .map(|x: Box<dyn Resource>| x.downcast()) | ||||
| .map(|x: Result<Box<R>, _>| x.ok().unwrap()) | .map(|x: Result<Box<R>, _>| x.ok().unwrap()) | ||||
| .map(|x| *x) | .map(|x| *x) | ||||
| @@ -103,7 +112,7 @@ impl Resources { | |||||
| R: Resource, | R: Resource, | ||||
| { | { | ||||
| self.resources.get(&ResourceId::new::<R>()).map(|r| RefMut { | self.resources.get(&ResourceId::new::<R>()).map(|r| RefMut { | ||||
| inner: CellRefMut::map(r.borrow_mut(), Box::as_mut), | |||||
| inner: r.borrow_mut().map(Box::as_mut), | |||||
| phantom: PhantomData, | phantom: PhantomData, | ||||
| }) | }) | ||||
| } | } | ||||
| @@ -116,7 +125,7 @@ impl Resources { | |||||
| pub fn get_resource_mut(&mut self, id: ResourceId) -> Option<&mut dyn Resource> { | pub fn get_resource_mut(&mut self, id: ResourceId) -> Option<&mut dyn Resource> { | ||||
| self.resources | self.resources | ||||
| .get_mut(&id) | .get_mut(&id) | ||||
| .map(TrustCell::get_mut) | |||||
| .map(Cell::get_mut) | |||||
| .map(Box::as_mut) | .map(Box::as_mut) | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,17 @@ | |||||
| use hibitset::BitSet; | |||||
| use crate::component::Component; | |||||
| pub struct MaskedStorage<T: Component> { | |||||
| mask: BitSet, | |||||
| inner: T::Storage, | |||||
| } | |||||
| impl<T: Component> MaskedStorage<T> { | |||||
| pub fn new(inner: T::Storage) -> Self { | |||||
| Self { | |||||
| mask: BitSet::new(), | |||||
| inner, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| mod masked; | |||||
| mod vec; | |||||
| pub use masked::MaskedStorage; | |||||
| pub use vec::VecStorage; | |||||
| pub trait Storage<T> {} | |||||
| @@ -0,0 +1,13 @@ | |||||
| use std::mem::MaybeUninit; | |||||
| use super::Storage; | |||||
| pub struct VecStorage<T>(Vec<MaybeUninit<T>>); | |||||
| impl<T> Storage<T> for VecStorage<T> {} | |||||
| impl<T> Default for VecStorage<T> { | |||||
| fn default() -> Self { | |||||
| Self(Vec::new()) | |||||
| } | |||||
| } | |||||
| @@ -1,7 +1,7 @@ | |||||
| use std::marker::PhantomData; | use std::marker::PhantomData; | ||||
| use std::ops::Deref; | use std::ops::Deref; | ||||
| use crate::resources::ResourceId; | |||||
| use crate::resource::ResourceId; | |||||
| use super::{DynamicSystemData, System, SystemData}; | use super::{DynamicSystemData, System, SystemData}; | ||||
| @@ -4,7 +4,7 @@ mod system_data; | |||||
| pub use accessor::{Accessor, AccessorCow}; | pub use accessor::{Accessor, AccessorCow}; | ||||
| pub use system_data::{DynamicSystemData, SystemData}; | pub use system_data::{DynamicSystemData, SystemData}; | ||||
| use crate::resources::Resources; | |||||
| use crate::resource::Resources; | |||||
| use accessor::AccessorType; | use accessor::AccessorType; | ||||
| @@ -1,6 +1,6 @@ | |||||
| use std::marker::PhantomData; | use std::marker::PhantomData; | ||||
| use crate::resources::{ResourceId, Resources}; | |||||
| use crate::resource::{ResourceId, Resources}; | |||||
| use super::accessor::{Accessor, StaticAccessor}; | use super::accessor::{Accessor, StaticAccessor}; | ||||
| @@ -0,0 +1,47 @@ | |||||
| use std::ops::{Deref, DerefMut}; | |||||
| use crate::{component::Component, entity::Entities, resource::Resources, storage::MaskedStorage}; | |||||
| pub struct World(Resources); | |||||
| impl World { | |||||
| pub fn register<T: Component>(&mut self) | |||||
| where | |||||
| T::Storage: Default, | |||||
| { | |||||
| self.register_with_storage::<T, _>(Default::default); | |||||
| } | |||||
| pub fn register_with_storage<T, F>(&mut self, storage: F) | |||||
| where | |||||
| T: Component, | |||||
| F: FnOnce() -> T::Storage, | |||||
| { | |||||
| self.entry() | |||||
| .or_insert_with(move || MaskedStorage::<T>::new(storage())); | |||||
| } | |||||
| } | |||||
| impl Default for World { | |||||
| fn default() -> Self { | |||||
| let mut resources = Resources::default(); | |||||
| resources.insert(Entities::default()); | |||||
| Self(resources) | |||||
| } | |||||
| } | |||||
| impl Deref for World { | |||||
| type Target = Resources; | |||||
| fn deref(&self) -> &Self::Target { | |||||
| &self.0 | |||||
| } | |||||
| } | |||||
| impl DerefMut for World { | |||||
| fn deref_mut(&mut self) -> &mut Self::Target { | |||||
| &mut self.0 | |||||
| } | |||||
| } | |||||