| @@ -0,0 +1,9 @@ | |||||
| pub mod read; | |||||
| pub mod read_storage; | |||||
| pub mod write; | |||||
| pub mod write_storage; | |||||
| pub use read::Read; | |||||
| pub use read_storage::ReadStorage; | |||||
| pub use write::Write; | |||||
| pub use write_storage::WriteStorage; | |||||
| @@ -0,0 +1,55 @@ | |||||
| use std::marker::PhantomData; | |||||
| use std::ops::Deref; | |||||
| use crate::{ | |||||
| resource::{Ref, Resource, ResourceId}, | |||||
| system::SystemData, | |||||
| world::{DefaultSetupHandler, SetupHandler, World}, | |||||
| }; | |||||
| pub struct Read<'a, T: 'a, F = DefaultSetupHandler> { | |||||
| inner: Ref<'a, T>, | |||||
| marker: PhantomData<F>, | |||||
| } | |||||
| impl<'a, T, F> Read<'a, T, F> { | |||||
| pub fn new(inner: Ref<'a, T>) -> Self { | |||||
| Self { | |||||
| inner, | |||||
| marker: PhantomData, | |||||
| } | |||||
| } | |||||
| } | |||||
| impl<'a, T, F> Deref for Read<'a, T, F> | |||||
| where | |||||
| T: Resource, | |||||
| { | |||||
| type Target = T; | |||||
| fn deref(&self) -> &T { | |||||
| &*self.inner | |||||
| } | |||||
| } | |||||
| impl<'a, T, F> SystemData<'a> for Read<'a, T, F> | |||||
| where | |||||
| T: Resource, | |||||
| F: SetupHandler<T>, | |||||
| { | |||||
| fn setup(world: &mut World) { | |||||
| F::setup(world) | |||||
| } | |||||
| fn fetch(world: &'a World) -> Self { | |||||
| Self::new(world.borrow()) | |||||
| } | |||||
| fn reads() -> Vec<ResourceId> { | |||||
| vec![ResourceId::new::<T>()] | |||||
| } | |||||
| fn writes() -> Vec<ResourceId> { | |||||
| vec![] | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| use crate::{ | |||||
| component::Component, | |||||
| entity::Entities, | |||||
| misc::TryDefault, | |||||
| resource::{Ref, ResourceId}, | |||||
| storage::{MaskedStorage, StorageWrapper}, | |||||
| system::SystemData, | |||||
| world::World, | |||||
| }; | |||||
| pub type ReadStorage<'a, T> = StorageWrapper<'a, T, Ref<'a, MaskedStorage<T>>>; | |||||
| impl<'a, T> SystemData<'a> for ReadStorage<'a, T> | |||||
| where | |||||
| T: Component, | |||||
| { | |||||
| fn setup(world: &mut World) { | |||||
| world.register_component_with_storage::<T, _>(TryDefault::unwrap_default); | |||||
| } | |||||
| fn fetch(world: &'a World) -> Self { | |||||
| Self::new(world.borrow(), world.borrow()) | |||||
| } | |||||
| fn reads() -> Vec<ResourceId> { | |||||
| vec![ | |||||
| ResourceId::new::<Entities>(), | |||||
| ResourceId::new::<MaskedStorage<T>>(), | |||||
| ] | |||||
| } | |||||
| fn writes() -> Vec<ResourceId> { | |||||
| vec![] | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,64 @@ | |||||
| use std::marker::PhantomData; | |||||
| use std::ops::{Deref, DerefMut}; | |||||
| use crate::{ | |||||
| resource::{RefMut, Resource, ResourceId}, | |||||
| system::SystemData, | |||||
| world::{DefaultSetupHandler, SetupHandler, World}, | |||||
| }; | |||||
| pub struct Write<'a, T: 'a, F = DefaultSetupHandler> { | |||||
| inner: RefMut<'a, T>, | |||||
| marker: PhantomData<F>, | |||||
| } | |||||
| impl<'a, T, F> Write<'a, T, F> { | |||||
| pub fn new(inner: RefMut<'a, T>) -> Self { | |||||
| Self { | |||||
| inner, | |||||
| marker: PhantomData, | |||||
| } | |||||
| } | |||||
| } | |||||
| impl<'a, T, F> Deref for Write<'a, T, F> | |||||
| where | |||||
| T: Resource, | |||||
| { | |||||
| type Target = T; | |||||
| fn deref(&self) -> &T { | |||||
| &*self.inner | |||||
| } | |||||
| } | |||||
| impl<'a, T, F> DerefMut for Write<'a, T, F> | |||||
| where | |||||
| T: Resource, | |||||
| { | |||||
| fn deref_mut(&mut self) -> &mut T { | |||||
| &mut *self.inner | |||||
| } | |||||
| } | |||||
| impl<'a, T, F> SystemData<'a> for Write<'a, T, F> | |||||
| where | |||||
| T: Resource, | |||||
| F: SetupHandler<T>, | |||||
| { | |||||
| fn setup(world: &mut World) { | |||||
| F::setup(world) | |||||
| } | |||||
| fn fetch(world: &'a World) -> Self { | |||||
| Self::new(world.borrow_mut()) | |||||
| } | |||||
| fn reads() -> Vec<ResourceId> { | |||||
| vec![] | |||||
| } | |||||
| fn writes() -> Vec<ResourceId> { | |||||
| vec![ResourceId::new::<T>()] | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| use crate::{ | |||||
| component::Component, | |||||
| entity::Entities, | |||||
| misc::TryDefault, | |||||
| resource::{RefMut, ResourceId}, | |||||
| storage::{MaskedStorage, StorageWrapper}, | |||||
| system::SystemData, | |||||
| world::World, | |||||
| }; | |||||
| pub type WriteStorage<'a, T> = StorageWrapper<'a, T, RefMut<'a, MaskedStorage<T>>>; | |||||
| impl<'a, T> SystemData<'a> for WriteStorage<'a, T> | |||||
| where | |||||
| T: Component, | |||||
| { | |||||
| fn setup(world: &mut World) { | |||||
| world.register_component_with_storage::<T, _>(TryDefault::unwrap_default); | |||||
| } | |||||
| fn fetch(world: &'a World) -> Self { | |||||
| Self::new(world.borrow_mut(), world.borrow()) | |||||
| } | |||||
| fn reads() -> Vec<ResourceId> { | |||||
| vec![ResourceId::new::<Entities>()] | |||||
| } | |||||
| fn writes() -> Vec<ResourceId> { | |||||
| vec![ResourceId::new::<MaskedStorage<T>>()] | |||||
| } | |||||
| } | |||||
| @@ -1,5 +1,7 @@ | |||||
| pub mod access; | |||||
| pub mod component; | pub mod component; | ||||
| pub mod entity; | pub mod entity; | ||||
| pub mod misc; | |||||
| pub mod resource; | pub mod resource; | ||||
| pub mod storage; | pub mod storage; | ||||
| pub mod system; | pub mod system; | ||||
| @@ -20,13 +20,13 @@ fn main() { | |||||
| info!("Application started!"); | info!("Application started!"); | ||||
| let mut world = World::default(); | let mut world = World::default(); | ||||
| world.register::<Position>(); | |||||
| world.register::<Velocity>(); | |||||
| world.register::<Acceleration>(); | |||||
| world.register_component::<Position>(); | |||||
| world.register_component::<Velocity>(); | |||||
| world.register_component::<Acceleration>(); | |||||
| /* | /* | ||||
| for _ in 0..ENTITY_COUNT { | for _ in 0..ENTITY_COUNT { | ||||
| resources | |||||
| world | |||||
| .create_entity() | .create_entity() | ||||
| .with(Velocity::random()) | .with(Velocity::random()) | ||||
| .with(Position::random()) | .with(Position::random()) | ||||
| @@ -0,0 +1,3 @@ | |||||
| pub mod try_default; | |||||
| pub use try_default::TryDefault; | |||||
| @@ -0,0 +1,19 @@ | |||||
| pub trait TryDefault: Sized { | |||||
| fn try_default() -> Result<Self, String>; | |||||
| fn unwrap_default() -> Self { | |||||
| match Self::try_default() { | |||||
| Ok(x) => x, | |||||
| Err(e) => panic!("Failed to create a default value for storage ({:?})", e), | |||||
| } | |||||
| } | |||||
| } | |||||
| impl<T> TryDefault for T | |||||
| where | |||||
| T: Default, | |||||
| { | |||||
| fn try_default() -> Result<Self, String> { | |||||
| Ok(T::default()) | |||||
| } | |||||
| } | |||||
| @@ -1,7 +1,11 @@ | |||||
| mod masked; | |||||
| mod vec; | |||||
| mod masked_storage; | |||||
| mod storage_wrapper; | |||||
| mod vec_storage; | |||||
| pub use masked::MaskedStorage; | |||||
| pub use vec::VecStorage; | |||||
| pub use masked_storage::MaskedStorage; | |||||
| pub use storage_wrapper::StorageWrapper; | |||||
| pub use vec_storage::VecStorage; | |||||
| pub trait Storage<T> {} | |||||
| use crate::misc::TryDefault; | |||||
| pub trait Storage<T>: TryDefault {} | |||||
| @@ -0,0 +1,19 @@ | |||||
| use std::marker::PhantomData; | |||||
| use crate::{entity::Entities, resource::Ref}; | |||||
| pub struct StorageWrapper<'a, T, D> { | |||||
| data: D, | |||||
| entities: Ref<'a, Entities>, | |||||
| phantom: PhantomData<T>, | |||||
| } | |||||
| impl<'a, T, D> StorageWrapper<'a, T, D> { | |||||
| pub fn new(data: D, entities: Ref<'a, Entities>) -> Self { | |||||
| Self { | |||||
| data, | |||||
| entities, | |||||
| phantom: PhantomData, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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::resource::Resources; | |||||
| use crate::world::World; | |||||
| use accessor::AccessorType; | use accessor::AccessorType; | ||||
| @@ -19,14 +19,14 @@ pub trait System<'a> { | |||||
| ) | ) | ||||
| } | } | ||||
| fn setup(&mut self, resources: &mut Resources) { | |||||
| <Self::SystemData as DynamicSystemData>::setup(&self.accessor(), resources) | |||||
| fn setup(&mut self, world: &mut World) { | |||||
| <Self::SystemData as DynamicSystemData>::setup(&self.accessor(), world) | |||||
| } | } | ||||
| fn dispose(self, resources: &mut Resources) | |||||
| fn dispose(self, world: &mut World) | |||||
| where | where | ||||
| Self: Sized, | Self: Sized, | ||||
| { | { | ||||
| let _ = resources; | |||||
| let _ = world; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,13 +1,13 @@ | |||||
| use std::marker::PhantomData; | use std::marker::PhantomData; | ||||
| use crate::resource::{ResourceId, Resources}; | |||||
| use crate::{resource::ResourceId, world::World}; | |||||
| use super::accessor::{Accessor, StaticAccessor}; | use super::accessor::{Accessor, StaticAccessor}; | ||||
| pub trait SystemData<'a> { | pub trait SystemData<'a> { | ||||
| fn setup(resources: &mut Resources); | |||||
| fn setup(world: &mut World); | |||||
| fn fetch(resources: &'a Resources) -> Self; | |||||
| fn fetch(world: &'a World) -> Self; | |||||
| fn reads() -> Vec<ResourceId>; | fn reads() -> Vec<ResourceId>; | ||||
| @@ -17,9 +17,9 @@ pub trait SystemData<'a> { | |||||
| pub trait DynamicSystemData<'a> { | pub trait DynamicSystemData<'a> { | ||||
| type Accessor: Accessor; | type Accessor: Accessor; | ||||
| fn setup(accessor: &Self::Accessor, resources: &mut Resources); | |||||
| fn setup(accessor: &Self::Accessor, world: &mut World); | |||||
| fn fetch(access: &Self::Accessor, resources: &'a Resources) -> Self; | |||||
| fn fetch(access: &Self::Accessor, world: &'a World) -> Self; | |||||
| } | } | ||||
| /* SystemData */ | /* SystemData */ | ||||
| @@ -28,9 +28,9 @@ impl<'a, T> SystemData<'a> for PhantomData<T> | |||||
| where | where | ||||
| T: ?Sized, | T: ?Sized, | ||||
| { | { | ||||
| fn setup(_: &mut Resources) {} | |||||
| fn setup(_: &mut World) {} | |||||
| fn fetch(_: &Resources) -> Self { | |||||
| fn fetch(_: &World) -> Self { | |||||
| PhantomData | PhantomData | ||||
| } | } | ||||
| @@ -51,12 +51,12 @@ where | |||||
| { | { | ||||
| type Accessor = StaticAccessor<T>; | type Accessor = StaticAccessor<T>; | ||||
| fn setup(_: &StaticAccessor<T>, resources: &mut Resources) { | |||||
| T::setup(resources); | |||||
| fn setup(_: &StaticAccessor<T>, world: &mut World) { | |||||
| T::setup(world); | |||||
| } | } | ||||
| fn fetch(_: &StaticAccessor<T>, resources: &'a Resources) -> Self { | |||||
| T::fetch(resources) | |||||
| fn fetch(_: &StaticAccessor<T>, world: &'a World) -> Self { | |||||
| T::fetch(world) | |||||
| } | } | ||||
| } | } | ||||
| @@ -68,18 +68,18 @@ mod impl_system_data { | |||||
| impl<'a, $($ty),*> SystemData<'a> for ( $( $ty , )* ) | impl<'a, $($ty),*> SystemData<'a> for ( $( $ty , )* ) | ||||
| where $( $ty : SystemData<'a> ),* | where $( $ty : SystemData<'a> ),* | ||||
| { | { | ||||
| fn setup(resources: &mut Resources) { | |||||
| fn setup(world: &mut World) { | |||||
| #![allow(unused_variables)] | #![allow(unused_variables)] | ||||
| $( | $( | ||||
| <$ty as SystemData>::setup(&mut *resources); | |||||
| <$ty as SystemData>::setup(&mut *world); | |||||
| )* | )* | ||||
| } | } | ||||
| fn fetch(resources: &'a Resources) -> Self { | |||||
| fn fetch(world: &'a World) -> Self { | |||||
| #![allow(unused_variables)] | #![allow(unused_variables)] | ||||
| ( $( <$ty as SystemData<'a>>::fetch(resources), )* ) | |||||
| ( $( <$ty as SystemData<'a>>::fetch(world), )* ) | |||||
| } | } | ||||
| fn reads() -> Vec<ResourceId> { | fn reads() -> Vec<ResourceId> { | ||||
| @@ -1,18 +1,29 @@ | |||||
| mod setup; | |||||
| pub use setup::{DefaultSetupHandler, SetupHandler}; | |||||
| use std::ops::{Deref, DerefMut}; | use std::ops::{Deref, DerefMut}; | ||||
| use crate::{component::Component, entity::Entities, resource::Resources, storage::MaskedStorage}; | |||||
| use crate::{ | |||||
| access::{Read, ReadStorage, WriteStorage}, | |||||
| component::Component, | |||||
| entity::Entities, | |||||
| resource::{Ref, RefMut, Resource, Resources}, | |||||
| storage::MaskedStorage, | |||||
| system::SystemData, | |||||
| }; | |||||
| pub struct World(Resources); | pub struct World(Resources); | ||||
| impl World { | impl World { | ||||
| pub fn register<T: Component>(&mut self) | |||||
| pub fn register_component<T: Component>(&mut self) | |||||
| where | where | ||||
| T::Storage: Default, | T::Storage: Default, | ||||
| { | { | ||||
| self.register_with_storage::<T, _>(Default::default); | |||||
| self.register_component_with_storage::<T, _>(Default::default); | |||||
| } | } | ||||
| pub fn register_with_storage<T, F>(&mut self, storage: F) | |||||
| pub fn register_component_with_storage<T, F>(&mut self, storage: F) | |||||
| where | where | ||||
| T: Component, | T: Component, | ||||
| F: FnOnce() -> T::Storage, | F: FnOnce() -> T::Storage, | ||||
| @@ -20,6 +31,34 @@ impl World { | |||||
| self.entry() | self.entry() | ||||
| .or_insert_with(move || MaskedStorage::<T>::new(storage())); | .or_insert_with(move || MaskedStorage::<T>::new(storage())); | ||||
| } | } | ||||
| pub fn register_resource<T: Resource>(&mut self, res: T) { | |||||
| self.0.insert(res); | |||||
| } | |||||
| pub fn resource<T: Resource>(&self) -> Ref<T> { | |||||
| self.0.borrow() | |||||
| } | |||||
| pub fn resource_mut<T: Resource>(&self) -> RefMut<T> { | |||||
| self.0.borrow_mut() | |||||
| } | |||||
| pub fn entities(&self) -> Read<Entities> { | |||||
| Read::fetch(&self) | |||||
| } | |||||
| pub fn entities_mut(&self) -> RefMut<Entities> { | |||||
| self.resource_mut() | |||||
| } | |||||
| pub fn component<T: Component>(&self) -> ReadStorage<T> { | |||||
| ReadStorage::fetch(&self) | |||||
| } | |||||
| pub fn component_mut<T: Component>(&self) -> WriteStorage<T> { | |||||
| WriteStorage::fetch(&self) | |||||
| } | |||||
| } | } | ||||
| impl Default for World { | impl Default for World { | ||||
| @@ -0,0 +1,18 @@ | |||||
| use crate::resource::Resource; | |||||
| use super::World; | |||||
| pub trait SetupHandler<T>: Sized { | |||||
| fn setup(world: &mut World); | |||||
| } | |||||
| pub struct DefaultSetupHandler; | |||||
| impl<T> SetupHandler<T> for DefaultSetupHandler | |||||
| where | |||||
| T: Default + Resource, | |||||
| { | |||||
| fn setup(world: &mut World) { | |||||
| world.entry().or_insert_with(T::default); | |||||
| } | |||||
| } | |||||