bevy_ecs/
component.rs

1//! Types for declaring and storing [`Component`]s.
2
3use crate::{
4    self as bevy_ecs,
5    archetype::ArchetypeFlags,
6    change_detection::MAX_CHANGE_AGE,
7    entity::Entity,
8    storage::{SparseSetIndex, Storages},
9    system::{Local, Resource, SystemParam},
10    world::{DeferredWorld, FromWorld, World},
11};
12pub use bevy_ecs_macros::Component;
13use bevy_ptr::{OwningPtr, UnsafeCellDeref};
14#[cfg(feature = "bevy_reflect")]
15use bevy_reflect::Reflect;
16use bevy_utils::TypeIdMap;
17use std::cell::UnsafeCell;
18use std::{
19    alloc::Layout,
20    any::{Any, TypeId},
21    borrow::Cow,
22    marker::PhantomData,
23    mem::needs_drop,
24};
25
26/// A data type that can be used to store data for an [entity].
27///
28/// `Component` is a [derivable trait]: this means that a data type can implement it by applying a `#[derive(Component)]` attribute to it.
29/// However, components must always satisfy the `Send + Sync + 'static` trait bounds.
30///
31/// [entity]: crate::entity
32/// [derivable trait]: https://doc.rust-lang.org/book/appendix-03-derivable-traits.html
33///
34/// # Examples
35///
36/// Components can take many forms: they are usually structs, but can also be of every other kind of data type, like enums or zero sized types.
37/// The following examples show how components are laid out in code.
38///
39/// ```
40/// # use bevy_ecs::component::Component;
41/// # struct Color;
42/// #
43/// // A component can contain data...
44/// #[derive(Component)]
45/// struct LicensePlate(String);
46///
47/// // ... but it can also be a zero-sized marker.
48/// #[derive(Component)]
49/// struct Car;
50///
51/// // Components can also be structs with named fields...
52/// #[derive(Component)]
53/// struct VehiclePerformance {
54///     acceleration: f32,
55///     top_speed: f32,
56///     handling: f32,
57/// }
58///
59/// // ... or enums.
60/// #[derive(Component)]
61/// enum WheelCount {
62///     Two,
63///     Three,
64///     Four,
65/// }
66/// ```
67///
68/// # Component and data access
69///
70/// See the [`entity`] module level documentation to learn how to add or remove components from an entity.
71///
72/// See the documentation for [`Query`] to learn how to access component data from a system.
73///
74/// [`entity`]: crate::entity#usage
75/// [`Query`]: crate::system::Query
76///
77/// # Choosing a storage type
78///
79/// Components can be stored in the world using different strategies with their own performance implications.
80/// By default, components are added to the [`Table`] storage, which is optimized for query iteration.
81///
82/// Alternatively, components can be added to the [`SparseSet`] storage, which is optimized for component insertion and removal.
83/// This is achieved by adding an additional `#[component(storage = "SparseSet")]` attribute to the derive one:
84///
85/// ```
86/// # use bevy_ecs::component::Component;
87/// #
88/// #[derive(Component)]
89/// #[component(storage = "SparseSet")]
90/// struct ComponentA;
91/// ```
92///
93/// [`Table`]: crate::storage::Table
94/// [`SparseSet`]: crate::storage::SparseSet
95///
96/// # Implementing the trait for foreign types
97///
98/// As a consequence of the [orphan rule], it is not possible to separate into two different crates the implementation of `Component` from the definition of a type.
99/// This means that it is not possible to directly have a type defined in a third party library as a component.
100/// This important limitation can be easily worked around using the [newtype pattern]:
101/// this makes it possible to locally define and implement `Component` for a tuple struct that wraps the foreign type.
102/// The following example gives a demonstration of this pattern.
103///
104/// ```
105/// // `Component` is defined in the `bevy_ecs` crate.
106/// use bevy_ecs::component::Component;
107///
108/// // `Duration` is defined in the `std` crate.
109/// use std::time::Duration;
110///
111/// // It is not possible to implement `Component` for `Duration` from this position, as they are
112/// // both foreign items, defined in an external crate. However, nothing prevents to define a new
113/// // `Cooldown` type that wraps `Duration`. As `Cooldown` is defined in a local crate, it is
114/// // possible to implement `Component` for it.
115/// #[derive(Component)]
116/// struct Cooldown(Duration);
117/// ```
118///
119/// [orphan rule]: https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type
120/// [newtype pattern]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types
121///
122/// # `!Sync` Components
123/// A `!Sync` type cannot implement `Component`. However, it is possible to wrap a `Send` but not `Sync`
124/// type in [`SyncCell`] or the currently unstable [`Exclusive`] to make it `Sync`. This forces only
125/// having mutable access (`&mut T` only, never `&T`), but makes it safe to reference across multiple
126/// threads.
127///
128/// This will fail to compile since `RefCell` is `!Sync`.
129/// ```compile_fail
130/// # use std::cell::RefCell;
131/// # use bevy_ecs::component::Component;
132/// #[derive(Component)]
133/// struct NotSync {
134///    counter: RefCell<usize>,
135/// }
136/// ```
137///
138/// This will compile since the `RefCell` is wrapped with `SyncCell`.
139/// ```
140/// # use std::cell::RefCell;
141/// # use bevy_ecs::component::Component;
142/// use bevy_utils::synccell::SyncCell;
143///
144/// // This will compile.
145/// #[derive(Component)]
146/// struct ActuallySync {
147///    counter: SyncCell<RefCell<usize>>,
148/// }
149/// ```
150///
151/// [`SyncCell`]: bevy_utils::synccell::SyncCell
152/// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html
153#[diagnostic::on_unimplemented(
154    message = "`{Self}` is not a `Component`",
155    label = "invalid `Component`",
156    note = "consider annotating `{Self}` with `#[derive(Component)]`"
157)]
158pub trait Component: Send + Sync + 'static {
159    /// A constant indicating the storage type used for this component.
160    const STORAGE_TYPE: StorageType;
161
162    /// Called when registering this component, allowing mutable access to its [`ComponentHooks`].
163    fn register_component_hooks(_hooks: &mut ComponentHooks) {}
164}
165
166/// The storage used for a specific component type.
167///
168/// # Examples
169/// The [`StorageType`] for a component is configured via the derive attribute
170///
171/// ```
172/// # use bevy_ecs::{prelude::*, component::*};
173/// #[derive(Component)]
174/// #[component(storage = "SparseSet")]
175/// struct A;
176/// ```
177#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
178pub enum StorageType {
179    /// Provides fast and cache-friendly iteration, but slower addition and removal of components.
180    /// This is the default storage type.
181    #[default]
182    Table,
183    /// Provides fast addition and removal of components, but slower iteration.
184    SparseSet,
185}
186
187/// The type used for [`Component`] lifecycle hooks such as `on_add`, `on_insert` or `on_remove`
188pub type ComponentHook = for<'w> fn(DeferredWorld<'w>, Entity, ComponentId);
189
190/// [`World`]-mutating functions that run as part of lifecycle events of a [`Component`].
191///
192/// Hooks are functions that run when a component is added, overwritten, or removed from an entity.
193/// These are intended to be used for structural side effects that need to happen when a component is added or removed,
194/// and are not intended for general-purpose logic.
195///
196/// For example, you might use a hook to update a cached index when a component is added,
197/// to clean up resources when a component is removed,
198/// or to keep hierarchical data structures across entities in sync.
199///
200/// This information is stored in the [`ComponentInfo`] of the associated component.
201///
202/// # Example
203///
204/// ```
205/// use bevy_ecs::prelude::*;
206/// use bevy_utils::HashSet;
207///
208/// #[derive(Component)]
209/// struct MyTrackedComponent;
210///
211/// #[derive(Resource, Default)]
212/// struct TrackedEntities(HashSet<Entity>);
213///
214/// let mut world = World::new();
215/// world.init_resource::<TrackedEntities>();
216///
217/// // No entities with `MyTrackedComponent` have been added yet, so we can safely add component hooks
218/// let mut tracked_component_query = world.query::<&MyTrackedComponent>();
219/// assert!(tracked_component_query.iter(&world).next().is_none());
220///
221/// world.register_component_hooks::<MyTrackedComponent>().on_add(|mut world, entity, _component_id| {
222///    let mut tracked_entities = world.resource_mut::<TrackedEntities>();
223///   tracked_entities.0.insert(entity);
224/// });
225///
226/// world.register_component_hooks::<MyTrackedComponent>().on_remove(|mut world, entity, _component_id| {
227///   let mut tracked_entities = world.resource_mut::<TrackedEntities>();
228///   tracked_entities.0.remove(&entity);
229/// });
230///
231/// let entity = world.spawn(MyTrackedComponent).id();
232/// let tracked_entities = world.resource::<TrackedEntities>();
233/// assert!(tracked_entities.0.contains(&entity));
234///
235/// world.despawn(entity);
236/// let tracked_entities = world.resource::<TrackedEntities>();
237/// assert!(!tracked_entities.0.contains(&entity));
238/// ```
239#[derive(Debug, Clone, Default)]
240pub struct ComponentHooks {
241    pub(crate) on_add: Option<ComponentHook>,
242    pub(crate) on_insert: Option<ComponentHook>,
243    pub(crate) on_remove: Option<ComponentHook>,
244}
245
246impl ComponentHooks {
247    /// Register a [`ComponentHook`] that will be run when this component is added to an entity.
248    /// An `on_add` hook will always run before `on_insert` hooks. Spawning an entity counts as
249    /// adding all of its components.
250    ///
251    /// # Panics
252    ///
253    /// Will panic if the component already has an `on_add` hook
254    pub fn on_add(&mut self, hook: ComponentHook) -> &mut Self {
255        self.try_on_add(hook)
256            .expect("Component id: {:?}, already has an on_add hook")
257    }
258
259    /// Register a [`ComponentHook`] that will be run when this component is added (with `.insert`)
260    /// or replaced.
261    ///
262    /// An `on_insert` hook always runs after any `on_add` hooks (if the entity didn't already have the component).
263    ///
264    /// # Warning
265    ///
266    /// The hook won't run if the component is already present and is only mutated, such as in a system via a query.
267    /// As a result, this is *not* an appropriate mechanism for reliably updating indexes and other caches.
268    ///
269    /// # Panics
270    ///
271    /// Will panic if the component already has an `on_insert` hook
272    pub fn on_insert(&mut self, hook: ComponentHook) -> &mut Self {
273        self.try_on_insert(hook)
274            .expect("Component id: {:?}, already has an on_insert hook")
275    }
276
277    /// Register a [`ComponentHook`] that will be run when this component is removed from an entity.
278    /// Despawning an entity counts as removing all of its components.
279    ///
280    /// # Panics
281    ///
282    /// Will panic if the component already has an `on_remove` hook
283    pub fn on_remove(&mut self, hook: ComponentHook) -> &mut Self {
284        self.try_on_remove(hook)
285            .expect("Component id: {:?}, already has an on_remove hook")
286    }
287
288    /// Attempt to register a [`ComponentHook`] that will be run when this component is added to an entity.
289    ///
290    /// This is a fallible version of [`Self::on_add`].
291    ///
292    /// Returns `None` if the component already has an `on_add` hook.
293    pub fn try_on_add(&mut self, hook: ComponentHook) -> Option<&mut Self> {
294        if self.on_add.is_some() {
295            return None;
296        }
297        self.on_add = Some(hook);
298        Some(self)
299    }
300
301    /// Attempt to register a [`ComponentHook`] that will be run when this component is added (with `.insert`)
302    ///
303    /// This is a fallible version of [`Self::on_insert`].
304    ///
305    /// Returns `None` if the component already has an `on_insert` hook.
306    pub fn try_on_insert(&mut self, hook: ComponentHook) -> Option<&mut Self> {
307        if self.on_insert.is_some() {
308            return None;
309        }
310        self.on_insert = Some(hook);
311        Some(self)
312    }
313
314    /// Attempt to register a [`ComponentHook`] that will be run when this component is removed from an entity.
315    ///
316    /// This is a fallible version of [`Self::on_remove`].
317    ///
318    /// Returns `None` if the component already has an `on_remove` hook.
319    pub fn try_on_remove(&mut self, hook: ComponentHook) -> Option<&mut Self> {
320        if self.on_remove.is_some() {
321            return None;
322        }
323        self.on_remove = Some(hook);
324        Some(self)
325    }
326}
327
328/// Stores metadata for a type of component or resource stored in a specific [`World`].
329#[derive(Debug, Clone)]
330pub struct ComponentInfo {
331    id: ComponentId,
332    descriptor: ComponentDescriptor,
333    hooks: ComponentHooks,
334}
335
336impl ComponentInfo {
337    /// Returns a value uniquely identifying the current component.
338    #[inline]
339    pub fn id(&self) -> ComponentId {
340        self.id
341    }
342
343    /// Returns the name of the current component.
344    #[inline]
345    pub fn name(&self) -> &str {
346        &self.descriptor.name
347    }
348
349    /// Returns the [`TypeId`] of the underlying component type.
350    /// Returns `None` if the component does not correspond to a Rust type.
351    #[inline]
352    pub fn type_id(&self) -> Option<TypeId> {
353        self.descriptor.type_id
354    }
355
356    /// Returns the layout used to store values of this component in memory.
357    #[inline]
358    pub fn layout(&self) -> Layout {
359        self.descriptor.layout
360    }
361
362    #[inline]
363    /// Get the function which should be called to clean up values of
364    /// the underlying component type. This maps to the
365    /// [`Drop`] implementation for 'normal' Rust components
366    ///
367    /// Returns `None` if values of the underlying component type don't
368    /// need to be dropped, e.g. as reported by [`needs_drop`].
369    pub fn drop(&self) -> Option<unsafe fn(OwningPtr<'_>)> {
370        self.descriptor.drop
371    }
372
373    /// Returns a value indicating the storage strategy for the current component.
374    #[inline]
375    pub fn storage_type(&self) -> StorageType {
376        self.descriptor.storage_type
377    }
378
379    /// Returns `true` if the underlying component type can be freely shared between threads.
380    /// If this returns `false`, then extra care must be taken to ensure that components
381    /// are not accessed from the wrong thread.
382    #[inline]
383    pub fn is_send_and_sync(&self) -> bool {
384        self.descriptor.is_send_and_sync
385    }
386
387    /// Create a new [`ComponentInfo`].
388    pub(crate) fn new(id: ComponentId, descriptor: ComponentDescriptor) -> Self {
389        ComponentInfo {
390            id,
391            descriptor,
392            hooks: ComponentHooks::default(),
393        }
394    }
395
396    /// Update the given flags to include any [`ComponentHook`] registered to self
397    #[inline]
398    pub(crate) fn update_archetype_flags(&self, flags: &mut ArchetypeFlags) {
399        if self.hooks().on_add.is_some() {
400            flags.insert(ArchetypeFlags::ON_ADD_HOOK);
401        }
402        if self.hooks().on_insert.is_some() {
403            flags.insert(ArchetypeFlags::ON_INSERT_HOOK);
404        }
405        if self.hooks().on_remove.is_some() {
406            flags.insert(ArchetypeFlags::ON_REMOVE_HOOK);
407        }
408    }
409
410    /// Provides a reference to the collection of hooks associated with this [`Component`]
411    pub fn hooks(&self) -> &ComponentHooks {
412        &self.hooks
413    }
414}
415
416/// A value which uniquely identifies the type of a [`Component`] of [`Resource`] within a
417/// [`World`].
418///
419/// Each time a new `Component` type is registered within a `World` using
420/// e.g. [`World::init_component`] or [`World::init_component_with_descriptor`]
421/// or a Resource with e.g. [`World::init_resource`],
422/// a corresponding `ComponentId` is created to track it.
423///
424/// While the distinction between `ComponentId` and [`TypeId`] may seem superficial, breaking them
425/// into two separate but related concepts allows components to exist outside of Rust's type system.
426/// Each Rust type registered as a `Component` will have a corresponding `ComponentId`, but additional
427/// `ComponentId`s may exist in a `World` to track components which cannot be
428/// represented as Rust types for scripting or other advanced use-cases.
429///
430/// A `ComponentId` is tightly coupled to its parent `World`. Attempting to use a `ComponentId` from
431/// one `World` to access the metadata of a `Component` in a different `World` is undefined behavior
432/// and must not be attempted.
433///
434/// Given a type `T` which implements [`Component`], the `ComponentId` for `T` can be retrieved
435/// from a `World` using [`World::component_id()`] or via [`Components::component_id()`]. Access
436/// to the `ComponentId` for a [`Resource`] is available via [`Components::resource_id()`].
437#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
438#[cfg_attr(
439    feature = "bevy_reflect",
440    derive(Reflect),
441    reflect(Debug, Hash, PartialEq)
442)]
443pub struct ComponentId(usize);
444
445impl ComponentId {
446    /// Creates a new [`ComponentId`].
447    ///
448    /// The `index` is a unique value associated with each type of component in a given world.
449    /// Usually, this value is taken from a counter incremented for each type of component registered with the world.
450    #[inline]
451    pub const fn new(index: usize) -> ComponentId {
452        ComponentId(index)
453    }
454
455    /// Returns the index of the current component.
456    #[inline]
457    pub fn index(self) -> usize {
458        self.0
459    }
460}
461
462impl SparseSetIndex for ComponentId {
463    #[inline]
464    fn sparse_set_index(&self) -> usize {
465        self.index()
466    }
467
468    #[inline]
469    fn get_sparse_set_index(value: usize) -> Self {
470        Self(value)
471    }
472}
473
474/// A value describing a component or resource, which may or may not correspond to a Rust type.
475#[derive(Clone)]
476pub struct ComponentDescriptor {
477    name: Cow<'static, str>,
478    // SAFETY: This must remain private. It must match the statically known StorageType of the
479    // associated rust component type if one exists.
480    storage_type: StorageType,
481    // SAFETY: This must remain private. It must only be set to "true" if this component is
482    // actually Send + Sync
483    is_send_and_sync: bool,
484    type_id: Option<TypeId>,
485    layout: Layout,
486    // SAFETY: this function must be safe to call with pointers pointing to items of the type
487    // this descriptor describes.
488    // None if the underlying type doesn't need to be dropped
489    drop: Option<for<'a> unsafe fn(OwningPtr<'a>)>,
490}
491
492// We need to ignore the `drop` field in our `Debug` impl
493impl std::fmt::Debug for ComponentDescriptor {
494    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
495        f.debug_struct("ComponentDescriptor")
496            .field("name", &self.name)
497            .field("storage_type", &self.storage_type)
498            .field("is_send_and_sync", &self.is_send_and_sync)
499            .field("type_id", &self.type_id)
500            .field("layout", &self.layout)
501            .finish()
502    }
503}
504
505impl ComponentDescriptor {
506    /// # SAFETY
507    ///
508    /// `x` must points to a valid value of type `T`.
509    unsafe fn drop_ptr<T>(x: OwningPtr<'_>) {
510        // SAFETY: Contract is required to be upheld by the caller.
511        unsafe {
512            x.drop_as::<T>();
513        }
514    }
515
516    /// Create a new `ComponentDescriptor` for the type `T`.
517    pub fn new<T: Component>() -> Self {
518        Self {
519            name: Cow::Borrowed(std::any::type_name::<T>()),
520            storage_type: T::STORAGE_TYPE,
521            is_send_and_sync: true,
522            type_id: Some(TypeId::of::<T>()),
523            layout: Layout::new::<T>(),
524            drop: needs_drop::<T>().then_some(Self::drop_ptr::<T> as _),
525        }
526    }
527
528    /// Create a new `ComponentDescriptor`.
529    ///
530    /// # Safety
531    /// - the `drop` fn must be usable on a pointer with a value of the layout `layout`
532    /// - the component type must be safe to access from any thread (Send + Sync in rust terms)
533    pub unsafe fn new_with_layout(
534        name: impl Into<Cow<'static, str>>,
535        storage_type: StorageType,
536        layout: Layout,
537        drop: Option<for<'a> unsafe fn(OwningPtr<'a>)>,
538    ) -> Self {
539        Self {
540            name: name.into(),
541            storage_type,
542            is_send_and_sync: true,
543            type_id: None,
544            layout,
545            drop,
546        }
547    }
548
549    /// Create a new `ComponentDescriptor` for a resource.
550    ///
551    /// The [`StorageType`] for resources is always [`StorageType::Table`].
552    pub fn new_resource<T: Resource>() -> Self {
553        Self {
554            name: Cow::Borrowed(std::any::type_name::<T>()),
555            // PERF: `SparseStorage` may actually be a more
556            // reasonable choice as `storage_type` for resources.
557            storage_type: StorageType::Table,
558            is_send_and_sync: true,
559            type_id: Some(TypeId::of::<T>()),
560            layout: Layout::new::<T>(),
561            drop: needs_drop::<T>().then_some(Self::drop_ptr::<T> as _),
562        }
563    }
564
565    fn new_non_send<T: Any>(storage_type: StorageType) -> Self {
566        Self {
567            name: Cow::Borrowed(std::any::type_name::<T>()),
568            storage_type,
569            is_send_and_sync: false,
570            type_id: Some(TypeId::of::<T>()),
571            layout: Layout::new::<T>(),
572            drop: needs_drop::<T>().then_some(Self::drop_ptr::<T> as _),
573        }
574    }
575
576    /// Returns a value indicating the storage strategy for the current component.
577    #[inline]
578    pub fn storage_type(&self) -> StorageType {
579        self.storage_type
580    }
581
582    /// Returns the [`TypeId`] of the underlying component type.
583    /// Returns `None` if the component does not correspond to a Rust type.
584    #[inline]
585    pub fn type_id(&self) -> Option<TypeId> {
586        self.type_id
587    }
588
589    /// Returns the name of the current component.
590    #[inline]
591    pub fn name(&self) -> &str {
592        self.name.as_ref()
593    }
594}
595
596/// Stores metadata associated with each kind of [`Component`] in a given [`World`].
597#[derive(Debug, Default)]
598pub struct Components {
599    components: Vec<ComponentInfo>,
600    indices: TypeIdMap<ComponentId>,
601    resource_indices: TypeIdMap<ComponentId>,
602}
603
604impl Components {
605    /// Initializes a component of type `T` with this instance.
606    /// If a component of this type has already been initialized, this will return
607    /// the ID of the pre-existing component.
608    ///
609    /// # See also
610    ///
611    /// * [`Components::component_id()`]
612    /// * [`Components::init_component_with_descriptor()`]
613    #[inline]
614    pub fn init_component<T: Component>(&mut self, storages: &mut Storages) -> ComponentId {
615        let type_id = TypeId::of::<T>();
616
617        let Components {
618            indices,
619            components,
620            ..
621        } = self;
622        *indices.entry(type_id).or_insert_with(|| {
623            let index = Components::init_component_inner(
624                components,
625                storages,
626                ComponentDescriptor::new::<T>(),
627            );
628            T::register_component_hooks(&mut components[index.index()].hooks);
629            index
630        })
631    }
632
633    /// Initializes a component described by `descriptor`.
634    ///
635    /// ## Note
636    ///
637    /// If this method is called multiple times with identical descriptors, a distinct `ComponentId`
638    /// will be created for each one.
639    ///
640    /// # See also
641    ///
642    /// * [`Components::component_id()`]
643    /// * [`Components::init_component()`]
644    pub fn init_component_with_descriptor(
645        &mut self,
646        storages: &mut Storages,
647        descriptor: ComponentDescriptor,
648    ) -> ComponentId {
649        Components::init_component_inner(&mut self.components, storages, descriptor)
650    }
651
652    #[inline]
653    fn init_component_inner(
654        components: &mut Vec<ComponentInfo>,
655        storages: &mut Storages,
656        descriptor: ComponentDescriptor,
657    ) -> ComponentId {
658        let component_id = ComponentId(components.len());
659        let info = ComponentInfo::new(component_id, descriptor);
660        if info.descriptor.storage_type == StorageType::SparseSet {
661            storages.sparse_sets.get_or_insert(&info);
662        }
663        components.push(info);
664        component_id
665    }
666
667    /// Returns the number of components registered with this instance.
668    #[inline]
669    pub fn len(&self) -> usize {
670        self.components.len()
671    }
672
673    /// Returns `true` if there are no components registered with this instance. Otherwise, this returns `false`.
674    #[inline]
675    pub fn is_empty(&self) -> bool {
676        self.components.len() == 0
677    }
678
679    /// Gets the metadata associated with the given component.
680    ///
681    /// This will return an incorrect result if `id` did not come from the same world as `self`. It may return `None` or a garbage value.
682    #[inline]
683    pub fn get_info(&self, id: ComponentId) -> Option<&ComponentInfo> {
684        self.components.get(id.0)
685    }
686
687    /// Returns the name associated with the given component.
688    ///
689    /// This will return an incorrect result if `id` did not come from the same world as `self`. It may return `None` or a garbage value.
690    #[inline]
691    pub fn get_name(&self, id: ComponentId) -> Option<&str> {
692        self.get_info(id).map(|descriptor| descriptor.name())
693    }
694
695    /// Gets the metadata associated with the given component.
696    /// # Safety
697    ///
698    /// `id` must be a valid [`ComponentId`]
699    #[inline]
700    pub unsafe fn get_info_unchecked(&self, id: ComponentId) -> &ComponentInfo {
701        debug_assert!(id.index() < self.components.len());
702        // SAFETY: The caller ensures `id` is valid.
703        unsafe { self.components.get_unchecked(id.0) }
704    }
705
706    #[inline]
707    pub(crate) fn get_hooks_mut(&mut self, id: ComponentId) -> Option<&mut ComponentHooks> {
708        self.components.get_mut(id.0).map(|info| &mut info.hooks)
709    }
710
711    /// Type-erased equivalent of [`Components::component_id()`].
712    #[inline]
713    pub fn get_id(&self, type_id: TypeId) -> Option<ComponentId> {
714        self.indices.get(&type_id).copied()
715    }
716
717    /// Returns the [`ComponentId`] of the given [`Component`] type `T`.
718    ///
719    /// The returned `ComponentId` is specific to the `Components` instance
720    /// it was retrieved from and should not be used with another `Components`
721    /// instance.
722    ///
723    /// Returns [`None`] if the `Component` type has not
724    /// yet been initialized using [`Components::init_component()`].
725    ///
726    /// ```
727    /// use bevy_ecs::prelude::*;
728    ///
729    /// let mut world = World::new();
730    ///
731    /// #[derive(Component)]
732    /// struct ComponentA;
733    ///
734    /// let component_a_id = world.init_component::<ComponentA>();
735    ///
736    /// assert_eq!(component_a_id, world.components().component_id::<ComponentA>().unwrap())
737    /// ```
738    ///
739    /// # See also
740    ///
741    /// * [`Components::get_id()`]
742    /// * [`Components::resource_id()`]
743    /// * [`World::component_id()`]
744    #[inline]
745    pub fn component_id<T: Component>(&self) -> Option<ComponentId> {
746        self.get_id(TypeId::of::<T>())
747    }
748
749    /// Type-erased equivalent of [`Components::resource_id()`].
750    #[inline]
751    pub fn get_resource_id(&self, type_id: TypeId) -> Option<ComponentId> {
752        self.resource_indices.get(&type_id).copied()
753    }
754
755    /// Returns the [`ComponentId`] of the given [`Resource`] type `T`.
756    ///
757    /// The returned `ComponentId` is specific to the `Components` instance
758    /// it was retrieved from and should not be used with another `Components`
759    /// instance.
760    ///
761    /// Returns [`None`] if the `Resource` type has not
762    /// yet been initialized using [`Components::init_resource()`].
763    ///
764    /// ```
765    /// use bevy_ecs::prelude::*;
766    ///
767    /// let mut world = World::new();
768    ///
769    /// #[derive(Resource, Default)]
770    /// struct ResourceA;
771    ///
772    /// let resource_a_id = world.init_resource::<ResourceA>();
773    ///
774    /// assert_eq!(resource_a_id, world.components().resource_id::<ResourceA>().unwrap())
775    /// ```
776    ///
777    /// # See also
778    ///
779    /// * [`Components::component_id()`]
780    /// * [`Components::get_resource_id()`]
781    #[inline]
782    pub fn resource_id<T: Resource>(&self) -> Option<ComponentId> {
783        self.get_resource_id(TypeId::of::<T>())
784    }
785
786    /// Initializes a [`Resource`] of type `T` with this instance.
787    /// If a resource of this type has already been initialized, this will return
788    /// the ID of the pre-existing resource.
789    ///
790    /// # See also
791    ///
792    /// * [`Components::resource_id()`]
793    #[inline]
794    pub fn init_resource<T: Resource>(&mut self) -> ComponentId {
795        // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`]
796        unsafe {
797            self.get_or_insert_resource_with(TypeId::of::<T>(), || {
798                ComponentDescriptor::new_resource::<T>()
799            })
800        }
801    }
802
803    /// Initializes a [non-send resource](crate::system::NonSend) of type `T` with this instance.
804    /// If a resource of this type has already been initialized, this will return
805    /// the ID of the pre-existing resource.
806    #[inline]
807    pub fn init_non_send<T: Any>(&mut self) -> ComponentId {
808        // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`]
809        unsafe {
810            self.get_or_insert_resource_with(TypeId::of::<T>(), || {
811                ComponentDescriptor::new_non_send::<T>(StorageType::default())
812            })
813        }
814    }
815
816    /// # Safety
817    ///
818    /// The [`ComponentDescriptor`] must match the [`TypeId`]
819    #[inline]
820    unsafe fn get_or_insert_resource_with(
821        &mut self,
822        type_id: TypeId,
823        func: impl FnOnce() -> ComponentDescriptor,
824    ) -> ComponentId {
825        let components = &mut self.components;
826        *self.resource_indices.entry(type_id).or_insert_with(|| {
827            let descriptor = func();
828            let component_id = ComponentId(components.len());
829            components.push(ComponentInfo::new(component_id, descriptor));
830            component_id
831        })
832    }
833
834    /// Gets an iterator over all components registered with this instance.
835    pub fn iter(&self) -> impl Iterator<Item = &ComponentInfo> + '_ {
836        self.components.iter()
837    }
838}
839
840/// A value that tracks when a system ran relative to other systems.
841/// This is used to power change detection.
842///
843/// *Note* that a system that hasn't been run yet has a `Tick` of 0.
844#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialEq)]
845#[cfg_attr(
846    feature = "bevy_reflect",
847    derive(Reflect),
848    reflect(Debug, Hash, PartialEq)
849)]
850pub struct Tick {
851    tick: u32,
852}
853
854impl Tick {
855    /// The maximum relative age for a change tick.
856    /// The value of this is equal to [`MAX_CHANGE_AGE`].
857    ///
858    /// Since change detection will not work for any ticks older than this,
859    /// ticks are periodically scanned to ensure their relative values are below this.
860    pub const MAX: Self = Self::new(MAX_CHANGE_AGE);
861
862    /// Creates a new [`Tick`] wrapping the given value.
863    #[inline]
864    pub const fn new(tick: u32) -> Self {
865        Self { tick }
866    }
867
868    /// Gets the value of this change tick.
869    #[inline]
870    pub const fn get(self) -> u32 {
871        self.tick
872    }
873
874    /// Sets the value of this change tick.
875    #[inline]
876    pub fn set(&mut self, tick: u32) {
877        self.tick = tick;
878    }
879
880    /// Returns `true` if this `Tick` occurred since the system's `last_run`.
881    ///
882    /// `this_run` is the current tick of the system, used as a reference to help deal with wraparound.
883    #[inline]
884    pub fn is_newer_than(self, last_run: Tick, this_run: Tick) -> bool {
885        // This works even with wraparound because the world tick (`this_run`) is always "newer" than
886        // `last_run` and `self.tick`, and we scan periodically to clamp `ComponentTicks` values
887        // so they never get older than `u32::MAX` (the difference would overflow).
888        //
889        // The clamp here ensures determinism (since scans could differ between app runs).
890        let ticks_since_insert = this_run.relative_to(self).tick.min(MAX_CHANGE_AGE);
891        let ticks_since_system = this_run.relative_to(last_run).tick.min(MAX_CHANGE_AGE);
892
893        ticks_since_system > ticks_since_insert
894    }
895
896    /// Returns a change tick representing the relationship between `self` and `other`.
897    #[inline]
898    pub(crate) fn relative_to(self, other: Self) -> Self {
899        let tick = self.tick.wrapping_sub(other.tick);
900        Self { tick }
901    }
902
903    /// Wraps this change tick's value if it exceeds [`Tick::MAX`].
904    ///
905    /// Returns `true` if wrapping was performed. Otherwise, returns `false`.
906    #[inline]
907    pub(crate) fn check_tick(&mut self, tick: Tick) -> bool {
908        let age = tick.relative_to(*self);
909        // This comparison assumes that `age` has not overflowed `u32::MAX` before, which will be true
910        // so long as this check always runs before that can happen.
911        if age.get() > Self::MAX.get() {
912            *self = tick.relative_to(Self::MAX);
913            true
914        } else {
915            false
916        }
917    }
918}
919
920/// Interior-mutable access to the [`Tick`]s for a single component or resource.
921#[derive(Copy, Clone, Debug)]
922pub struct TickCells<'a> {
923    /// The tick indicating when the value was added to the world.
924    pub added: &'a UnsafeCell<Tick>,
925    /// The tick indicating the last time the value was modified.
926    pub changed: &'a UnsafeCell<Tick>,
927}
928
929impl<'a> TickCells<'a> {
930    /// # Safety
931    /// All cells contained within must uphold the safety invariants of [`UnsafeCellDeref::read`].
932    #[inline]
933    pub(crate) unsafe fn read(&self) -> ComponentTicks {
934        ComponentTicks {
935            // SAFETY: The callers uphold the invariants for `read`.
936            added: unsafe { self.added.read() },
937            // SAFETY: The callers uphold the invariants for `read`.
938            changed: unsafe { self.changed.read() },
939        }
940    }
941}
942
943/// Records when a component or resource was added and when it was last mutably dereferenced (or added).
944#[derive(Copy, Clone, Debug)]
945#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))]
946pub struct ComponentTicks {
947    pub(crate) added: Tick,
948    pub(crate) changed: Tick,
949}
950
951impl ComponentTicks {
952    /// Returns `true` if the component or resource was added after the system last ran
953    /// (or the system is running for the first time).
954    #[inline]
955    pub fn is_added(&self, last_run: Tick, this_run: Tick) -> bool {
956        self.added.is_newer_than(last_run, this_run)
957    }
958
959    /// Returns `true` if the component or resource was added or mutably dereferenced after the system last ran
960    /// (or the system is running for the first time).
961    #[inline]
962    pub fn is_changed(&self, last_run: Tick, this_run: Tick) -> bool {
963        self.changed.is_newer_than(last_run, this_run)
964    }
965
966    /// Returns the tick recording the time this component or resource was most recently changed.
967    #[inline]
968    pub fn last_changed_tick(&self) -> Tick {
969        self.changed
970    }
971
972    /// Returns the tick recording the time this component or resource was added.
973    #[inline]
974    pub fn added_tick(&self) -> Tick {
975        self.added
976    }
977
978    pub(crate) fn new(change_tick: Tick) -> Self {
979        Self {
980            added: change_tick,
981            changed: change_tick,
982        }
983    }
984
985    /// Manually sets the change tick.
986    ///
987    /// This is normally done automatically via the [`DerefMut`](std::ops::DerefMut) implementation
988    /// on [`Mut<T>`](crate::change_detection::Mut), [`ResMut<T>`](crate::change_detection::ResMut), etc.
989    /// However, components and resources that make use of interior mutability might require manual updates.
990    ///
991    /// # Example
992    /// ```no_run
993    /// # use bevy_ecs::{world::World, component::ComponentTicks};
994    /// let world: World = unimplemented!();
995    /// let component_ticks: ComponentTicks = unimplemented!();
996    ///
997    /// component_ticks.set_changed(world.read_change_tick());
998    /// ```
999    #[inline]
1000    pub fn set_changed(&mut self, change_tick: Tick) {
1001        self.changed = change_tick;
1002    }
1003}
1004
1005/// A [`SystemParam`] that provides access to the [`ComponentId`] for a specific component type.
1006///
1007/// # Example
1008/// ```
1009/// # use bevy_ecs::{system::Local, component::{Component, ComponentId, ComponentIdFor}};
1010/// #[derive(Component)]
1011/// struct Player;
1012/// fn my_system(component_id: ComponentIdFor<Player>) {
1013///     let component_id: ComponentId = component_id.get();
1014///     // ...
1015/// }
1016/// ```
1017#[derive(SystemParam)]
1018pub struct ComponentIdFor<'s, T: Component>(Local<'s, InitComponentId<T>>);
1019
1020impl<T: Component> ComponentIdFor<'_, T> {
1021    /// Gets the [`ComponentId`] for the type `T`.
1022    #[inline]
1023    pub fn get(&self) -> ComponentId {
1024        **self
1025    }
1026}
1027
1028impl<T: Component> std::ops::Deref for ComponentIdFor<'_, T> {
1029    type Target = ComponentId;
1030    fn deref(&self) -> &Self::Target {
1031        &self.0.component_id
1032    }
1033}
1034
1035impl<T: Component> From<ComponentIdFor<'_, T>> for ComponentId {
1036    #[inline]
1037    fn from(to_component_id: ComponentIdFor<T>) -> ComponentId {
1038        *to_component_id
1039    }
1040}
1041
1042/// Initializes the [`ComponentId`] for a specific type when used with [`FromWorld`].
1043struct InitComponentId<T: Component> {
1044    component_id: ComponentId,
1045    marker: PhantomData<T>,
1046}
1047
1048impl<T: Component> FromWorld for InitComponentId<T> {
1049    fn from_world(world: &mut World) -> Self {
1050        Self {
1051            component_id: world.init_component::<T>(),
1052            marker: PhantomData,
1053        }
1054    }
1055}