| @@ -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 entity; | |||
| pub mod misc; | |||
| pub mod resource; | |||
| pub mod storage; | |||
| pub mod system; | |||
| @@ -20,13 +20,13 @@ fn main() { | |||
| info!("Application started!"); | |||
| 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 { | |||
| resources | |||
| world | |||
| .create_entity() | |||
| .with(Velocity::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 system_data::{DynamicSystemData, SystemData}; | |||
| use crate::resource::Resources; | |||
| use crate::world::World; | |||
| 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 | |||
| Self: Sized, | |||
| { | |||
| let _ = resources; | |||
| let _ = world; | |||
| } | |||
| } | |||
| @@ -1,13 +1,13 @@ | |||
| use std::marker::PhantomData; | |||
| use crate::resource::{ResourceId, Resources}; | |||
| use crate::{resource::ResourceId, world::World}; | |||
| use super::accessor::{Accessor, StaticAccessor}; | |||
| 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>; | |||
| @@ -17,9 +17,9 @@ pub trait SystemData<'a> { | |||
| pub trait DynamicSystemData<'a> { | |||
| 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 */ | |||
| @@ -28,9 +28,9 @@ impl<'a, T> SystemData<'a> for PhantomData<T> | |||
| where | |||
| T: ?Sized, | |||
| { | |||
| fn setup(_: &mut Resources) {} | |||
| fn setup(_: &mut World) {} | |||
| fn fetch(_: &Resources) -> Self { | |||
| fn fetch(_: &World) -> Self { | |||
| PhantomData | |||
| } | |||
| @@ -51,12 +51,12 @@ where | |||
| { | |||
| 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 , )* ) | |||
| where $( $ty : SystemData<'a> ),* | |||
| { | |||
| fn setup(resources: &mut Resources) { | |||
| fn setup(world: &mut World) { | |||
| #![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)] | |||
| ( $( <$ty as SystemData<'a>>::fetch(resources), )* ) | |||
| ( $( <$ty as SystemData<'a>>::fetch(world), )* ) | |||
| } | |||
| fn reads() -> Vec<ResourceId> { | |||
| @@ -1,18 +1,29 @@ | |||
| mod setup; | |||
| pub use setup::{DefaultSetupHandler, SetupHandler}; | |||
| 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); | |||
| impl World { | |||
| pub fn register<T: Component>(&mut self) | |||
| pub fn register_component<T: Component>(&mut self) | |||
| where | |||
| 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 | |||
| T: Component, | |||
| F: FnOnce() -> T::Storage, | |||
| @@ -20,6 +31,34 @@ impl World { | |||
| self.entry() | |||
| .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 { | |||
| @@ -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); | |||
| } | |||
| } | |||