use std::any::type_name; use linkme::distributed_slice; use crate::component::storage::archetype::{ Archetype, Entity as ArchetypeEntity, MatchingComponentIter as ArchetypeMatchingComponentIter, }; use crate::component::{ Component, Handle as ComponentHandle, HandleFromEntityComponentRef, 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> { world: &'a World, 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() } 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(Some(component), self.world) .unwrap_or_else(|err| { panic!( "Taking component {} lock failed: {err}", type_name::() ); }), ) } 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(Some(component), self.world) .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( world: &'a World, archetype: &'a Archetype, entity: &'a ArchetypeEntity, ) -> Self { Self { world, 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(), )) } } #[allow(clippy::module_name_repetitions)] #[macro_export] macro_rules! static_entity { ($visibility: vis $ident: ident, $components: expr) => { $visibility static $ident: ::std::sync::LazyLock<$crate::uid::Uid> = ::std::sync::LazyLock::new(|| { $crate::uid::Uid::new_unique($crate::uid::Kind::Entity) }); $crate::private::paste::paste! { mod [<__ecs_ $ident:lower _static_entity_priv>] { use super::*; #[$crate::private::linkme::distributed_slice( $crate::entity::CREATE_STATIC_ENTITIES )] #[linkme(crate=$crate::private::linkme)] static CREATE_STATIC_ENTITY: fn(&$crate::World) = |world| { world.create_entity_with_uid($components, *$ident); }; } } } } #[distributed_slice] #[doc(hidden)] pub static CREATE_STATIC_ENTITIES: [fn(&World)];