bevy_ecs/archetype.rs
1//! Types for defining [`Archetype`]s, collections of entities that have the same set of
2//! components.
3//!
4//! An archetype uniquely describes a group of entities that share the same components:
5//! a world only has one archetype for each unique combination of components, and all
6//! entities that have those components and only those components belong to that
7//! archetype.
8//!
9//! Archetypes are not to be confused with [`Table`]s. Each archetype stores its table
10//! components in one table, and each archetype uniquely points to one table, but multiple
11//! archetypes may store their table components in the same table. These archetypes
12//! differ only by the [`SparseSet`] components.
13//!
14//! Like tables, archetypes can be created but are never cleaned up. Empty archetypes are
15//! not removed, and persist until the world is dropped.
16//!
17//! Archetypes can be fetched from [`Archetypes`], which is accessible via [`World::archetypes`].
18//!
19//! [`Table`]: crate::storage::Table
20//! [`World::archetypes`]: crate::world::World::archetypes
21
22use crate::{
23 bundle::BundleId,
24 component::{ComponentId, Components, RequiredComponentConstructor, StorageType},
25 entity::{Entity, EntityLocation},
26 observer::Observers,
27 storage::{ImmutableSparseSet, SparseArray, SparseSet, SparseSetIndex, TableId, TableRow},
28};
29use alloc::{boxed::Box, vec::Vec};
30use bevy_platform::collections::HashMap;
31use core::{
32 hash::Hash,
33 ops::{Index, IndexMut, RangeFrom},
34};
35
36/// An opaque location within a [`Archetype`].
37///
38/// This can be used in conjunction with [`ArchetypeId`] to find the exact location
39/// of an [`Entity`] within a [`World`]. An entity's archetype and index can be
40/// retrieved via [`Entities::get`].
41///
42/// [`World`]: crate::world::World
43/// [`Entities::get`]: crate::entity::Entities
44#[derive(Debug, Copy, Clone, Eq, PartialEq)]
45// SAFETY: Must be repr(transparent) due to the safety requirements on EntityLocation
46#[repr(transparent)]
47pub struct ArchetypeRow(u32);
48
49impl ArchetypeRow {
50 /// Index indicating an invalid archetype row.
51 /// This is meant to be used as a placeholder.
52 pub const INVALID: ArchetypeRow = ArchetypeRow(u32::MAX);
53
54 /// Creates a `ArchetypeRow`.
55 #[inline]
56 pub const fn new(index: usize) -> Self {
57 Self(index as u32)
58 }
59
60 /// Gets the index of the row.
61 #[inline]
62 pub const fn index(self) -> usize {
63 self.0 as usize
64 }
65}
66
67/// An opaque unique ID for a single [`Archetype`] within a [`World`].
68///
69/// Archetype IDs are only valid for a given World, and are not globally unique.
70/// Attempting to use an archetype ID on a world that it wasn't sourced from will
71/// not return the archetype with the same components. The only exception to this is
72/// [`EMPTY`] which is guaranteed to be identical for all Worlds.
73///
74/// [`World`]: crate::world::World
75/// [`EMPTY`]: ArchetypeId::EMPTY
76#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
77// SAFETY: Must be repr(transparent) due to the safety requirements on EntityLocation
78#[repr(transparent)]
79pub struct ArchetypeId(u32);
80
81impl ArchetypeId {
82 /// The ID for the [`Archetype`] without any components.
83 pub const EMPTY: ArchetypeId = ArchetypeId(0);
84 /// # Safety:
85 ///
86 /// This must always have an all-1s bit pattern to ensure soundness in fast entity id space allocation.
87 pub const INVALID: ArchetypeId = ArchetypeId(u32::MAX);
88
89 /// Create an `ArchetypeId` from a plain value.
90 ///
91 /// This is useful if you need to store the `ArchetypeId` as a plain value,
92 /// for example in a specialized data structure such as a bitset.
93 ///
94 /// While it doesn't break any safety invariants, you should ensure the
95 /// values comes from a pre-existing [`ArchetypeId::index`] in this world
96 /// to avoid panics and other unexpected behaviors.
97 #[inline]
98 pub const fn new(index: usize) -> Self {
99 ArchetypeId(index as u32)
100 }
101
102 /// The plain value of this `ArchetypeId`.
103 ///
104 /// In bevy, this is mostly used to store archetype ids in [`FixedBitSet`]s.
105 ///
106 /// [`FixedBitSet`]: fixedbitset::FixedBitSet
107 #[inline]
108 pub fn index(self) -> usize {
109 self.0 as usize
110 }
111}
112
113/// Used in [`ArchetypeAfterBundleInsert`] to track whether components in the bundle are newly
114/// added or already existed in the entity's archetype.
115#[derive(Copy, Clone, Eq, PartialEq)]
116pub(crate) enum ComponentStatus {
117 Added,
118 Existing,
119}
120
121/// Used in [`Edges`] to cache the result of inserting a bundle into the source archetype.
122pub(crate) struct ArchetypeAfterBundleInsert {
123 /// The target archetype after the bundle is inserted into the source archetype.
124 pub archetype_id: ArchetypeId,
125 /// For each component iterated in the same order as the source [`Bundle`](crate::bundle::Bundle),
126 /// indicate if the component is newly added to the target archetype or if it already existed.
127 pub bundle_status: Vec<ComponentStatus>,
128 /// The set of additional required components that must be initialized immediately when adding this Bundle.
129 ///
130 /// The initial values are determined based on the provided constructor, falling back to the `Default` trait if none is given.
131 pub required_components: Vec<RequiredComponentConstructor>,
132 /// The components added by this bundle. This includes any Required Components that are inserted when adding this bundle.
133 pub added: Vec<ComponentId>,
134 /// The components that were explicitly contributed by this bundle, but already existed in the archetype. This _does not_ include any
135 /// Required Components.
136 pub existing: Vec<ComponentId>,
137}
138
139impl ArchetypeAfterBundleInsert {
140 pub(crate) fn iter_inserted(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
141 self.added.iter().chain(self.existing.iter()).copied()
142 }
143
144 pub(crate) fn iter_added(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
145 self.added.iter().copied()
146 }
147
148 pub(crate) fn iter_existing(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
149 self.existing.iter().copied()
150 }
151}
152
153/// This trait is used to report the status of [`Bundle`](crate::bundle::Bundle) components
154/// being inserted into a given entity, relative to that entity's original archetype.
155/// See [`crate::bundle::BundleInfo::write_components`] for more info.
156pub(crate) trait BundleComponentStatus {
157 /// Returns the Bundle's component status for the given "bundle index".
158 ///
159 /// # Safety
160 /// Callers must ensure that index is always a valid bundle index for the
161 /// Bundle associated with this [`BundleComponentStatus`]
162 unsafe fn get_status(&self, index: usize) -> ComponentStatus;
163}
164
165impl BundleComponentStatus for ArchetypeAfterBundleInsert {
166 #[inline]
167 unsafe fn get_status(&self, index: usize) -> ComponentStatus {
168 // SAFETY: caller has ensured index is a valid bundle index for this bundle
169 unsafe { *self.bundle_status.get_unchecked(index) }
170 }
171}
172
173pub(crate) struct SpawnBundleStatus;
174
175impl BundleComponentStatus for SpawnBundleStatus {
176 #[inline]
177 unsafe fn get_status(&self, _index: usize) -> ComponentStatus {
178 // Components inserted during a spawn call are always treated as added.
179 ComponentStatus::Added
180 }
181}
182
183/// Archetypes and bundles form a graph. Adding or removing a bundle moves
184/// an [`Entity`] to a new [`Archetype`].
185///
186/// [`Edges`] caches the results of these moves. Each archetype caches
187/// the result of a structural alteration. This can be used to monitor the
188/// state of the archetype graph.
189///
190/// Note: This type only contains edges the [`World`] has already traversed.
191/// If any of functions return `None`, it doesn't mean there is guaranteed
192/// not to be a result of adding or removing that bundle, but rather that
193/// operation that has moved an entity along that edge has not been performed
194/// yet.
195///
196/// [`World`]: crate::world::World
197#[derive(Default)]
198pub struct Edges {
199 insert_bundle: SparseArray<BundleId, ArchetypeAfterBundleInsert>,
200 remove_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
201 take_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
202}
203
204impl Edges {
205 /// Checks the cache for the target archetype when inserting a bundle into the
206 /// source archetype.
207 ///
208 /// If this returns `None`, it means there has not been a transition from
209 /// the source archetype via the provided bundle.
210 #[inline]
211 pub fn get_archetype_after_bundle_insert(&self, bundle_id: BundleId) -> Option<ArchetypeId> {
212 self.get_archetype_after_bundle_insert_internal(bundle_id)
213 .map(|bundle| bundle.archetype_id)
214 }
215
216 /// Internal version of `get_archetype_after_bundle_insert` that
217 /// fetches the full `ArchetypeAfterBundleInsert`.
218 #[inline]
219 pub(crate) fn get_archetype_after_bundle_insert_internal(
220 &self,
221 bundle_id: BundleId,
222 ) -> Option<&ArchetypeAfterBundleInsert> {
223 self.insert_bundle.get(bundle_id)
224 }
225
226 /// Caches the target archetype when inserting a bundle into the source archetype.
227 #[inline]
228 pub(crate) fn cache_archetype_after_bundle_insert(
229 &mut self,
230 bundle_id: BundleId,
231 archetype_id: ArchetypeId,
232 bundle_status: Vec<ComponentStatus>,
233 required_components: Vec<RequiredComponentConstructor>,
234 added: Vec<ComponentId>,
235 existing: Vec<ComponentId>,
236 ) {
237 self.insert_bundle.insert(
238 bundle_id,
239 ArchetypeAfterBundleInsert {
240 archetype_id,
241 bundle_status,
242 required_components,
243 added,
244 existing,
245 },
246 );
247 }
248
249 /// Checks the cache for the target archetype when removing a bundle from the
250 /// source archetype.
251 ///
252 /// If this returns `None`, it means there has not been a transition from
253 /// the source archetype via the provided bundle.
254 ///
255 /// If this returns `Some(None)`, it means that the bundle cannot be removed
256 /// from the source archetype.
257 #[inline]
258 pub fn get_archetype_after_bundle_remove(
259 &self,
260 bundle_id: BundleId,
261 ) -> Option<Option<ArchetypeId>> {
262 self.remove_bundle.get(bundle_id).cloned()
263 }
264
265 /// Caches the target archetype when removing a bundle from the source archetype.
266 #[inline]
267 pub(crate) fn cache_archetype_after_bundle_remove(
268 &mut self,
269 bundle_id: BundleId,
270 archetype_id: Option<ArchetypeId>,
271 ) {
272 self.remove_bundle.insert(bundle_id, archetype_id);
273 }
274
275 /// Checks the cache for the target archetype when taking a bundle from the
276 /// source archetype.
277 ///
278 /// Unlike `remove`, `take` will only succeed if the source archetype
279 /// contains all of the components in the bundle.
280 ///
281 /// If this returns `None`, it means there has not been a transition from
282 /// the source archetype via the provided bundle.
283 ///
284 /// If this returns `Some(None)`, it means that the bundle cannot be taken
285 /// from the source archetype.
286 #[inline]
287 pub fn get_archetype_after_bundle_take(
288 &self,
289 bundle_id: BundleId,
290 ) -> Option<Option<ArchetypeId>> {
291 self.take_bundle.get(bundle_id).cloned()
292 }
293
294 /// Caches the target archetype when taking a bundle from the source archetype.
295 ///
296 /// Unlike `remove`, `take` will only succeed if the source archetype
297 /// contains all of the components in the bundle.
298 #[inline]
299 pub(crate) fn cache_archetype_after_bundle_take(
300 &mut self,
301 bundle_id: BundleId,
302 archetype_id: Option<ArchetypeId>,
303 ) {
304 self.take_bundle.insert(bundle_id, archetype_id);
305 }
306}
307
308/// Metadata about an [`Entity`] in a [`Archetype`].
309pub struct ArchetypeEntity {
310 entity: Entity,
311 table_row: TableRow,
312}
313
314impl ArchetypeEntity {
315 /// The ID of the entity.
316 #[inline]
317 pub const fn id(&self) -> Entity {
318 self.entity
319 }
320
321 /// The row in the [`Table`] where the entity's components are stored.
322 ///
323 /// [`Table`]: crate::storage::Table
324 #[inline]
325 pub const fn table_row(&self) -> TableRow {
326 self.table_row
327 }
328}
329
330/// Internal metadata for an [`Entity`] getting removed from an [`Archetype`].
331pub(crate) struct ArchetypeSwapRemoveResult {
332 /// If the [`Entity`] was not the last in the [`Archetype`], it gets removed by swapping it out
333 /// with the last entity in the archetype. In that case, this field contains the swapped entity.
334 pub(crate) swapped_entity: Option<Entity>,
335 /// The [`TableRow`] where the removed entity's components are stored.
336 pub(crate) table_row: TableRow,
337}
338
339/// Internal metadata for a [`Component`] within a given [`Archetype`].
340///
341/// [`Component`]: crate::component::Component
342struct ArchetypeComponentInfo {
343 storage_type: StorageType,
344 archetype_component_id: ArchetypeComponentId,
345}
346
347bitflags::bitflags! {
348 /// Flags used to keep track of metadata about the component in this [`Archetype`]
349 ///
350 /// Used primarily to early-out when there are no [`ComponentHook`] registered for any contained components.
351 #[derive(Clone, Copy)]
352 pub(crate) struct ArchetypeFlags: u32 {
353 const ON_ADD_HOOK = (1 << 0);
354 const ON_INSERT_HOOK = (1 << 1);
355 const ON_REPLACE_HOOK = (1 << 2);
356 const ON_REMOVE_HOOK = (1 << 3);
357 const ON_DESPAWN_HOOK = (1 << 4);
358 const ON_ADD_OBSERVER = (1 << 5);
359 const ON_INSERT_OBSERVER = (1 << 6);
360 const ON_REPLACE_OBSERVER = (1 << 7);
361 const ON_REMOVE_OBSERVER = (1 << 8);
362 const ON_DESPAWN_OBSERVER = (1 << 9);
363 }
364}
365
366/// Metadata for a single archetype within a [`World`].
367///
368/// For more information, see the *[module level documentation]*.
369///
370/// [`World`]: crate::world::World
371/// [module level documentation]: crate::archetype
372pub struct Archetype {
373 id: ArchetypeId,
374 table_id: TableId,
375 edges: Edges,
376 entities: Vec<ArchetypeEntity>,
377 components: ImmutableSparseSet<ComponentId, ArchetypeComponentInfo>,
378 pub(crate) flags: ArchetypeFlags,
379}
380
381impl Archetype {
382 /// `table_components` and `sparse_set_components` must be sorted
383 pub(crate) fn new(
384 components: &Components,
385 component_index: &mut ComponentIndex,
386 observers: &Observers,
387 id: ArchetypeId,
388 table_id: TableId,
389 table_components: impl Iterator<Item = (ComponentId, ArchetypeComponentId)>,
390 sparse_set_components: impl Iterator<Item = (ComponentId, ArchetypeComponentId)>,
391 ) -> Self {
392 let (min_table, _) = table_components.size_hint();
393 let (min_sparse, _) = sparse_set_components.size_hint();
394 let mut flags = ArchetypeFlags::empty();
395 let mut archetype_components = SparseSet::with_capacity(min_table + min_sparse);
396 for (idx, (component_id, archetype_component_id)) in table_components.enumerate() {
397 // SAFETY: We are creating an archetype that includes this component so it must exist
398 let info = unsafe { components.get_info_unchecked(component_id) };
399 info.update_archetype_flags(&mut flags);
400 observers.update_archetype_flags(component_id, &mut flags);
401 archetype_components.insert(
402 component_id,
403 ArchetypeComponentInfo {
404 storage_type: StorageType::Table,
405 archetype_component_id,
406 },
407 );
408 // NOTE: the `table_components` are sorted AND they were inserted in the `Table` in the same
409 // sorted order, so the index of the `Column` in the `Table` is the same as the index of the
410 // component in the `table_components` vector
411 component_index
412 .entry(component_id)
413 .or_default()
414 .insert(id, ArchetypeRecord { column: Some(idx) });
415 }
416
417 for (component_id, archetype_component_id) in sparse_set_components {
418 // SAFETY: We are creating an archetype that includes this component so it must exist
419 let info = unsafe { components.get_info_unchecked(component_id) };
420 info.update_archetype_flags(&mut flags);
421 observers.update_archetype_flags(component_id, &mut flags);
422 archetype_components.insert(
423 component_id,
424 ArchetypeComponentInfo {
425 storage_type: StorageType::SparseSet,
426 archetype_component_id,
427 },
428 );
429 component_index
430 .entry(component_id)
431 .or_default()
432 .insert(id, ArchetypeRecord { column: None });
433 }
434 Self {
435 id,
436 table_id,
437 entities: Vec::new(),
438 components: archetype_components.into_immutable(),
439 edges: Default::default(),
440 flags,
441 }
442 }
443
444 /// Fetches the ID for the archetype.
445 #[inline]
446 pub fn id(&self) -> ArchetypeId {
447 self.id
448 }
449
450 /// Fetches the flags for the archetype.
451 #[inline]
452 pub(crate) fn flags(&self) -> ArchetypeFlags {
453 self.flags
454 }
455
456 /// Fetches the archetype's [`Table`] ID.
457 ///
458 /// [`Table`]: crate::storage::Table
459 #[inline]
460 pub fn table_id(&self) -> TableId {
461 self.table_id
462 }
463
464 /// Fetches the entities contained in this archetype.
465 #[inline]
466 pub fn entities(&self) -> &[ArchetypeEntity] {
467 &self.entities
468 }
469
470 /// Gets an iterator of all of the components stored in [`Table`]s.
471 ///
472 /// All of the IDs are unique.
473 ///
474 /// [`Table`]: crate::storage::Table
475 #[inline]
476 pub fn table_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
477 self.components
478 .iter()
479 .filter(|(_, component)| component.storage_type == StorageType::Table)
480 .map(|(id, _)| *id)
481 }
482
483 /// Gets an iterator of all of the components stored in [`ComponentSparseSet`]s.
484 ///
485 /// All of the IDs are unique.
486 ///
487 /// [`ComponentSparseSet`]: crate::storage::ComponentSparseSet
488 #[inline]
489 pub fn sparse_set_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
490 self.components
491 .iter()
492 .filter(|(_, component)| component.storage_type == StorageType::SparseSet)
493 .map(|(id, _)| *id)
494 }
495
496 /// Gets an iterator of all of the components in the archetype.
497 ///
498 /// All of the IDs are unique.
499 #[inline]
500 pub fn components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
501 self.components.indices()
502 }
503
504 /// Returns the total number of components in the archetype
505 #[inline]
506 pub fn component_count(&self) -> usize {
507 self.components.len()
508 }
509
510 /// Gets an iterator of all of the components in the archetype, along with
511 /// their archetype component ID.
512 pub(crate) fn components_with_archetype_component_id(
513 &self,
514 ) -> impl Iterator<Item = (ComponentId, ArchetypeComponentId)> + '_ {
515 self.components
516 .iter()
517 .map(|(component_id, info)| (*component_id, info.archetype_component_id))
518 }
519
520 /// Fetches an immutable reference to the archetype's [`Edges`], a cache of
521 /// archetypal relationships.
522 #[inline]
523 pub fn edges(&self) -> &Edges {
524 &self.edges
525 }
526
527 /// Fetches a mutable reference to the archetype's [`Edges`], a cache of
528 /// archetypal relationships.
529 #[inline]
530 pub(crate) fn edges_mut(&mut self) -> &mut Edges {
531 &mut self.edges
532 }
533
534 /// Fetches the row in the [`Table`] where the components for the entity at `index`
535 /// is stored.
536 ///
537 /// An entity's archetype row can be fetched from [`EntityLocation::archetype_row`], which
538 /// can be retrieved from [`Entities::get`].
539 ///
540 /// # Panics
541 /// This function will panic if `index >= self.len()`.
542 ///
543 /// [`Table`]: crate::storage::Table
544 /// [`EntityLocation::archetype_row`]: crate::entity::EntityLocation::archetype_row
545 /// [`Entities::get`]: crate::entity::Entities::get
546 #[inline]
547 pub fn entity_table_row(&self, row: ArchetypeRow) -> TableRow {
548 self.entities[row.index()].table_row
549 }
550
551 /// Updates if the components for the entity at `index` can be found
552 /// in the corresponding table.
553 ///
554 /// # Panics
555 /// This function will panic if `index >= self.len()`.
556 #[inline]
557 pub(crate) fn set_entity_table_row(&mut self, row: ArchetypeRow, table_row: TableRow) {
558 self.entities[row.index()].table_row = table_row;
559 }
560
561 /// Allocates an entity to the archetype.
562 ///
563 /// # Safety
564 /// valid component values must be immediately written to the relevant storages
565 /// `table_row` must be valid
566 #[inline]
567 pub(crate) unsafe fn allocate(
568 &mut self,
569 entity: Entity,
570 table_row: TableRow,
571 ) -> EntityLocation {
572 let archetype_row = ArchetypeRow::new(self.entities.len());
573 self.entities.push(ArchetypeEntity { entity, table_row });
574
575 EntityLocation {
576 archetype_id: self.id,
577 archetype_row,
578 table_id: self.table_id,
579 table_row,
580 }
581 }
582
583 #[inline]
584 pub(crate) fn reserve(&mut self, additional: usize) {
585 self.entities.reserve(additional);
586 }
587
588 /// Removes the entity at `row` by swapping it out. Returns the table row the entity is stored
589 /// in.
590 ///
591 /// # Panics
592 /// This function will panic if `row >= self.entities.len()`
593 #[inline]
594 pub(crate) fn swap_remove(&mut self, row: ArchetypeRow) -> ArchetypeSwapRemoveResult {
595 let is_last = row.index() == self.entities.len() - 1;
596 let entity = self.entities.swap_remove(row.index());
597 ArchetypeSwapRemoveResult {
598 swapped_entity: if is_last {
599 None
600 } else {
601 Some(self.entities[row.index()].entity)
602 },
603 table_row: entity.table_row,
604 }
605 }
606
607 /// Gets the total number of entities that belong to the archetype.
608 #[inline]
609 pub fn len(&self) -> usize {
610 self.entities.len()
611 }
612
613 /// Checks if the archetype has any entities.
614 #[inline]
615 pub fn is_empty(&self) -> bool {
616 self.entities.is_empty()
617 }
618
619 /// Checks if the archetype contains a specific component. This runs in `O(1)` time.
620 #[inline]
621 pub fn contains(&self, component_id: ComponentId) -> bool {
622 self.components.contains(component_id)
623 }
624
625 /// Gets the type of storage where a component in the archetype can be found.
626 /// Returns `None` if the component is not part of the archetype.
627 /// This runs in `O(1)` time.
628 #[inline]
629 pub fn get_storage_type(&self, component_id: ComponentId) -> Option<StorageType> {
630 self.components
631 .get(component_id)
632 .map(|info| info.storage_type)
633 }
634
635 /// Fetches the corresponding [`ArchetypeComponentId`] for a component in the archetype.
636 /// Returns `None` if the component is not part of the archetype.
637 /// This runs in `O(1)` time.
638 #[inline]
639 pub fn get_archetype_component_id(
640 &self,
641 component_id: ComponentId,
642 ) -> Option<ArchetypeComponentId> {
643 self.components
644 .get(component_id)
645 .map(|info| info.archetype_component_id)
646 }
647
648 /// Clears all entities from the archetype.
649 pub(crate) fn clear_entities(&mut self) {
650 self.entities.clear();
651 }
652
653 /// Returns true if any of the components in this archetype have `on_add` hooks
654 #[inline]
655 pub fn has_add_hook(&self) -> bool {
656 self.flags().contains(ArchetypeFlags::ON_ADD_HOOK)
657 }
658
659 /// Returns true if any of the components in this archetype have `on_insert` hooks
660 #[inline]
661 pub fn has_insert_hook(&self) -> bool {
662 self.flags().contains(ArchetypeFlags::ON_INSERT_HOOK)
663 }
664
665 /// Returns true if any of the components in this archetype have `on_replace` hooks
666 #[inline]
667 pub fn has_replace_hook(&self) -> bool {
668 self.flags().contains(ArchetypeFlags::ON_REPLACE_HOOK)
669 }
670
671 /// Returns true if any of the components in this archetype have `on_remove` hooks
672 #[inline]
673 pub fn has_remove_hook(&self) -> bool {
674 self.flags().contains(ArchetypeFlags::ON_REMOVE_HOOK)
675 }
676
677 /// Returns true if any of the components in this archetype have `on_despawn` hooks
678 #[inline]
679 pub fn has_despawn_hook(&self) -> bool {
680 self.flags().contains(ArchetypeFlags::ON_DESPAWN_HOOK)
681 }
682
683 /// Returns true if any of the components in this archetype have at least one [`OnAdd`] observer
684 ///
685 /// [`OnAdd`]: crate::world::OnAdd
686 #[inline]
687 pub fn has_add_observer(&self) -> bool {
688 self.flags().contains(ArchetypeFlags::ON_ADD_OBSERVER)
689 }
690
691 /// Returns true if any of the components in this archetype have at least one [`OnInsert`] observer
692 ///
693 /// [`OnInsert`]: crate::world::OnInsert
694 #[inline]
695 pub fn has_insert_observer(&self) -> bool {
696 self.flags().contains(ArchetypeFlags::ON_INSERT_OBSERVER)
697 }
698
699 /// Returns true if any of the components in this archetype have at least one [`OnReplace`] observer
700 ///
701 /// [`OnReplace`]: crate::world::OnReplace
702 #[inline]
703 pub fn has_replace_observer(&self) -> bool {
704 self.flags().contains(ArchetypeFlags::ON_REPLACE_OBSERVER)
705 }
706
707 /// Returns true if any of the components in this archetype have at least one [`OnRemove`] observer
708 ///
709 /// [`OnRemove`]: crate::world::OnRemove
710 #[inline]
711 pub fn has_remove_observer(&self) -> bool {
712 self.flags().contains(ArchetypeFlags::ON_REMOVE_OBSERVER)
713 }
714
715 /// Returns true if any of the components in this archetype have at least one [`OnDespawn`] observer
716 ///
717 /// [`OnDespawn`]: crate::world::OnDespawn
718 #[inline]
719 pub fn has_despawn_observer(&self) -> bool {
720 self.flags().contains(ArchetypeFlags::ON_DESPAWN_OBSERVER)
721 }
722}
723
724/// The next [`ArchetypeId`] in an [`Archetypes`] collection.
725///
726/// This is used in archetype update methods to limit archetype updates to the
727/// ones added since the last time the method ran.
728#[derive(Debug, Copy, Clone, PartialEq)]
729pub struct ArchetypeGeneration(pub(crate) ArchetypeId);
730
731impl ArchetypeGeneration {
732 /// The first archetype.
733 #[inline]
734 pub const fn initial() -> Self {
735 ArchetypeGeneration(ArchetypeId::EMPTY)
736 }
737}
738
739#[derive(Hash, PartialEq, Eq)]
740struct ArchetypeComponents {
741 table_components: Box<[ComponentId]>,
742 sparse_set_components: Box<[ComponentId]>,
743}
744
745/// An opaque unique joint ID for a [`Component`] in an [`Archetype`] within a [`World`].
746///
747/// A component may be present within multiple archetypes, but each component within
748/// each archetype has its own unique `ArchetypeComponentId`. This is leveraged by the system
749/// schedulers to opportunistically run multiple systems in parallel that would otherwise
750/// conflict. For example, `Query<&mut A, With<B>>` and `Query<&mut A, Without<B>>` can run in
751/// parallel as the matched `ArchetypeComponentId` sets for both queries are disjoint, even
752/// though `&mut A` on both queries point to the same [`ComponentId`].
753///
754/// In SQL terms, these IDs are composite keys on a [many-to-many relationship] between archetypes
755/// and components. Each component type will have only one [`ComponentId`], but may have many
756/// [`ArchetypeComponentId`]s, one for every archetype the component is present in. Likewise, each
757/// archetype will have only one [`ArchetypeId`] but may have many [`ArchetypeComponentId`]s, one
758/// for each component that belongs to the archetype.
759///
760/// Every [`Resource`] is also assigned one of these IDs. As resources do not belong to any
761/// particular archetype, a resource's ID uniquely identifies it.
762///
763/// These IDs are only valid within a given World, and are not globally unique.
764/// Attempting to use an ID on a world that it wasn't sourced from will
765/// not point to the same archetype nor the same component.
766///
767/// [`Component`]: crate::component::Component
768/// [`World`]: crate::world::World
769/// [`Resource`]: crate::resource::Resource
770/// [many-to-many relationship]: https://en.wikipedia.org/wiki/Many-to-many_(data_model)
771#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
772pub struct ArchetypeComponentId(usize);
773
774impl SparseSetIndex for ArchetypeComponentId {
775 #[inline]
776 fn sparse_set_index(&self) -> usize {
777 self.0
778 }
779
780 fn get_sparse_set_index(value: usize) -> Self {
781 Self(value)
782 }
783}
784
785/// Maps a [`ComponentId`] to the list of [`Archetypes`]([`Archetype`]) that contain the [`Component`](crate::component::Component),
786/// along with an [`ArchetypeRecord`] which contains some metadata about how the component is stored in the archetype.
787pub type ComponentIndex = HashMap<ComponentId, HashMap<ArchetypeId, ArchetypeRecord>>;
788
789/// The backing store of all [`Archetype`]s within a [`World`].
790///
791/// For more information, see the *[module level documentation]*.
792///
793/// [`World`]: crate::world::World
794/// [module level documentation]: crate::archetype
795pub struct Archetypes {
796 pub(crate) archetypes: Vec<Archetype>,
797 archetype_component_count: usize,
798 /// find the archetype id by the archetype's components
799 by_components: HashMap<ArchetypeComponents, ArchetypeId>,
800 /// find all the archetypes that contain a component
801 pub(crate) by_component: ComponentIndex,
802}
803
804/// Metadata about how a component is stored in an [`Archetype`].
805pub struct ArchetypeRecord {
806 /// Index of the component in the archetype's [`Table`](crate::storage::Table),
807 /// or None if the component is a sparse set component.
808 #[expect(
809 dead_code,
810 reason = "Currently unused, but planned to be used to implement a component index to improve performance of fragmenting relations."
811 )]
812 pub(crate) column: Option<usize>,
813}
814
815impl Archetypes {
816 pub(crate) fn new() -> Self {
817 let mut archetypes = Archetypes {
818 archetypes: Vec::new(),
819 by_components: Default::default(),
820 by_component: Default::default(),
821 archetype_component_count: 0,
822 };
823 // SAFETY: Empty archetype has no components
824 unsafe {
825 archetypes.get_id_or_insert(
826 &Components::default(),
827 &Observers::default(),
828 TableId::empty(),
829 Vec::new(),
830 Vec::new(),
831 );
832 }
833 archetypes
834 }
835
836 /// Returns the "generation", a handle to the current highest archetype ID.
837 ///
838 /// This can be used with the `Index` [`Archetypes`] implementation to
839 /// iterate over newly introduced [`Archetype`]s since the last time this
840 /// function was called.
841 #[inline]
842 pub fn generation(&self) -> ArchetypeGeneration {
843 let id = ArchetypeId::new(self.archetypes.len());
844 ArchetypeGeneration(id)
845 }
846
847 /// Fetches the total number of [`Archetype`]s within the world.
848 #[inline]
849 #[expect(
850 clippy::len_without_is_empty,
851 reason = "The internal vec is never empty"
852 )]
853 pub fn len(&self) -> usize {
854 self.archetypes.len()
855 }
856
857 /// Fetches an immutable reference to the archetype without any components.
858 ///
859 /// Shorthand for `archetypes.get(ArchetypeId::EMPTY).unwrap()`
860 #[inline]
861 pub fn empty(&self) -> &Archetype {
862 // SAFETY: empty archetype always exists
863 unsafe { self.archetypes.get_unchecked(ArchetypeId::EMPTY.index()) }
864 }
865
866 /// Fetches a mutable reference to the archetype without any components.
867 #[inline]
868 pub(crate) fn empty_mut(&mut self) -> &mut Archetype {
869 // SAFETY: empty archetype always exists
870 unsafe {
871 self.archetypes
872 .get_unchecked_mut(ArchetypeId::EMPTY.index())
873 }
874 }
875
876 /// Generate and store a new [`ArchetypeComponentId`].
877 ///
878 /// This simply increment the counter and return the new value.
879 ///
880 /// # Panics
881 ///
882 /// On archetype component id overflow.
883 pub(crate) fn new_archetype_component_id(&mut self) -> ArchetypeComponentId {
884 let id = ArchetypeComponentId(self.archetype_component_count);
885 self.archetype_component_count = self
886 .archetype_component_count
887 .checked_add(1)
888 .expect("archetype_component_count overflow");
889 id
890 }
891
892 /// Fetches an immutable reference to an [`Archetype`] using its
893 /// ID. Returns `None` if no corresponding archetype exists.
894 #[inline]
895 pub fn get(&self, id: ArchetypeId) -> Option<&Archetype> {
896 self.archetypes.get(id.index())
897 }
898
899 /// # Panics
900 ///
901 /// Panics if `a` and `b` are equal.
902 #[inline]
903 pub(crate) fn get_2_mut(
904 &mut self,
905 a: ArchetypeId,
906 b: ArchetypeId,
907 ) -> (&mut Archetype, &mut Archetype) {
908 if a.index() > b.index() {
909 let (b_slice, a_slice) = self.archetypes.split_at_mut(a.index());
910 (&mut a_slice[0], &mut b_slice[b.index()])
911 } else {
912 let (a_slice, b_slice) = self.archetypes.split_at_mut(b.index());
913 (&mut a_slice[a.index()], &mut b_slice[0])
914 }
915 }
916
917 /// Returns a read-only iterator over all archetypes.
918 #[inline]
919 pub fn iter(&self) -> impl Iterator<Item = &Archetype> {
920 self.archetypes.iter()
921 }
922
923 /// Gets the archetype id matching the given inputs or inserts a new one if it doesn't exist.
924 /// `table_components` and `sparse_set_components` must be sorted
925 ///
926 /// # Safety
927 /// [`TableId`] must exist in tables
928 /// `table_components` and `sparse_set_components` must exist in `components`
929 pub(crate) unsafe fn get_id_or_insert(
930 &mut self,
931 components: &Components,
932 observers: &Observers,
933 table_id: TableId,
934 table_components: Vec<ComponentId>,
935 sparse_set_components: Vec<ComponentId>,
936 ) -> ArchetypeId {
937 let archetype_identity = ArchetypeComponents {
938 sparse_set_components: sparse_set_components.into_boxed_slice(),
939 table_components: table_components.into_boxed_slice(),
940 };
941
942 let archetypes = &mut self.archetypes;
943 let archetype_component_count = &mut self.archetype_component_count;
944 let component_index = &mut self.by_component;
945 *self
946 .by_components
947 .entry(archetype_identity)
948 .or_insert_with_key(move |identity| {
949 let ArchetypeComponents {
950 table_components,
951 sparse_set_components,
952 } = identity;
953 let id = ArchetypeId::new(archetypes.len());
954 let table_start = *archetype_component_count;
955 *archetype_component_count += table_components.len();
956 let table_archetype_components =
957 (table_start..*archetype_component_count).map(ArchetypeComponentId);
958 let sparse_start = *archetype_component_count;
959 *archetype_component_count += sparse_set_components.len();
960 let sparse_set_archetype_components =
961 (sparse_start..*archetype_component_count).map(ArchetypeComponentId);
962 archetypes.push(Archetype::new(
963 components,
964 component_index,
965 observers,
966 id,
967 table_id,
968 table_components
969 .iter()
970 .copied()
971 .zip(table_archetype_components),
972 sparse_set_components
973 .iter()
974 .copied()
975 .zip(sparse_set_archetype_components),
976 ));
977 id
978 })
979 }
980
981 /// Returns the number of components that are stored in archetypes.
982 /// Note that if some component `T` is stored in more than one archetype, it will be counted once for each archetype it's present in.
983 #[inline]
984 pub fn archetype_components_len(&self) -> usize {
985 self.archetype_component_count
986 }
987
988 /// Clears all entities from all archetypes.
989 pub(crate) fn clear_entities(&mut self) {
990 for archetype in &mut self.archetypes {
991 archetype.clear_entities();
992 }
993 }
994
995 /// Get the component index
996 pub(crate) fn component_index(&self) -> &ComponentIndex {
997 &self.by_component
998 }
999
1000 pub(crate) fn update_flags(
1001 &mut self,
1002 component_id: ComponentId,
1003 flags: ArchetypeFlags,
1004 set: bool,
1005 ) {
1006 if let Some(archetypes) = self.by_component.get(&component_id) {
1007 for archetype_id in archetypes.keys() {
1008 // SAFETY: the component index only contains valid archetype ids
1009 self.archetypes
1010 .get_mut(archetype_id.index())
1011 .unwrap()
1012 .flags
1013 .set(flags, set);
1014 }
1015 }
1016 }
1017}
1018
1019impl Index<RangeFrom<ArchetypeGeneration>> for Archetypes {
1020 type Output = [Archetype];
1021
1022 #[inline]
1023 fn index(&self, index: RangeFrom<ArchetypeGeneration>) -> &Self::Output {
1024 &self.archetypes[index.start.0.index()..]
1025 }
1026}
1027impl Index<ArchetypeId> for Archetypes {
1028 type Output = Archetype;
1029
1030 #[inline]
1031 fn index(&self, index: ArchetypeId) -> &Self::Output {
1032 &self.archetypes[index.index()]
1033 }
1034}
1035
1036impl IndexMut<ArchetypeId> for Archetypes {
1037 #[inline]
1038 fn index_mut(&mut self, index: ArchetypeId) -> &mut Self::Output {
1039 &mut self.archetypes[index.index()]
1040 }
1041}