use std::any::type_name; use std::ops::Deref; use std::sync::LazyLock; use crate::component::storage::archetype::{ Archetype, Entity as ArchetypeEntity, MatchingComponentIter as ArchetypeMatchingComponentIter, }; use crate::component::{ Component, Handle as ComponentHandle, HandleMut as ComponentHandleMut, }; use crate::uid::{Kind as UidKind, Uid}; use crate::{EntityComponentRef, World}; /// A handle to a entity. #[derive(Debug)] pub struct Handle<'a> { archetype: &'a Archetype, entity: &'a ArchetypeEntity, } impl<'a> Handle<'a> { /// Returns the [`Uid`] of this entity. #[inline] #[must_use] pub fn uid(&self) -> Uid { self.entity.uid() } /// Returns a reference to the specified component in this entity. `None` is /// returned if the component isn't found in the entity. /// /// # Panics /// Will panic if: /// - The component's ID is not a component ID /// - The component is mutably borrowed elsewhere #[must_use] pub fn get(&self) -> Option> { assert_eq!(ComponentT::id().kind(), UidKind::Component); let component = self.get_matching_components(ComponentT::id()).next()?; Some( ComponentHandle::from_entity_component_ref(component).unwrap_or_else(|err| { panic!( "Taking component {} lock failed: {err}", type_name::() ); }), ) } /// Returns a mutable reference to the specified component in this entity. `None` is /// returned if the component isn't found in the entity. /// /// # Panics /// Will panic if: /// - The component's ID is not a component ID /// - The component is borrowed elsewhere #[must_use] pub fn get_mut( &self, ) -> Option> { assert_eq!(ComponentT::id().kind(), UidKind::Component); let component = self.get_matching_components(ComponentT::id()).next()?; Some( ComponentHandleMut::from_entity_component_ref(component).unwrap_or_else( |err| { panic!( "Taking component {} lock failed: {err}", type_name::() ); }, ), ) } #[inline] #[must_use] pub fn get_matching_components(&self, component_uid: Uid) -> MatchingComponentIter<'a> { MatchingComponentIter { inner: self.archetype.get_matching_component_indices(component_uid), entity: self.entity, } } pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self { Self { archetype, entity } } } #[derive(Debug)] pub struct MatchingComponentIter<'a> { inner: ArchetypeMatchingComponentIter<'a>, entity: &'a ArchetypeEntity, } impl<'a> Iterator for MatchingComponentIter<'a> { type Item = EntityComponentRef<'a>; fn next(&mut self) -> Option { let (matching_component_id, index) = self.inner.next()?; Some(EntityComponentRef::new( matching_component_id, self.entity.components().get(index).unwrap(), )) } } /// The data type of a declaration of a entity. #[derive(Debug)] pub struct Declaration { uid: LazyLock, create_func: fn(&mut World), } impl Declaration { pub(crate) fn create(&self, world: &mut World) { (self.create_func)(world); } #[doc(hidden)] pub const fn new(create_func: fn(&mut World)) -> Self { Self { uid: LazyLock::new(|| Uid::new_unique(UidKind::Entity)), create_func, } } } impl Deref for Declaration { type Target = Uid; fn deref(&self) -> &Self::Target { &self.uid } } #[allow(clippy::module_name_repetitions)] #[macro_export] macro_rules! declare_entity { ($visibility: vis $ident: ident, $components: expr) => { $visibility static $ident: $crate::entity::Declaration = $crate::entity::Declaration::new(|world| { world.create_entity_with_uid(*$ident, $components); }); } }