use std::any::{type_name, Any}; use std::fmt::Debug; use seq_macro::seq; use crate::uid::Uid; use crate::lock::{ReadGuard, WriteGuard}; use crate::system::{ComponentRef, ComponentRefMut, Input as SystemInput}; use crate::type_name::TypeName; 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> where Self: Sized; type Ref<'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; #[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. 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 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 { type MutRefs<'component> where Self: 'component; type Refs<'component> where Self: 'component; fn into_vec(self) -> Vec>; fn metadata() -> Vec; fn from_components_mut<'component>( components: impl Iterator, world: &'component World, lock_component: fn( entity_component: &EntityComponent, ) -> WriteGuard<'_, Box>, ) -> Self::MutRefs<'component>; fn from_components<'component>( components: impl Iterator, world: &'component World, lock_component: fn( entity_component: &EntityComponent, ) -> ReadGuard<'_, Box>, ) -> Self::Refs<'component>; } /// [`Component`] metadata. #[derive(Debug, Clone)] #[non_exhaustive] pub struct Metadata { pub id: Uid, pub is_optional: IsOptional, } impl Metadata { pub fn of(component: &ComponentT) -> Self { Self { id: component.self_id(), is_optional: component.self_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; } 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>,)* { type MutRefs<'component> = (#(Comp~I::RefMut<'component>,)*) where Self: 'component; type Refs<'component> = (#(Comp~I::Ref<'component>,)*) where Self: 'component; fn into_vec(self) -> Vec> { Vec::from_iter([#(Box::new(self.I) as Box,)*]) } fn metadata() -> Vec { vec![ #( Metadata { id: Comp~I::id(), is_optional: Comp~I::is_optional() }, )* ] } fn from_components_mut<'component>( components: impl Iterator, world: &'component World, lock_component: fn( entity_component: &EntityComponent, ) -> WriteGuard<'_, Box>, ) -> Self::MutRefs<'component> { #( let mut comp_~I: Option>> = None; )* for comp in components { #( if comp.id == Comp~I::Component::id() { comp_~I = Some(lock_component(comp)); continue; } )* } (#( Comp~I::RefMut::from_optional_mut_component(comp_~I, world), )*) } fn from_components<'component>( components: impl Iterator, world: &'component World, lock_component: fn( entity_component: &EntityComponent, ) -> ReadGuard<'_, Box>, ) -> Self::Refs<'component> { #( let mut comp_~I: Option>> = None; )* for comp in components { #( if comp.id == Comp~I::Component::id() { comp_~I = Some(lock_component(comp)); continue; } )* } (#( Comp~I::Ref::from_optional_component(comp_~I, world), )*) } } }); }; } seq!(C in 0..=64 { inner!(C); });