diff options
Diffstat (limited to 'ecs/src/system.rs')
-rw-r--r-- | ecs/src/system.rs | 344 |
1 files changed, 32 insertions, 312 deletions
diff --git a/ecs/src/system.rs b/ecs/src/system.rs index 40eba8d..95ab7a8 100644 --- a/ecs/src/system.rs +++ b/ecs/src/system.rs @@ -1,52 +1,28 @@ -use std::any::{type_name, Any}; -use std::convert::Infallible; use std::fmt::Debug; -use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; use ecs_macros::Component; use seq_macro::seq; -use crate::component::{ - Component, - FromLockedOptional as FromLockedOptionalComponent, - FromOptional as FromOptionalComponent, - FromOptionalMut as FromOptionalMutComponent, -}; -use crate::lock::{ - Error as LockError, - Lock, - MappedReadGuard, - MappedWriteGuard, - ReadGuard, - WriteGuard, -}; -use crate::tuple::{ReduceElement as TupleReduceElement, Tuple}; +use crate::uid::Uid; use crate::World; +pub mod initializable; +pub mod observer; pub mod stateful; -pub trait System<'world, Impl>: 'static +/// Metadata of a system. +#[derive(Debug)] +#[non_exhaustive] +pub struct Metadata { - type Input; - - #[must_use] - fn initialize(self, input: Self::Input) -> Self; - - fn run<'this>(&'this self, world: &'world World) - where - 'this: 'world; - - fn into_type_erased(self) -> TypeErased; + pub ent_id: Uid, +} - fn get_local_component_mut<LocalComponent: Component>( - &self, - ) -> Option<ComponentRefMut<LocalComponent>>; +pub trait System<'world, Impl>: 'static +{ + type Callbacks: Callbacks; - fn set_local_component<LocalComponent: Component>( - &mut self, - local_component: LocalComponent, - ); + fn finish(self) -> (TypeErased, Self::Callbacks); } macro_rules! impl_system { @@ -58,58 +34,23 @@ macro_rules! impl_system { Func: Fn(#(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world, Input = ()>,)* { - type Input = Infallible; - - fn initialize(self, _input: Self::Input) -> Self - { - self - } - - fn run<'this>(&'this self, world: &'world World) - where - 'this: 'world - { - let func = *self; - - func(#({ - TParam~I::new(self, world) - },)*); - } + type Callbacks = NoCallbacks; - fn into_type_erased(self) -> TypeErased + fn finish(self) -> (TypeErased, Self::Callbacks) { - TypeErased { - data: Box::new(self), - run: Box::new(|data, world| { - // SAFETY: The caller of TypeErased::run ensures the lifetime - // is correct - let data = unsafe { &*std::ptr::from_ref(data) }; - - let me = data - .downcast_ref::<Func>() - .expect("Function downcast failed"); - + let type_erased = TypeErased { + run: Box::new(move |world, metadata| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; - me.run(world); + self(#({ + TParam~I::new(world, &metadata) + },)*); }), - } - } - - fn get_local_component_mut<LocalComponent: Component>( - &self, - ) -> Option<ComponentRefMut<LocalComponent>> - { - panic!("System does not have any local components"); - } + }; - fn set_local_component<LocalComponent: Component>( - &mut self, - _local_component: LocalComponent, - ) { - panic!("System does not have any local components"); + (type_erased, NoCallbacks) } } }); @@ -120,7 +61,7 @@ seq!(C in 1..16 { impl_system!(C); }); -pub trait Into<Impl> +pub trait Into<'world, Impl> { type System; @@ -129,7 +70,6 @@ pub trait Into<Impl> pub struct TypeErased { - data: Box<dyn Any>, run: Box<TypeErasedRunFn>, } @@ -139,12 +79,9 @@ impl TypeErased /// /// # Safety /// `world_data` must live at least as long as the [`World`] the system belongs to. - pub unsafe fn run(&self, world: &World) + pub unsafe fn run(&self, world: &World, metadata: Metadata) { - // You have to dereference for downcasting to work for some reason - let data = &*self.data; - - (self.run)(data, world); + (self.run)(world, metadata); } } @@ -157,246 +94,29 @@ impl Debug for TypeErased } /// Function in [`TypeErased`] used to run the system. -type TypeErasedRunFn = dyn Fn(&dyn Any, &World); +type TypeErasedRunFn = dyn Fn(&World, Metadata); /// A parameter to a [`System`]. pub trait Param<'world> { type Input; - fn initialize<SystemImpl>( - system: &mut impl System<'world, SystemImpl>, - input: Self::Input, - ); - - fn new<SystemImpl>( - system: &'world impl System<'world, SystemImpl>, - world: &'world World, - ) -> Self; + fn new(world: &'world World, system_metadata: &Metadata) -> Self; } /// A type which can be used as input to a [`System`]. pub trait Input: 'static {} -/// Component tuple reducing operation to get the parameters that takes input. -pub struct ParamWithInputFilter; - -impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> - for InputT -where - Accumulator: Tuple, -{ - type Return = Accumulator::WithElementAtEnd<Self>; -} - -impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for () -{ - type Return = Accumulator; -} - -#[derive(Debug)] -pub struct ComponentRefMut<'a, ComponentT: Component> -{ - inner: MappedWriteGuard<'a, ComponentT>, - _ph: PhantomData<ComponentT>, -} - -impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT> -{ - pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self - { - 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, - } - } -} - -impl<'component, ComponentT: Component> FromOptionalMutComponent<'component> - for ComponentRefMut<'component, ComponentT> -{ - fn from_optional_mut_component( - inner: Option<WriteGuard<'component, Box<dyn Component>>>, - _world: &'component World, - ) -> Self - { - 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::write_nonblock).transpose()?, - world, - )) - } -} - -impl<'comp, ComponentT> FromOptionalMutComponent<'comp> - for Option<ComponentRefMut<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_mut_component( - optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>, - _world: &'comp World, - ) -> Self - { - optional_component.map(|component| ComponentRefMut::new(component)) - } -} - -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<ComponentT: Component> Deref for ComponentRefMut<'_, ComponentT> -{ - type Target = ComponentT; - - fn deref(&self) -> &Self::Target - { - &self.inner - } -} - -impl<ComponentT: Component> DerefMut for ComponentRefMut<'_, ComponentT> +pub trait Callbacks { - fn deref_mut(&mut self) -> &mut Self::Target - { - &mut self.inner - } + fn on_created(&mut self, world: &mut World, metadata: Metadata); } -#[derive(Debug)] -pub struct ComponentRef<'a, ComponentT: Component> -{ - inner: MappedReadGuard<'a, ComponentT>, - _ph: PhantomData<ComponentT>, -} +pub struct NoCallbacks; -impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT> +impl Callbacks for NoCallbacks { - pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self - { - 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, - } - } -} - -impl<'component, ComponentT: Component> FromOptionalComponent<'component> - for ComponentRef<'component, ComponentT> -{ - fn from_optional_component( - inner: Option<ReadGuard<'component, Box<dyn Component>>>, - _world: &'component World, - ) -> Self - { - 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::read_nonblock).transpose()?, - world, - )) - } -} - -impl<'comp, ComponentT> FromOptionalComponent<'comp> - for Option<ComponentRef<'comp, ComponentT>> -where - ComponentT: Component, -{ - fn from_optional_component( - optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>, - _world: &'comp World, - ) -> Self - { - optional_component.map(|component| ComponentRef::new(component)) - } -} - -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<ComponentT: Component> Deref for ComponentRef<'_, ComponentT> -{ - type Target = ComponentT; - - fn deref(&self) -> &Self::Target - { - &self.inner - } + fn on_created(&mut self, _world: &mut World, _metadata: Metadata) {} } #[derive(Debug, Component)] |