diff options
Diffstat (limited to 'ecs/src/component.rs')
-rw-r--r-- | ecs/src/component.rs | 185 |
1 files changed, 105 insertions, 80 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs index 525bd98..c01fd75 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -1,4 +1,5 @@ use std::any::{type_name, Any}; +use std::error::Error; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; @@ -11,34 +12,32 @@ use crate::event::component::{ }; use crate::lock::{ Error as LockError, - Lock, MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard, }; use crate::system::Input as SystemInput; -use crate::type_name::TypeName; use crate::uid::Uid; use crate::util::Array; -use crate::World; +use crate::{EntityComponentRef, World}; pub mod local; pub(crate) mod storage; -pub trait Component: SystemInput + Any + TypeName +pub trait Component: SystemInput + Any { /// The component type in question. Will usually be `Self` type Component: Component where Self: Sized; - type HandleMut<'component>: FromLockedOptional<'component> + type HandleMut<'component>: HandleFromEntityComponentRef<'component> where Self: Sized; - type Handle<'component>: FromLockedOptional<'component> + type Handle<'component>: HandleFromEntityComponentRef<'component> where Self: Sized; @@ -47,6 +46,9 @@ pub trait Component: SystemInput + Any + TypeName where Self: Sized; + /// Returns the name of this component. + fn name(&self) -> &'static str; + /// Returns the component UID of a component event for this component. fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid; @@ -92,19 +94,11 @@ impl Debug for dyn Component } } -impl TypeName for Box<dyn Component> -{ - fn type_name(&self) -> &'static str - { - self.as_ref().type_name() - } -} - impl<ComponentT> Component for Option<ComponentT> where ComponentT: Component, - for<'a> Option<ComponentT::Handle<'a>>: FromLockedOptional<'a>, - for<'a> Option<ComponentT::HandleMut<'a>>: FromLockedOptional<'a>, + for<'a> Option<ComponentT::Handle<'a>>: HandleFromEntityComponentRef<'a>, + for<'a> Option<ComponentT::HandleMut<'a>>: HandleFromEntityComponentRef<'a>, { type Component = ComponentT; type Handle<'component> = Option<ComponentT::Handle<'component>>; @@ -115,6 +109,11 @@ where ComponentT::id() } + fn name(&self) -> &'static str + { + type_name::<Self>() + } + fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid { match event_kind { @@ -133,16 +132,6 @@ where } } -impl<ComponentT> TypeName for Option<ComponentT> -where - ComponentT: Component, -{ - fn type_name(&self) -> &'static str - { - type_name::<Self>() - } -} - impl<ComponentT> SystemInput for Option<ComponentT> where ComponentT: Component {} /// A sequence of components. @@ -166,7 +155,7 @@ pub trait Sequence pub trait Ref { type Component: Component; - type Handle<'component>: FromLockedOptional<'component>; + type Handle<'component>: HandleFromEntityComponentRef<'component>; } impl<ComponentT> Ref for &ComponentT @@ -212,16 +201,15 @@ impl Metadata } } -pub trait FromLockedOptional<'comp>: Sized +pub trait HandleFromEntityComponentRef<'comp>: Sized { - /// Converts a reference to a optional locked boxed component to a instance of `Self`. - /// - /// # Errors - /// Returns `Err` if taking the lock (in a non-blocking way) fails. - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, + type Error: Error; + + /// Creates a new handle instance from a [`EntityComponentRef`]. + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, world: &'comp World, - ) -> Result<Self, LockError>; + ) -> Result<Self, Self::Error>; } #[derive(Debug)] @@ -238,8 +226,7 @@ impl<'a, ComponentT: Component> Handle<'a, ComponentT> inner: inner.map(|component| { component.downcast_ref::<ComponentT>().unwrap_or_else(|| { panic!( - "Cannot downcast component {} to type {}", - component.type_name(), + "Failed to downcast component to type {}", type_name::<ComponentT>() ); }) @@ -248,36 +235,49 @@ impl<'a, ComponentT: Component> Handle<'a, ComponentT> } } -impl<'component, ComponentT: Component> FromLockedOptional<'component> - for Handle<'component, ComponentT> +impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp> + for Handle<'comp, ComponentT> { - fn from_locked_optional_component( - optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>, - _world: &'component World, - ) -> Result<Self, LockError> - { - let component = optional_component.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - }); + type Error = HandleError; - Ok(Self::new(component.read_nonblock()?)) + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, + _world: &'comp World, + ) -> Result<Self, Self::Error> + { + let entity_comp = + entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; + + Ok(Self::new( + entity_comp + .component() + .read_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) } } -impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<Handle<'comp, ComponentT>> +impl<'comp, ComponentT> HandleFromEntityComponentRef<'comp> + for Option<Handle<'comp, ComponentT>> where ComponentT: Component, { - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, + type Error = HandleError; + + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, _world: &'comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - optional_component - .map(|lock| Ok(Handle::new(lock.read_nonblock()?))) + entity_component_ref + .map(|entity_comp| { + Ok(Handle::new( + entity_comp + .component() + .read_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) + }) .transpose() } } @@ -304,11 +304,9 @@ impl<'a, ComponentT: Component> HandleMut<'a, ComponentT> { 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 {}", + "Failed to downcast component to type {}", type_name::<ComponentT>() ); }) @@ -317,36 +315,49 @@ impl<'a, ComponentT: Component> HandleMut<'a, ComponentT> } } -impl<'component, ComponentT: Component> FromLockedOptional<'component> - for HandleMut<'component, ComponentT> +impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp> + for HandleMut<'comp, ComponentT> { - fn from_locked_optional_component( - optional_component: Option<&'component Lock<Box<dyn Component>>>, - _world: &'component World, - ) -> Result<Self, LockError> - { - let component = optional_component.unwrap_or_else(|| { - panic!( - "Component {} was not found in entity", - type_name::<ComponentT>() - ); - }); + type Error = HandleError; - Ok(Self::new(component.write_nonblock()?)) + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, + _world: &'comp World, + ) -> Result<Self, Self::Error> + { + let entity_comp = + entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; + + Ok(Self::new( + entity_comp + .component() + .write_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) } } -impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<HandleMut<'comp, ComponentT>> +impl<'comp, ComponentT> HandleFromEntityComponentRef<'comp> + for Option<HandleMut<'comp, ComponentT>> where ComponentT: Component, { - fn from_locked_optional_component( - optional_component: Option<&'comp Lock<Box<dyn Component>>>, + type Error = HandleError; + + fn from_entity_component_ref( + entity_component_ref: Option<EntityComponentRef<'comp>>, _world: &'comp World, - ) -> Result<Self, LockError> + ) -> Result<Self, Self::Error> { - optional_component - .map(|lock| Ok(HandleMut::new(lock.write_nonblock()?))) + entity_component_ref + .map(|entity_comp| { + Ok(HandleMut::new( + entity_comp + .component() + .write_nonblock() + .map_err(AcquireComponentLockFailed)?, + )) + }) .transpose() } } @@ -369,6 +380,20 @@ impl<ComponentT: Component> DerefMut for HandleMut<'_, ComponentT> } } +#[derive(Debug, thiserror::Error)] +pub enum HandleError +{ + #[error(transparent)] + AcquireComponentLockFailed(#[from] AcquireComponentLockFailed), + + #[error("Component does not exist")] + ComponentDoesNotExist, +} + +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub struct AcquireComponentLockFailed(LockError); + macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { |