summaryrefslogtreecommitdiff
path: root/ecs/src/entity.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/entity.rs')
-rw-r--r--ecs/src/entity.rs109
1 files changed, 100 insertions, 9 deletions
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index a43f9ce..bab3d61 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -1,10 +1,22 @@
+use std::any::type_name;
+
use linkme::distributed_slice;
-use crate::component::storage::archetype::{Archetype, Entity as ArchetypeEntity};
-use crate::uid::Uid;
+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,
@@ -21,15 +33,72 @@ impl<'a> Handle<'a>
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<ComponentT: Component>(&self) -> Option<ComponentHandle<'_, ComponentT>>
+ {
+ 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::<ComponentT>()
+ );
+ }),
+ )
+ }
+
+ /// 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<ComponentT: Component>(
+ &self,
+ ) -> Option<ComponentHandleMut<'_, ComponentT>>
+ {
+ 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::<ComponentT>()
+ );
+ },
+ ),
+ )
+ }
+
#[inline]
#[must_use]
- pub fn get_component(&self, component_uid: Uid) -> Option<EntityComponentRef<'a>>
+ pub fn get_matching_components(&self, component_uid: Uid)
+ -> MatchingComponentIter<'a>
{
- let index = self.archetype.get_index_for_component(component_uid)?;
+ MatchingComponentIter {
+ inner: self.archetype.get_matching_component_indices(component_uid),
+ entity: self.entity,
+ }
+ }
- Some(EntityComponentRef::new(
- self.entity.components().get(index).unwrap(),
- ))
+ pub fn component_ids(&self) -> impl Iterator<Item = Uid> + '_
+ {
+ self.archetype.component_ids_sorted()
}
pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self
@@ -38,6 +107,28 @@ impl<'a> Handle<'a>
}
}
+#[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<Self::Item>
+ {
+ 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 {
@@ -55,7 +146,7 @@ macro_rules! static_entity {
$crate::entity::CREATE_STATIC_ENTITIES
)]
#[linkme(crate=$crate::private::linkme)]
- static CREATE_STATIC_ENTITY: fn(&$crate::World) = |world| {
+ static CREATE_STATIC_ENTITY: fn(&mut $crate::World) = |world| {
world.create_entity_with_uid($components, *$ident);
};
}
@@ -65,4 +156,4 @@ macro_rules! static_entity {
#[distributed_slice]
#[doc(hidden)]
-pub static CREATE_STATIC_ENTITIES: [fn(&World)];
+pub static CREATE_STATIC_ENTITIES: [fn(&mut World)];