diff options
Diffstat (limited to 'ecs/src/component.rs')
| -rw-r--r-- | ecs/src/component.rs | 192 |
1 files changed, 74 insertions, 118 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs index a0ed752..17b279b 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -1,10 +1,11 @@ use std::any::{type_name, Any}; -use std::error::Error; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; use seq_macro::seq; +use crate::event::component::Changed; +use crate::event::Submitter as EventSubmitter; use crate::lock::{ Error as LockError, MappedReadGuard, @@ -12,6 +13,7 @@ use crate::lock::{ ReadGuard, WriteGuard, }; +use crate::pair::Pair; use crate::system::Input as SystemInput; use crate::uid::Uid; use crate::util::Array; @@ -23,14 +25,6 @@ pub(crate) mod storage; pub trait Component: SystemInput + Any { - type HandleMut<'component>: HandleFromEntityComponentRef<'component> - where - Self: Sized; - - type Handle<'component>: HandleFromEntityComponentRef<'component> - where - Self: Sized; - /// Returns the ID of this component. fn id() -> Uid where @@ -77,87 +71,44 @@ pub trait Sequence fn into_parts_array(self) -> Self::PartsArray; } -/// [`Component`] metadata. -#[derive(Debug, Clone)] -#[non_exhaustive] -pub struct Metadata +#[derive(Debug)] +pub struct Handle<'a, DataT: 'static> { - pub id: Uid, + inner: MappedReadGuard<'a, DataT>, } -impl Metadata +impl<'comp, DataT: 'static> Handle<'comp, DataT> { - #[must_use] - pub fn of<ComponentT: Component>() -> Self - { - Self { id: ComponentT::id() } - } -} - -pub trait HandleFromEntityComponentRef<'comp>: Sized -{ - type Error: Error; - /// Creates a new handle instance from a [`EntityComponentRef`]. /// /// # Errors - /// See the implementation's [`Self::Error`] type. - fn from_entity_component_ref( - entity_component_ref: Option<EntityComponentRef<'comp>>, - world: &'comp World, - ) -> Result<Self, Self::Error>; -} - -#[derive(Debug)] -pub struct Handle<'a, ComponentData: 'static> -{ - inner: MappedReadGuard<'a, ComponentData>, -} - -impl<'a, ComponentData: 'static> Handle<'a, ComponentData> -{ - pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Any>>) -> Self + /// Will return `Err` if acquiring the component's lock fails. + pub fn from_entity_component_ref( + entity_component_ref: &EntityComponentRef<'comp>, + ) -> Result<Self, HandleError> { - Self { - inner: inner.map(|component| { - component - .downcast_ref::<ComponentData>() - .unwrap_or_else(|| { - panic!( - "Failed to downcast component to type {}", - type_name::<ComponentData>() - ); - }) - }), - } + Self::new( + entity_component_ref + .component() + .read_nonblock() + .map_err(AcquireLockError)?, + ) } -} - -impl<'comp, ComponentData: 'static> HandleFromEntityComponentRef<'comp> - for Handle<'comp, ComponentData> -{ - type Error = HandleError; - fn from_entity_component_ref( - entity_component_ref: Option<EntityComponentRef<'comp>>, - _world: &'comp World, - ) -> Result<Self, Self::Error> + fn new(inner: ReadGuard<'comp, Box<dyn Any>>) -> Result<Self, HandleError> { - let entity_comp = - entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; - - Ok(Self::new( - entity_comp - .component() - .read_nonblock() - .map_err(AcquireComponentLockFailed)?, - )) + Ok(Self { + inner: ReadGuard::try_map(inner, |component| { + component.downcast_ref::<DataT>() + }) + .map_err(|_| HandleError::IncorrectType)?, + }) } } -impl<ComponentData: 'static> Deref for Handle<'_, ComponentData> +impl<DataT: 'static> Deref for Handle<'_, DataT> { - type Target = ComponentData; + type Target = DataT; fn deref(&self) -> &Self::Target { @@ -166,55 +117,54 @@ impl<ComponentData: 'static> Deref for Handle<'_, ComponentData> } #[derive(Debug)] -pub struct HandleMut<'a, ComponentData: 'static> +pub struct HandleMut<'a, DataT: 'static> { - inner: MappedWriteGuard<'a, ComponentData>, + entity_component_ref: EntityComponentRef<'a>, + inner: MappedWriteGuard<'a, DataT>, + event_submitter: EventSubmitter<'a>, } -impl<'a, ComponentData: 'static> HandleMut<'a, ComponentData> +impl<'comp, DataT: 'static> HandleMut<'comp, DataT> { - pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Any>>) -> Self + /// Creates a new handle instance from a [`EntityComponentRef`]. + /// + /// # Errors + /// Will return `Err` if acquiring the component's lock fails. + pub fn from_entity_component_ref( + entity_component_ref: &EntityComponentRef<'comp>, + world: &'comp World, + ) -> Result<Self, HandleError> { - Self { - inner: inner.map(|component| { - component - .downcast_mut::<ComponentData>() - .unwrap_or_else(|| { - panic!( - "Failed to downcast component to type {}", - type_name::<ComponentData>() - ); - }) - }), - } + let inner = entity_component_ref + .component() + .write_nonblock() + .map_err(AcquireLockError)?; + + Ok(Self { + entity_component_ref: entity_component_ref.clone(), + inner: WriteGuard::try_map(inner, |component| { + component.downcast_mut::<DataT>() + }) + .map_err(|_| HandleError::IncorrectType)?, + event_submitter: world.event_submitter(), + }) } -} -impl<'comp, ComponentData: 'static> HandleFromEntityComponentRef<'comp> - for HandleMut<'comp, ComponentData> -{ - type Error = HandleError; - - fn from_entity_component_ref( - entity_component_ref: Option<EntityComponentRef<'comp>>, - _world: &'comp World, - ) -> Result<Self, Self::Error> + pub fn set_changed(&self) { - let entity_comp = - entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?; - - Ok(Self::new( - entity_comp - .component() - .write_nonblock() - .map_err(AcquireComponentLockFailed)?, - )) + self.event_submitter.submit_event( + &Pair::builder() + .relation::<Changed>() + .target_id(self.entity_component_ref.id()) + .build(), + self.entity_component_ref.entity_id(), + ); } } -impl<ComponentData: 'static> Deref for HandleMut<'_, ComponentData> +impl<DataT: 'static> Deref for HandleMut<'_, DataT> { - type Target = ComponentData; + type Target = DataT; fn deref(&self) -> &Self::Target { @@ -222,7 +172,7 @@ impl<ComponentData: 'static> Deref for HandleMut<'_, ComponentData> } } -impl<ComponentData: 'static> DerefMut for HandleMut<'_, ComponentData> +impl<DataT: 'static> DerefMut for HandleMut<'_, DataT> { fn deref_mut(&mut self) -> &mut Self::Target { @@ -234,15 +184,15 @@ impl<ComponentData: 'static> DerefMut for HandleMut<'_, ComponentData> pub enum HandleError { #[error(transparent)] - AcquireComponentLockFailed(#[from] AcquireComponentLockFailed), + AcquireLockFailed(#[from] AcquireLockError), - #[error("Component does not exist")] - ComponentDoesNotExist, + #[error("Incorrect component type")] + IncorrectType, } #[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct AcquireComponentLockFailed(LockError); +#[error("Failed to acquire component lock")] +pub struct AcquireLockError(#[source] LockError); macro_rules! inner { ($c: tt) => { @@ -357,6 +307,12 @@ impl PartsBuilder data: Box::new(data), } } + + #[must_use] + pub fn build_with_any_data(self, id: Uid, data: Box<dyn Any>) -> Parts + { + Parts { id, name: self.name, data } + } } impl Default for PartsBuilder |
