use std::any::{type_name, Any}; use std::fmt::Debug; use seq_macro::seq; use crate::event::component::{ Added as ComponentAddedEvent, Kind as ComponentEventKind, Removed as ComponentRemovedEvent, }; use crate::lock::{Error as LockError, Lock, ReadGuard, WriteGuard}; use crate::system::{ComponentRef, ComponentRefMut, Input as SystemInput}; use crate::type_name::TypeName; use crate::uid::Uid; use crate::util::Array; use crate::{EntityComponent, World}; pub mod local; pub(crate) mod storage; pub trait Component: SystemInput + Any + TypeName { /// The component type in question. Will usually be `Self` type Component: Component where Self: Sized; type RefMut<'component>: FromOptionalMut<'component> + FromLockedOptional<'component> where Self: Sized; type Ref<'component>: FromOptional<'component> + FromLockedOptional<'component> where Self: Sized; /// Returns the ID of this component. fn id() -> Uid where Self: Sized; /// The ID of the component `self`. Returns the same value as [`Component::id`]. fn self_id(&self) -> Uid; /// Returns the component UID of a component event for this component. fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid; #[doc(hidden)] fn as_any_mut(&mut self) -> &mut dyn Any; #[doc(hidden)] fn as_any(&self) -> &dyn Any; /// Whether the component `self` is optional. Returns the same value as /// [`Component::is_optional`]. fn self_is_optional(&self) -> IsOptional { IsOptional::No } /// Returns whether this component is optional. #[must_use] fn is_optional() -> IsOptional where Self: Sized, { IsOptional::No } } impl dyn Component { pub fn downcast_mut(&mut self) -> Option<&mut Real> { self.as_any_mut().downcast_mut() } pub fn downcast_ref(&self) -> Option<&Real> { self.as_any().downcast_ref() } pub fn is(&self) -> bool { self.as_any().is::() } } impl Debug for dyn Component { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.debug_struct("Component").finish_non_exhaustive() } } impl TypeName for Box { fn type_name(&self) -> &'static str { self.as_ref().type_name() } } impl Component for Option where ComponentT: Component, { type Component = ComponentT; type Ref<'component> = Option>; type RefMut<'component> = Option>; fn id() -> Uid { ComponentT::id() } fn self_id(&self) -> Uid { Self::id() } fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid { match event_kind { ComponentEventKind::Removed => ComponentRemovedEvent::::id(), } } fn as_any_mut(&mut self) -> &mut dyn Any { self } fn as_any(&self) -> &dyn Any { self } fn self_is_optional(&self) -> IsOptional { Self::is_optional() } fn is_optional() -> IsOptional { IsOptional::Yes } } impl TypeName for Option where ComponentT: Component, { fn type_name(&self) -> &'static str { type_name::() } } impl SystemInput for Option where ComponentT: Component {} /// A sequence of components. pub trait Sequence { /// The number of components in this component sequence. const COUNT: usize; fn into_vec(self) -> Vec>; fn metadata() -> impl Array; fn added_event_ids() -> Vec; fn removed_event_ids() -> Vec; } /// A sequence of references (immutable or mutable) to components. pub trait RefSequence { type Handles<'component>; fn metadata() -> impl Array; fn from_components<'component>( components: &'component [EntityComponent], component_index_lookup: impl Fn(Uid) -> Option, world: &'component World, ) -> Self::Handles<'component>; } /// A mutable or immutable reference to a component. pub trait Ref { type Component: Component; type Handle<'component>: FromLockedOptional<'component>; } impl Ref for &ComponentT where ComponentT: Component, { type Component = ComponentT; type Handle<'component> = ComponentT::Ref<'component>; } impl Ref for &mut ComponentT where ComponentT: Component, { type Component = ComponentT; type Handle<'component> = ComponentT::RefMut<'component>; } /// [`Component`] metadata. #[derive(Debug, Clone)] #[non_exhaustive] pub struct Metadata { pub id: Uid, pub is_optional: IsOptional, } impl Metadata { pub fn get(component: &ComponentT) -> Self { Self { id: component.self_id(), is_optional: component.self_is_optional(), } } pub fn of() -> Self { Self { id: ComponentT::id(), is_optional: ComponentT::is_optional(), } } } /// Whether or not a `Component` is optional. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum IsOptional { Yes, No, } impl From for IsOptional { fn from(is_optional: bool) -> Self { if is_optional { return IsOptional::Yes; } IsOptional::No } } pub trait FromOptionalMut<'comp> { fn from_optional_mut_component( optional_component: Option>>, world: &'comp World, ) -> Self; } pub trait FromOptional<'comp> { fn from_optional_component( optional_component: Option>>, world: &'comp World, ) -> Self; } pub trait FromLockedOptional<'comp>: Sized { fn from_locked_optional_component( optional_component: Option<&'comp Lock>>, world: &'comp World, ) -> Result; } macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { impl<#(Comp~I: Component,)*> Sequence for (#(Comp~I,)*) where #(for<'comp> Comp~I::RefMut<'comp>: FromOptionalMut<'comp>,)* #(for<'comp> Comp~I::Ref<'comp>: FromOptional<'comp>,)* { const COUNT: usize = $c + 1; fn into_vec(self) -> Vec> { Vec::from_iter([#(Box::new(self.I) as Box,)*]) } fn metadata() -> impl Array { [ #( Metadata { id: Comp~I::id(), is_optional: Comp~I::is_optional(), }, )* ] } fn added_event_ids() -> Vec { vec![ #(ComponentAddedEvent::::id(),)* ] } fn removed_event_ids() -> Vec { vec![ #(ComponentRemovedEvent::::id(),)* ] } } impl<#(CompRef~I: Ref,)*> RefSequence for (#(CompRef~I,)*) { type Handles<'component> = (#(CompRef~I::Handle<'component>,)*); fn metadata() -> impl Array { [#( Metadata { id: CompRef~I::Component::id(), is_optional: CompRef~I::Component::is_optional(), }, )*] } fn from_components<'component>( components: &'component [EntityComponent], component_index_lookup: impl Fn(Uid) -> Option, world: &'component World, ) -> Self::Handles<'component> { (#( CompRef~I::Handle::from_locked_optional_component( component_index_lookup(CompRef~I::Component::id()) .and_then(|component_index| components.get(component_index)) .map(|component| &component.component), world, ).unwrap_or_else(|err| { panic!( "Taking component {} lock failed: {err}", type_name::() ); }), )*) } } }); }; } seq!(C in 0..=16 { inner!(C); }); impl Sequence for () { const COUNT: usize = 0; fn into_vec(self) -> Vec> { Vec::new() } fn metadata() -> impl Array { [] } fn added_event_ids() -> Vec { Vec::new() } fn removed_event_ids() -> Vec { Vec::new() } } impl RefSequence for () { type Handles<'component> = (); fn metadata() -> impl Array { [] } fn from_components<'component>( _components: &'component [EntityComponent], _component_index_lookup: impl Fn(Uid) -> Option, _world: &'component World, ) -> Self::Handles<'component> { () } }