evenio/
component.rs

1//! Types for working with [`Component`]s.
2
3use alloc::borrow::Cow;
4use alloc::collections::BTreeSet;
5use core::alloc::Layout;
6use core::any::TypeId;
7use core::ops::Index;
8
9use ahash::RandomState;
10pub use evenio_macros::Component;
11
12use crate::archetype::{Archetype, ArchetypeIdx};
13use crate::drop::DropFn;
14use crate::entity::EntityLocation;
15use crate::event::{EventPtr, GlobalEvent, TargetedEventId};
16use crate::handler::{HandlerConfig, HandlerInfo, HandlerParam, InitError};
17use crate::map::{Entry, IndexSet, TypeIdMap};
18use crate::mutability::{Mutability, MutabilityMarker};
19use crate::prelude::World;
20use crate::slot_map::{Key, SlotMap};
21use crate::sparse::SparseIndex;
22use crate::world::UnsafeWorldCell;
23
24/// Contains metadata for all the components in a world.
25///
26/// This can be obtained in a handler by using the `&Components` handler
27/// parameter.
28///
29/// ```
30/// # use evenio::prelude::*;
31/// # use evenio::component::Components;
32/// #
33/// # #[derive(GlobalEvent)] struct E;
34/// #
35/// # let mut world = World::new();
36/// world.add_handler(|_: Receiver<E>, components: &Components| {});
37/// ```
38#[derive(Debug)]
39pub struct Components {
40    infos: SlotMap<ComponentInfo>,
41    by_type_id: TypeIdMap<ComponentId>,
42}
43
44impl Components {
45    pub(crate) fn new() -> Self {
46        Self {
47            infos: SlotMap::new(),
48            by_type_id: TypeIdMap::default(),
49        }
50    }
51
52    pub(crate) fn add(&mut self, desc: ComponentDescriptor) -> (ComponentId, bool) {
53        if let Some(type_id) = desc.type_id {
54            return match self.by_type_id.entry(type_id) {
55                Entry::Vacant(v) => {
56                    let Some(k) = self.infos.insert_with(|k| ComponentInfo {
57                        name: desc.name,
58                        id: ComponentId(k),
59                        type_id: desc.type_id,
60                        layout: desc.layout,
61                        drop: desc.drop,
62                        mutability: desc.mutability,
63                        insert_events: BTreeSet::new(),
64                        remove_events: BTreeSet::new(),
65                        member_of: IndexSet::with_hasher(RandomState::new()),
66                    }) else {
67                        panic!("too many components")
68                    };
69
70                    (*v.insert(ComponentId(k)), true)
71                }
72                Entry::Occupied(o) => (*o.get(), false),
73            };
74        }
75
76        let Some(k) = self.infos.insert_with(|k| ComponentInfo {
77            name: desc.name,
78            id: ComponentId(k),
79            type_id: desc.type_id,
80            layout: desc.layout,
81            drop: desc.drop,
82            mutability: desc.mutability,
83            insert_events: BTreeSet::new(),
84            remove_events: BTreeSet::new(),
85            member_of: IndexSet::with_hasher(RandomState::new()),
86        }) else {
87            panic!("too many components")
88        };
89
90        (ComponentId(k), true)
91    }
92
93    pub(crate) fn remove(&mut self, component_id: ComponentId) -> Option<ComponentInfo> {
94        let info = self.infos.remove(component_id.0)?;
95
96        if let Some(type_id) = info.type_id {
97            self.by_type_id.remove(&type_id);
98        }
99
100        Some(info)
101    }
102
103    /// Gets the [`ComponentInfo`] of the given component. Returns `None` if the
104    /// ID is invalid.
105    pub fn get(&self, id: ComponentId) -> Option<&ComponentInfo> {
106        self.infos.get(id.0)
107    }
108
109    /// Gets the [`ComponentInfo`] for a component using its [`ComponentIdx`].
110    /// Returns `None` if the index is invalid.
111    pub fn get_by_index(&self, idx: ComponentIdx) -> Option<&ComponentInfo> {
112        self.infos.get_by_index(idx.0).map(|(_, v)| v)
113    }
114
115    pub(crate) fn get_by_index_mut(&mut self, idx: ComponentIdx) -> Option<&mut ComponentInfo> {
116        self.infos.get_by_index_mut(idx.0).map(|(_, v)| v)
117    }
118
119    /// Gets the [`ComponentInfo`] for a component using its [`TypeId`]. Returns
120    /// `None` if the `TypeId` does not map to a component.
121    pub fn get_by_type_id(&self, type_id: TypeId) -> Option<&ComponentInfo> {
122        let id = *self.by_type_id.get(&type_id)?;
123        Some(unsafe { self.get(id).unwrap_unchecked() })
124    }
125
126    /// Does the given component exist in the world?
127    pub fn contains(&self, id: ComponentId) -> bool {
128        self.get(id).is_some()
129    }
130
131    /// Returns an iterator over all component infos.
132    pub fn iter(&self) -> impl Iterator<Item = &ComponentInfo> {
133        self.infos.iter().map(|(_, v)| v)
134    }
135}
136
137impl Index<ComponentId> for Components {
138    type Output = ComponentInfo;
139
140    fn index(&self, index: ComponentId) -> &Self::Output {
141        if let Some(info) = self.get(index) {
142            info
143        } else {
144            panic!("no such component with ID of {index:?} exists")
145        }
146    }
147}
148
149impl Index<ComponentIdx> for Components {
150    type Output = ComponentInfo;
151
152    fn index(&self, index: ComponentIdx) -> &Self::Output {
153        if let Some(info) = self.get_by_index(index) {
154            info
155        } else {
156            panic!("no such component with index of {index:?} exists")
157        }
158    }
159}
160
161impl Index<TypeId> for Components {
162    type Output = ComponentInfo;
163
164    fn index(&self, index: TypeId) -> &Self::Output {
165        if let Some(info) = self.get_by_type_id(index) {
166            info
167        } else {
168            panic!("no such component with type ID of {index:?} exists")
169        }
170    }
171}
172
173unsafe impl HandlerParam for &'_ Components {
174    type State = ();
175
176    type This<'a> = &'a Components;
177
178    fn init(_world: &mut World, _config: &mut HandlerConfig) -> Result<Self::State, InitError> {
179        Ok(())
180    }
181
182    unsafe fn get<'a>(
183        _state: &'a mut Self::State,
184        _info: &'a HandlerInfo,
185        _event_ptr: EventPtr<'a>,
186        _target_location: EntityLocation,
187        world: UnsafeWorldCell<'a>,
188    ) -> Self::This<'a> {
189        world.components()
190    }
191
192    fn refresh_archetype(_state: &mut Self::State, _arch: &Archetype) {}
193
194    fn remove_archetype(_state: &mut Self::State, _arch: &Archetype) {}
195}
196
197/// Metadata for a component.
198#[derive(Debug)]
199pub struct ComponentInfo {
200    name: Cow<'static, str>,
201    id: ComponentId,
202    type_id: Option<TypeId>,
203    layout: Layout,
204    drop: DropFn,
205    mutability: Mutability,
206    pub(crate) insert_events: BTreeSet<TargetedEventId>,
207    pub(crate) remove_events: BTreeSet<TargetedEventId>,
208    /// The set of archetypes that have this component as one of its columns.
209    pub(crate) member_of: IndexSet<ArchetypeIdx>,
210}
211
212impl ComponentInfo {
213    /// Gets the name of the component.
214    ///
215    /// This name is intended for debugging purposes and should not be relied
216    /// upon for correctness.
217    pub fn name(&self) -> &str {
218        &self.name
219    }
220
221    /// Gets the ID of the component.
222    pub fn id(&self) -> ComponentId {
223        self.id
224    }
225
226    /// Gets the [`TypeId`] of the component, or `None` if it was not assigned a
227    /// type ID.
228    pub fn type_id(&self) -> Option<TypeId> {
229        self.type_id
230    }
231
232    /// Gets the [`Layout`] of the component.
233    pub fn layout(&self) -> Layout {
234        self.layout
235    }
236
237    /// Gets the [`DropFn`] of the component.
238    pub fn drop(&self) -> DropFn {
239        self.drop
240    }
241
242    /// Gets the [`Mutability`] of the component.
243    pub fn mutability(&self) -> Mutability {
244        self.mutability
245    }
246
247    /// Gets the set of [`Insert`] events for this component.
248    ///
249    /// [`Insert`]: crate::event::Insert
250    pub fn insert_events(&self) -> &BTreeSet<TargetedEventId> {
251        &self.insert_events
252    }
253
254    /// Gets the set of [`Remove`] components for this component.
255    ///
256    /// [`Remove`]: crate::event::Remove
257    pub fn remove_events(&self) -> &BTreeSet<TargetedEventId> {
258        &self.remove_events
259    }
260}
261
262/// Types which store data on [entities].
263///
264/// A `Component` is a piece of data which can be attached to an entity. An
265/// entity can have any combination of components, but cannot have more than one
266/// component of the same type.
267///
268/// To add a component to an entity, use the [`Insert`] event. To access
269/// components from handlers, use the [`Fetcher`] handler parameter.
270///
271/// [entities]: crate::entity
272/// [`Insert`]: crate::event::Insert
273/// [`Fetcher`]: crate::fetch::Fetcher
274///
275/// # Deriving
276///
277/// The `Component` trait can be implemented automatically by using the
278/// associated derive macro. However, the type must still satisfy the `'static`
279/// bound to do so.
280///
281/// ```
282/// use evenio::prelude::*;
283///
284/// // Component with some data.
285/// #[derive(Component)]
286/// struct Username(String);
287///
288/// // Component without data, known as a "marker" or "tag" component.
289/// struct Invisible;
290///
291/// // Derive it on structs with named fields.
292/// #[derive(Component)]
293/// struct Position {
294///     x: f32,
295///     y: f32,
296///     z: f32,
297/// }
298///
299/// // ...and on enums.
300/// #[derive(Component)]
301/// enum FriendStatus {
302///     Friendly,
303///     Neutral,
304///     Unfriendly,
305/// }
306///
307/// // Components can be immutable, which disallows mutable references
308/// // to the component once it's attached to an entity.
309/// #[derive(Component)]
310/// #[component(immutable)] // Override the default mutability.
311/// struct FooCounter(i32);
312/// ```
313pub trait Component: 'static {
314    /// Indicates if this event is [`Mutable`] or [`Immutable`].
315    ///
316    /// Immutable components disallow mutable references, which can be used to
317    /// ensure components are only modified via events.
318    ///
319    /// [`Mutable`]: crate::mutability::Mutable
320    /// [`Immutable`]: crate::mutability::Immutable
321    type Mutability: MutabilityMarker;
322}
323
324/// Data needed to create a new component.
325#[derive(Clone, Debug)]
326pub struct ComponentDescriptor {
327    /// The name of this component.
328    ///
329    /// This name is intended for debugging purposes and should not be relied
330    /// upon for correctness.
331    pub name: Cow<'static, str>,
332    /// The [`TypeId`] of this component, if any.
333    pub type_id: Option<TypeId>,
334    /// The [`Layout`] of the component.
335    pub layout: Layout,
336    /// The [`DropFn`] of the component. This is passed a pointer to the
337    /// component in order to drop it.
338    pub drop: DropFn,
339    /// The [mutability](Component::Mutability) of this component.
340    pub mutability: Mutability,
341}
342
343/// Lightweight identifier for a component type.
344///
345/// component identifiers are implemented using an [index] and a generation
346/// count. The generation count ensures that IDs from removed components are
347/// not reused by new components.
348///
349/// A component identifier is only meaningful in the [`World`] it was created
350/// from. Attempting to use a component ID in a different world will have
351/// unexpected results.
352///
353/// [index]: ComponentIdx
354#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
355pub struct ComponentId(Key);
356
357impl ComponentId {
358    /// The component ID which never identifies a live component. This is the
359    /// default value for `ComponentId`.
360    pub const NULL: Self = Self(Key::NULL);
361
362    /// Creates a new component ID from an index and generation count. Returns
363    /// `None` if a valid ID is not formed.
364    pub const fn new(index: u32, generation: u32) -> Option<Self> {
365        match Key::new(index, generation) {
366            Some(k) => Some(Self(k)),
367            None => None,
368        }
369    }
370
371    /// Returns the index of this ID.
372    pub const fn index(self) -> ComponentIdx {
373        ComponentIdx(self.0.index())
374    }
375
376    /// Returns the generation count of this ID.
377    pub const fn generation(self) -> u32 {
378        self.0.generation().get()
379    }
380}
381
382/// A [`ComponentId`] with the generation count stripped out.
383#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
384pub struct ComponentIdx(pub u32);
385
386unsafe impl SparseIndex for ComponentIdx {
387    const MAX: Self = Self(u32::MAX);
388
389    fn index(self) -> usize {
390        self.0.index()
391    }
392
393    fn from_index(idx: usize) -> Self {
394        Self(u32::from_index(idx))
395    }
396}
397
398/// An event sent immediately after a new component is added to the world.
399/// Contains the ID of the added component.
400#[derive(GlobalEvent, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
401pub struct AddComponent(pub ComponentId);
402
403/// An event sent immediately before a component is removed from the world.
404/// Contains the ID of the component to be removed.
405#[derive(GlobalEvent, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
406pub struct RemoveComponent(pub ComponentId);
407
408#[cfg(test)]
409mod tests {
410    use crate::prelude::*;
411
412    #[derive(GlobalEvent)]
413    struct E;
414
415    #[test]
416    fn remove_component() {
417        #[derive(Component)]
418        struct A(String);
419
420        #[derive(Component, PartialEq, Debug)]
421        struct B(Vec<String>);
422
423        let mut world = World::new();
424
425        let c1 = world.add_component::<A>();
426        let e1 = world.spawn();
427        world.insert(e1, A("hello".into()));
428        let s1 = world.add_handler(|_: Receiver<E>, Single(A(a)): Single<&mut A>| {
429            a.push_str("hello");
430        });
431        world.send(E);
432
433        assert!(world.remove_component(c1).is_some());
434        assert!(!world.handlers().contains(s1));
435        assert!(!world.entities().contains(e1));
436        assert_eq!(
437            world.archetypes().len(),
438            1,
439            "only the empty archetype should be present"
440        );
441
442        let c2 = world.add_component::<B>();
443        let e2 = world.spawn();
444        assert!(world.entities().contains(e2));
445        world.insert(e2, B(vec![]));
446        let s2 = world.add_handler(|_: Receiver<E>, Single(B(b)): Single<&mut B>| {
447            b.push("hello".into());
448        });
449        world.send(E);
450        assert_eq!(world.get::<B>(e2), Some(&B(vec!["hello".into()])));
451
452        assert!(world.remove_component(c2).is_some());
453        assert!(!world.handlers().contains(s2));
454        assert!(!world.entities().contains(e2));
455        assert_eq!(world.archetypes().len(), 1);
456    }
457
458    #[test]
459    fn component_member_of() {
460        let mut world = World::new();
461
462        #[derive(Component)]
463        struct A;
464
465        #[derive(Component)]
466        struct B;
467
468        #[derive(Component)]
469        struct C;
470
471        let c1 = world.add_component::<A>();
472        let c2 = world.add_component::<B>();
473        let c3 = world.add_component::<C>();
474
475        let e1 = world.spawn();
476        let e2 = world.spawn();
477        let e3 = world.spawn();
478
479        world.insert(e1, A);
480
481        world.insert(e2, A);
482        world.insert(e2, B);
483
484        world.insert(e3, A);
485        world.insert(e3, B);
486        world.insert(e3, C);
487
488        assert_eq!(world.components()[c1].member_of.len(), 3);
489        assert_eq!(world.components()[c2].member_of.len(), 2);
490        assert_eq!(world.components()[c3].member_of.len(), 1);
491
492        world.remove_component(c3);
493
494        assert_eq!(world.components()[c1].member_of.len(), 2);
495        assert_eq!(world.components()[c2].member_of.len(), 1);
496
497        world.remove_component(c2);
498
499        assert_eq!(world.components()[c1].member_of.len(), 1);
500    }
501}