use std::any::{Any, TypeId}; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; use engine_ecs_macros::Component; use seq_macro::seq; use crate::event::component::Changed; use crate::event::Submitter as EventSubmitter; use crate::lock::{ Error as LockError, MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard, }; use crate::pair::{MemberMetadata as PairMemberMetadata, Pair}; use crate::reflection::Type as TypeReflection; use crate::system::Input as SystemInput; use crate::uid::Uid; use crate::{EntityComponentRef, World}; pub mod local; pub(crate) mod storage; /// A component that is not a pair and is not a sole. pub trait Component: WithAssociatedId + SystemInput + Any + IntoParts { fn type_reflection() -> Option<&'static TypeReflection> where Self: Sized; /// Returns the name of this component. fn name(&self) -> &'static str; } pub trait WithAssociatedId { /// Returns the ID of this component. fn id() -> Uid; } /// A component that is removable from it's entity. /// /// This trait is implemented for [`crate::pair::Pair`] so it does not have [`Component`] /// as supertrait. pub trait Removable: WithAssociatedId {} impl Removable for ComponentT {} /// Implemented by tuples of types implementing [`Removable`]. /// /// This trait is sealed so it cannot be implemented by types outside of this module. pub trait RemovableTuple: sealed::Sealed { fn ids() -> impl IntoIterator; } macro_rules! gen_removable_tuple_impl { ($c: tt) => { seq!(I in 0..=$c { impl<#(RemovableT~I: Removable,)*> RemovableTuple for (#(RemovableT~I,)*) { fn ids() -> impl IntoIterator { [#(RemovableT~I::id(),)*] } } impl<#(RemovableT~I: Removable,)*> sealed::Sealed for (#(RemovableT~I,)*) { } }); }; } seq!(C in 0..=16 { gen_removable_tuple_impl!(C); }); #[derive(Debug)] pub struct Handle<'a, DataT: ?Sized + 'static> { inner: MappedReadGuard<'a, DataT>, } impl<'comp, DataT: 'static> Handle<'comp, DataT> { /// 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>, ) -> Result { Self::new( entity_component_ref .component() .read_nonblock() .map_err(AcquireLockError)?, ) } fn new(inner: ReadGuard<'comp, Box>) -> Result { Ok(Self { inner: ReadGuard::try_map(inner, |component| { component.downcast_ref::() }) .map_err(|_| HandleError::IncorrectType)?, }) } } impl<'comp> Handle<'comp, dyn Any> { /// Creates a handle to a untyped component. /// /// # Errors /// Will return `Err` if acquiring the component's lock fails. pub fn new_any( entity_component_ref: &EntityComponentRef<'comp>, ) -> Result { Ok(Self { inner: ReadGuard::map( entity_component_ref .component() .read_nonblock() .map_err(AcquireLockError)?, |component| &**component, ), }) } } impl Deref for Handle<'_, DataT> { type Target = DataT; fn deref(&self) -> &Self::Target { &self.inner } } #[derive(Debug)] pub struct HandleMut<'a, DataT: ?Sized + 'static> { entity_component_ref: EntityComponentRef<'a>, inner: MappedWriteGuard<'a, DataT>, event_submitter: EventSubmitter<'a>, } impl<'comp, DataT: 'static> HandleMut<'comp, DataT> { /// 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 { 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::() }) .map_err(|_| HandleError::IncorrectType)?, event_submitter: world.event_submitter(), }) } } impl<'comp> HandleMut<'comp, dyn Any> { /// Creates a handle to a untyped component. /// /// # Errors /// Will return `Err` if acquiring the component's lock fails. pub fn new_any( entity_component_ref: &EntityComponentRef<'comp>, world: &'comp World, ) -> Result { let inner = entity_component_ref .component() .write_nonblock() .map_err(AcquireLockError)?; Ok(Self { entity_component_ref: entity_component_ref.clone(), inner: WriteGuard::map(inner, |component| &mut **component), event_submitter: world.event_submitter(), }) } } impl HandleMut<'_, DataT> { pub fn set_changed(&self) { self.event_submitter.submit_event( &Pair::builder() .relation::() .target_id(self.entity_component_ref.id()) .build(), self.entity_component_ref.entity_id(), ); } } impl Deref for HandleMut<'_, DataT> { type Target = DataT; fn deref(&self) -> &Self::Target { &self.inner } } impl DerefMut for HandleMut<'_, DataT> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } #[derive(Debug, thiserror::Error)] pub enum HandleError { #[error(transparent)] AcquireLockFailed(#[from] AcquireLockError), #[error("Incorrect component type")] IncorrectType, } #[derive(Debug, thiserror::Error)] #[error("Failed to acquire component lock")] pub struct AcquireLockError(#[source] LockError); pub trait IntoParts { fn into_parts(self) -> Parts; } /// The parts of a component. #[derive(Debug)] #[non_exhaustive] pub struct Parts { pub id: Uid, pub name: &'static str, pub is_sole: bool, pub type_reflection: Option<&'static TypeReflection>, pub data: Box, pub pair_relation_metadata: Option, pub pair_target_metadata: Option, } impl Parts { /// Creates components parts from the component information stored in /// `component_info`. /// /// # Panics /// This function will panic if the type ID of the value in `data` does not equal /// to the type ID stored in `component_info`. #[must_use] pub fn from_component_info(component_info: &Info, id: Uid, data: Box) -> Self { assert_eq!((*data).type_id(), component_info.ty_id); Self::builder() .type_reflection(component_info.type_reflection) .name(component_info.name) .is_sole(component_info.is_sole) .build_with_any_data(id, data) } #[must_use] pub fn builder() -> PartsBuilder { PartsBuilder::default() } } impl IntoParts for Parts { fn into_parts(self) -> Parts { self } } #[derive(Debug)] pub struct PartsBuilder { name: &'static str, is_sole: bool, type_reflection: Option<&'static TypeReflection>, pair_relation_metadata: Option, pair_target_metadata: Option, } impl PartsBuilder { #[must_use] pub fn name(mut self, name: &'static str) -> Self { self.name = name; self } #[must_use] pub fn is_sole(mut self, is_sole: bool) -> Self { self.is_sole = is_sole; self } #[must_use] pub fn type_reflection( mut self, type_reflection: Option<&'static TypeReflection>, ) -> Self { self.type_reflection = type_reflection; self } #[must_use] pub fn pair_relation_metadata(mut self, metadata: Option) -> Self { self.pair_relation_metadata = metadata; self } #[must_use] pub fn pair_target_metadata(mut self, metadata: Option) -> Self { self.pair_target_metadata = metadata; self } #[must_use] pub fn build(self, id: Uid, data: Data) -> Parts { Parts { id, name: self.name, is_sole: self.is_sole, type_reflection: self.type_reflection, data: Box::new(data), pair_relation_metadata: self.pair_relation_metadata, pair_target_metadata: self.pair_target_metadata, } } #[must_use] pub fn build_with_any_data(self, id: Uid, data: Box) -> Parts { Parts { id, name: self.name, is_sole: self.is_sole, type_reflection: self.type_reflection, data, pair_relation_metadata: self.pair_relation_metadata, pair_target_metadata: self.pair_target_metadata, } } } impl Default for PartsBuilder { fn default() -> Self { Self { name: "(unspecified)", is_sole: false, type_reflection: None, pair_relation_metadata: None, pair_target_metadata: None, } } } #[derive(Debug, Clone, Component)] #[non_exhaustive] pub struct Info { pub type_reflection: Option<&'static TypeReflection>, pub ty_id: TypeId, pub name: &'static str, pub is_sole: bool, } mod sealed { pub trait Sealed {} }