xuko_ecs/
component.rs

1use crate::{ComponentId, component_id};
2use std::any::Any;
3
4/// Entity identifier
5pub type Entity = usize;
6
7/// A component that can be attached to an entity in a [`crate::World`].
8///
9/// An entity can have multiple components, which can be queried using [`crate::Query`].
10pub trait Component
11where
12    Self: Send + Sync + 'static,
13{
14}
15impl<T: Send + Sync + 'static> Component for T {}
16
17/// Holds all the data an entity contains, its components for example.
18#[derive(Default)]
19#[doc(alias = "EntityComponents")]
20#[doc(alias = "ComponentMap")]
21pub struct EntityData(indexmap::IndexMap<ComponentId, Box<dyn Any + Send + Sync + 'static>>);
22
23impl EntityData {
24    /// Create a new [`EntityData`]
25    pub fn new() -> Self {
26        Self::default()
27    }
28
29    /// Add a component to the entity
30    pub fn add<C: Component>(&mut self, c: C) {
31        let ci = ComponentId::from_value(&c);
32        self.0.insert(ci, Box::new(c));
33    }
34
35    /// Get a reference to the component of type `C`
36    ///
37    /// # Examples
38    ///
39    /// ```
40    /// use xuko_ecs::prelude::*;
41    ///
42    /// let mut world = World::new();
43    /// {
44    ///     let id = world.spawn();
45    ///     let entity_ref = world.get_entity(id).unwrap();
46    ///     if let Some(c) = entity_ref.get::<i32>() {
47    ///         // do stuff with `c`
48    ///     }
49    /// }
50    /// ```
51    pub fn get<C: Component>(&self) -> Option<&C> {
52        let ci = component_id!(C);
53        self.0.get(&ci).map(|v| v.downcast_ref::<C>().unwrap())
54    }
55
56    /// Get a mutable reference to the component of type `C`
57    pub fn get_mut<C: Component>(&mut self) -> Option<&mut C> {
58        let ci = component_id!(C);
59        self.0.get_mut(&ci).map(|v| v.downcast_mut::<C>().unwrap())
60    }
61
62    /// Get a list of all the types of components this entity has
63    pub fn keys(&self) -> Vec<ComponentId> {
64        self.0.keys().copied().collect()
65    }
66
67    /// Check whether this map has component `C`
68    pub fn has_component<C: Component>(&self) -> bool {
69        self.0.contains_key(&component_id!(C))
70    }
71
72    /// Remove a component from the entity
73    pub fn remove<C: Component>(&mut self) {
74        self.0.swap_remove(&component_id!(C));
75    }
76}