diff options
Diffstat (limited to 'ecs/src/system.rs')
-rw-r--r-- | ecs/src/system.rs | 170 |
1 files changed, 132 insertions, 38 deletions
diff --git a/ecs/src/system.rs b/ecs/src/system.rs index 046d25b..b410d8f 100644 --- a/ecs/src/system.rs +++ b/ecs/src/system.rs @@ -3,17 +3,25 @@ use std::convert::Infallible; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; -use std::panic::{RefUnwindSafe, UnwindSafe}; +use ecs_macros::Component; use seq_macro::seq; use crate::component::{ Component, + FromLockedOptional as FromLockedOptionalComponent, FromOptional as FromOptionalComponent, FromOptionalMut as FromOptionalMutComponent, }; -use crate::lock::{ReadGuard, WriteGuard}; -use crate::tuple::{ReduceElement as TupleReduceElement, With as TupleWith}; +use crate::lock::{ + Error as LockError, + Lock, + MappedReadGuard, + MappedWriteGuard, + ReadGuard, + WriteGuard, +}; +use crate::tuple::{ReduceElement as TupleReduceElement, Tuple}; use crate::World; pub mod stateful; @@ -47,8 +55,8 @@ macro_rules! impl_system { impl<'world, Func, #(TParam~I,)*> System<'world, fn(#(TParam~I,)*)> for Func where - Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, - #(TParam~I: Param<'world, Flags = NoInitParamFlag>,)* + Func: Fn(#(TParam~I,)*) + Copy + 'static, + #(TParam~I: Param<'world, Input = ()>,)* { type Input = Infallible; @@ -121,7 +129,7 @@ pub trait Into<Impl> pub struct TypeErased { - data: Box<dyn Any + RefUnwindSafe + UnwindSafe>, + data: Box<dyn Any>, run: Box<TypeErasedRunFn>, } @@ -149,13 +157,12 @@ impl Debug for TypeErased } /// Function in [`TypeErased`] used to run the system. -type TypeErasedRunFn = dyn Fn(&dyn Any, &World) + RefUnwindSafe + UnwindSafe; +type TypeErasedRunFn = dyn Fn(&dyn Any, &World); /// A parameter to a [`System`]. -pub unsafe trait Param<'world> +pub trait Param<'world> { type Input; - type Flags; fn initialize<SystemImpl>( system: &mut impl System<'world, SystemImpl>, @@ -168,8 +175,6 @@ pub unsafe trait Param<'world> ) -> Self; } -pub struct NoInitParamFlag {} - /// A type which can be used as input to a [`System`]. pub trait Input: 'static {} @@ -179,9 +184,9 @@ pub struct ParamWithInputFilter; impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for InputT where - Accumulator: TupleWith<Self>, + Accumulator: Tuple, { - type Return = Accumulator::With; + type Return = Accumulator::WithElementAtEnd<Self>; } impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for () @@ -192,7 +197,7 @@ impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for () #[derive(Debug)] pub struct ComponentRefMut<'a, ComponentT: Component> { - inner: WriteGuard<'a, Box<dyn Component>>, + inner: MappedWriteGuard<'a, ComponentT>, _ph: PhantomData<ComponentT>, } @@ -200,7 +205,19 @@ impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT> { pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self { - Self { inner, _ph: PhantomData } + Self { + inner: inner.map(|component| { + let component_type_name = component.type_name(); + + component.downcast_mut::<ComponentT>().unwrap_or_else(|| { + panic!( + "Cannot downcast component {component_type_name} to type {}", + type_name::<ComponentT>() + ); + }) + }), + _ph: PhantomData, + } } } @@ -212,15 +229,29 @@ impl<'component, ComponentT: Component> FromOptionalMutComponent<'component> _world: &'component World, ) -> Self { - Self { - inner: inner.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - }), - _ph: PhantomData, - } + Self::new(inner.unwrap_or_else(|| { + panic!( + "Component {} was not found in entity", + type_name::<ComponentT>() + ); + })) + } +} + +impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component> + for ComponentRefMut<'component, ComponentT> +{ + fn from_locked_optional_component( + optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, + world: &'component World, + ) -> Result<Self, LockError> + { + Ok(Self::from_optional_mut_component( + optional_component + .map(|lock| lock.write_nonblock()) + .transpose()?, + world, + )) } } @@ -238,13 +269,29 @@ where } } +impl<'comp, ComponentT> FromLockedOptionalComponent<'comp> + for Option<ComponentRefMut<'comp, ComponentT>> +where + ComponentT: Component, +{ + fn from_locked_optional_component( + optional_component: Option<&'comp Lock<Box<dyn Component>>>, + _world: &'comp World, + ) -> Result<Self, LockError> + { + optional_component + .map(|lock| Ok(ComponentRefMut::new(lock.write_nonblock()?))) + .transpose() + } +} + impl<'a, ComponentT: Component> Deref for ComponentRefMut<'a, ComponentT> { type Target = ComponentT; fn deref(&self) -> &Self::Target { - self.inner.downcast_ref().unwrap() + &self.inner } } @@ -252,14 +299,14 @@ impl<'a, ComponentT: Component> DerefMut for ComponentRefMut<'a, ComponentT> { fn deref_mut(&mut self) -> &mut Self::Target { - self.inner.downcast_mut().unwrap() + &mut self.inner } } #[derive(Debug)] pub struct ComponentRef<'a, ComponentT: Component> { - inner: ReadGuard<'a, Box<dyn Component>>, + inner: MappedReadGuard<'a, ComponentT>, _ph: PhantomData<ComponentT>, } @@ -267,7 +314,18 @@ impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT> { pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self { - Self { inner, _ph: PhantomData } + Self { + inner: inner.map(|component| { + component.downcast_ref::<ComponentT>().unwrap_or_else(|| { + panic!( + "Cannot downcast component {} to type {}", + component.type_name(), + type_name::<ComponentT>() + ); + }) + }), + _ph: PhantomData, + } } } @@ -279,15 +337,29 @@ impl<'component, ComponentT: Component> FromOptionalComponent<'component> _world: &'component World, ) -> Self { - Self { - inner: inner.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - }), - _ph: PhantomData, - } + Self::new(inner.unwrap_or_else(|| { + panic!( + "Component {} was not found in entity", + type_name::<ComponentT>() + ); + })) + } +} + +impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component> + for ComponentRef<'component, ComponentT> +{ + fn from_locked_optional_component( + optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, + world: &'component World, + ) -> Result<Self, LockError> + { + Ok(Self::from_optional_component( + optional_component + .map(|lock| lock.read_nonblock()) + .transpose()?, + world, + )) } } @@ -305,12 +377,34 @@ where } } +impl<'comp, ComponentT> FromLockedOptionalComponent<'comp> + for Option<ComponentRef<'comp, ComponentT>> +where + ComponentT: Component, +{ + fn from_locked_optional_component( + optional_component: Option<&'comp Lock<Box<dyn Component>>>, + _world: &'comp World, + ) -> Result<Self, LockError> + { + optional_component + .map(|lock| Ok(ComponentRef::new(lock.read_nonblock()?))) + .transpose() + } +} + impl<'a, ComponentT: Component> Deref for ComponentRef<'a, ComponentT> { type Target = ComponentT; fn deref(&self) -> &Self::Target { - self.inner.downcast_ref().unwrap() + &self.inner } } + +#[derive(Debug, Component)] +pub(crate) struct SystemComponent +{ + pub(crate) system: TypeErased, +} |