diff options
Diffstat (limited to 'ecs/src/component.rs')
-rw-r--r-- | ecs/src/component.rs | 289 |
1 files changed, 181 insertions, 108 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs index a9894b7..b2ecf80 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -3,10 +3,16 @@ use std::fmt::Debug; use seq_macro::seq; -use crate::lock::{ReadGuard, WriteGuard}; -use crate::system::{ComponentRef, ComponentRefMut, Input as SystemInput}; +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::Input as SystemInput; use crate::type_name::TypeName; use crate::uid::Uid; +use crate::util::Array; use crate::{EntityComponent, World}; pub mod local; @@ -20,11 +26,11 @@ pub trait Component: SystemInput + Any + TypeName where Self: Sized; - type RefMut<'component> + type RefMut<'component>: FromOptionalMut<'component> + FromLockedOptional<'component> where Self: Sized; - type Ref<'component> + type Ref<'component>: FromOptional<'component> + FromLockedOptional<'component> where Self: Sized; @@ -36,26 +42,28 @@ pub trait Component: SystemInput + Any + TypeName /// 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 + /// Returns whether the component `self` is optional. + fn self_is_optional(&self) -> bool { - IsOptional::No + false } /// Returns whether this component is optional. #[must_use] - fn is_optional() -> IsOptional + fn is_optional() -> bool where Self: Sized, { - IsOptional::No + false } } @@ -96,10 +104,12 @@ impl TypeName for Box<dyn Component> impl<ComponentT> Component for Option<ComponentT> where ComponentT: Component, + for<'a> Option<ComponentT::Ref<'a>>: FromOptional<'a> + FromLockedOptional<'a>, + for<'a> Option<ComponentT::RefMut<'a>>: FromOptionalMut<'a> + FromLockedOptional<'a>, { type Component = ComponentT; - type Ref<'component> = Option<ComponentRef<'component, ComponentT>>; - type RefMut<'component> = Option<ComponentRefMut<'component, ComponentT>>; + type Ref<'component> = Option<ComponentT::Ref<'component>>; + type RefMut<'component> = Option<ComponentT::RefMut<'component>>; fn id() -> Uid { @@ -111,6 +121,13 @@ where Self::id() } + fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid + { + match event_kind { + ComponentEventKind::Removed => ComponentRemovedEvent::<Self>::id(), + } + } + fn as_any_mut(&mut self) -> &mut dyn Any { self @@ -121,14 +138,14 @@ where self } - fn self_is_optional(&self) -> IsOptional + fn self_is_optional(&self) -> bool { - Self::is_optional() + true } - fn is_optional() -> IsOptional + fn is_optional() -> bool { - IsOptional::Yes + true } } @@ -147,33 +164,57 @@ impl<ComponentT> SystemInput for Option<ComponentT> where ComponentT: Component /// A sequence of components. pub trait Sequence { - type MutRefs<'component> - where - Self: 'component; + /// The number of components in this component sequence. + const COUNT: usize; - type Refs<'component> - where - Self: 'component; + type Array: Array<Box<dyn Component>>; - fn into_vec(self) -> Vec<Box<dyn Component>>; + fn into_array(self) -> Self::Array; - fn metadata() -> Vec<Metadata>; + fn metadata() -> impl Array<Metadata>; - fn from_components_mut<'component>( - components: impl Iterator<Item = &'component EntityComponent>, - world: &'component World, - lock_component: fn( - entity_component: &EntityComponent, - ) -> WriteGuard<'_, Box<dyn Component>>, - ) -> Self::MutRefs<'component>; + fn added_event_ids() -> Vec<Uid>; + + fn removed_event_ids() -> Vec<Uid>; +} + +/// A sequence of references (immutable or mutable) to components. +pub trait RefSequence +{ + type Handles<'component>; + + type Metadata: Array<Metadata>; + + fn metadata() -> Self::Metadata; fn from_components<'component>( - components: impl Iterator<Item = &'component EntityComponent>, + components: &'component [EntityComponent], + component_index_lookup: impl Fn(Uid) -> Option<usize>, world: &'component World, - lock_component: fn( - entity_component: &EntityComponent, - ) -> ReadGuard<'_, Box<dyn Component>>, - ) -> Self::Refs<'component>; + ) -> Self::Handles<'component>; +} + +/// A mutable or immutable reference to a component. +pub trait Ref +{ + type Component: Component; + type Handle<'component>: FromLockedOptional<'component>; +} + +impl<ComponentT> Ref for &ComponentT +where + ComponentT: Component, +{ + type Component = ComponentT; + type Handle<'component> = ComponentT::Ref<'component>; +} + +impl<ComponentT> Ref for &mut ComponentT +where + ComponentT: Component, +{ + type Component = ComponentT; + type Handle<'component> = ComponentT::RefMut<'component>; } /// [`Component`] metadata. @@ -182,7 +223,7 @@ pub trait Sequence pub struct Metadata { pub id: Uid, - pub is_optional: IsOptional, + pub is_optional: bool, } impl Metadata @@ -204,26 +245,6 @@ impl Metadata } } -/// Whether or not a `Component` is optional. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum IsOptional -{ - Yes, - No, -} - -impl From<bool> 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( @@ -240,6 +261,14 @@ pub trait FromOptional<'comp> ) -> Self; } +pub trait FromLockedOptional<'comp>: Sized +{ + fn from_locked_optional_component( + optional_component: Option<&'comp Lock<Box<dyn Component>>>, + world: &'comp World, + ) -> Result<Self, LockError>; +} + macro_rules! inner { ($c: tt) => { seq!(I in 0..=$c { @@ -248,79 +277,76 @@ macro_rules! inner { #(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; + const COUNT: usize = $c + 1; - type Refs<'component> = (#(Comp~I::Ref<'component>,)*) - where Self: 'component; + type Array = [Box<dyn Component>; $c + 1]; - fn into_vec(self) -> Vec<Box<dyn Component>> + fn into_array(self) -> Self::Array { - Vec::from_iter([#(Box::new(self.I) as Box<dyn Component>,)*]) + [#(Box::new(self.I) as Box<dyn Component>,)*] } - fn metadata() -> Vec<Metadata> + fn metadata() -> impl Array<Metadata> { - vec![ + [ #( Metadata { id: Comp~I::id(), - is_optional: Comp~I::is_optional() + is_optional: Comp~I::is_optional(), }, )* ] } - fn from_components_mut<'component>( - components: impl Iterator<Item = &'component EntityComponent>, - world: &'component World, - lock_component: fn( - entity_component: &EntityComponent, - ) -> WriteGuard<'_, Box<dyn Component>>, - ) -> Self::MutRefs<'component> + fn added_event_ids() -> Vec<Uid> + { + vec![ + #(ComponentAddedEvent::<Comp~I>::id(),)* + ] + } + + fn removed_event_ids() -> Vec<Uid> { - #( - let mut comp_~I: Option<WriteGuard<Box<dyn Component>>> = None; - )* + vec![ + #(ComponentRemovedEvent::<Comp~I>::id(),)* + ] + } + } - for comp in components { - #( - if comp.id == Comp~I::Component::id() { - comp_~I = Some(lock_component(comp)); - continue; - } - )* - } + impl<#(CompRef~I: Ref,)*> RefSequence for (#(CompRef~I,)*) + { + type Handles<'component> = (#(CompRef~I::Handle<'component>,)*); - (#( - Comp~I::RefMut::from_optional_mut_component(comp_~I, world), - )*) + type Metadata = [Metadata; $c + 1]; + + fn metadata() -> Self::Metadata + { + [#( + Metadata { + id: CompRef~I::Component::id(), + is_optional: CompRef~I::Component::is_optional(), + }, + )*] } fn from_components<'component>( - components: impl Iterator<Item = &'component EntityComponent>, + components: &'component [EntityComponent], + component_index_lookup: impl Fn(Uid) -> Option<usize>, world: &'component World, - lock_component: fn( - entity_component: &EntityComponent, - ) -> ReadGuard<'_, Box<dyn Component>>, - ) -> Self::Refs<'component> + ) -> Self::Handles<'component> { - - #( - let mut comp_~I: Option<ReadGuard<Box<dyn Component>>> = 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), + 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::<CompRef~I::Component>() + ); + }), )*) } } @@ -328,6 +354,53 @@ macro_rules! inner { }; } -seq!(C in 0..=64 { +seq!(C in 0..=16 { inner!(C); }); + +impl Sequence for () +{ + type Array = [Box<dyn Component>; 0]; + + const COUNT: usize = 0; + + fn into_array(self) -> Self::Array + { + [] + } + + fn metadata() -> impl Array<Metadata> + { + [] + } + + fn added_event_ids() -> Vec<Uid> + { + Vec::new() + } + + fn removed_event_ids() -> Vec<Uid> + { + Vec::new() + } +} + +impl RefSequence for () +{ + type Handles<'component> = (); + type Metadata = [Metadata; 0]; + + fn metadata() -> Self::Metadata + { + [] + } + + fn from_components<'component>( + _components: &'component [EntityComponent], + _component_index_lookup: impl Fn(Uid) -> Option<usize>, + _world: &'component World, + ) -> Self::Handles<'component> + { + () + } +} |