diff options
Diffstat (limited to 'ecs/src')
-rw-r--r-- | ecs/src/component.rs | 34 | ||||
-rw-r--r-- | ecs/src/system.rs | 24 | ||||
-rw-r--r-- | ecs/src/system/stateful.rs | 67 |
3 files changed, 123 insertions, 2 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs index 4829050..8119e93 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -1,5 +1,6 @@ use std::any::{Any, TypeId}; use std::fmt::Debug; +use std::ops::{Deref, DerefMut}; use seq_macro::seq; @@ -112,3 +113,36 @@ macro_rules! inner { seq!(C in 0..=64 { inner!(C); }); + +/// Holds a component which is local to a single system. +#[derive(Debug)] +pub struct Local<'world, Value> +{ + value: &'world mut Value, +} + +impl<'world, Value> Local<'world, Value> +{ + pub(crate) fn new(value: &'world mut Value) -> Self + { + Self { value } + } +} + +impl<'world, Value> Deref for Local<'world, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + self.value + } +} + +impl<'world, Value> DerefMut for Local<'world, Value> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + &mut self.value + } +} diff --git a/ecs/src/system.rs b/ecs/src/system.rs index ecf1885..8f4d0b0 100644 --- a/ecs/src/system.rs +++ b/ecs/src/system.rs @@ -1,14 +1,21 @@ use std::any::Any; +use std::convert::Infallible; use std::fmt::Debug; use crate::component::Sequence as ComponentSequence; use crate::{ComponentStorage, Query}; +pub mod stateful; + pub trait System<Impl>: 'static { type Query<'a>; - fn run(&self, component_storage: &mut ComponentStorage); + type Input; + + fn initialize(self, input: Self::Input) -> Self; + + fn run(&mut self, component_storage: &mut ComponentStorage); fn into_type_erased(self) -> TypeErased; } @@ -18,9 +25,15 @@ where Func: Fn(Query<Comps>) + 'static, Comps: ComponentSequence, { + type Input = Infallible; type Query<'a> = Query<'a, Comps>; - fn run(&self, component_storage: &mut ComponentStorage) + fn initialize(self, _input: Self::Input) -> Self + { + self + } + + fn run(&mut self, component_storage: &mut ComponentStorage) { self(Query::new(component_storage)); } @@ -38,6 +51,13 @@ where } } +pub trait Into<Impl> +{ + type System; + + fn into_system(self) -> Self::System; +} + pub struct TypeErased { data: Box<dyn Any>, diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs new file mode 100644 index 0000000..b641cf2 --- /dev/null +++ b/ecs/src/system/stateful.rs @@ -0,0 +1,67 @@ +use std::marker::PhantomData; + +use crate::component::Local; +use crate::system::{System, TypeErased}; +use crate::{ComponentStorage, Query}; + +/// A stateful system. +pub struct Stateful<Func, LocalComponent, Comps> +{ + func: Func, + local_component: Option<LocalComponent>, + _comps_pd: PhantomData<Comps>, +} + +impl<Func: 'static, Comps: 'static, LocalComponent: 'static> + System<fn(Query<Comps>, Local<LocalComponent>)> + for Stateful<Func, LocalComponent, Comps> +where + Func: Fn(Query<Comps>, Local<LocalComponent>), +{ + type Input = LocalComponent; + type Query<'a> = Query<'a, Comps>; + + fn initialize(mut self, input: Self::Input) -> Self + { + self.local_component = Some(input); + + self + } + + fn run(&mut self, component_storage: &mut ComponentStorage) + { + (self.func)( + Query::new(component_storage), + Local::new(self.local_component.as_mut().unwrap()), + ); + } + + fn into_type_erased(self) -> TypeErased + { + TypeErased { + data: Box::new(self), + func: Box::new(move |data, component_storage| { + let this = data.downcast_mut::<Self>().unwrap(); + + this.run(component_storage); + }), + } + } +} + +impl<Func: 'static, Comps, LocalComponent: 'static> + crate::system::Into<fn(Query<Comps>, Local<LocalComponent>)> for Func +where + Func: Fn(Query<Comps>, Local<LocalComponent>), +{ + type System = Stateful<Func, LocalComponent, Comps>; + + fn into_system(self) -> Self::System + { + Self::System { + func: self, + local_component: None, + _comps_pd: PhantomData, + } + } +} |