//! Types for declaring and storing [`Component`]s. use crate::{ self as bevy_ecs, archetype::ArchetypeFlags, bundle::BundleInfo, change_detection::MAX_CHANGE_AGE, entity::Entity, storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow}, system::{Local, Resource, SystemParam}, world::{DeferredWorld, FromWorld, World}, }; pub use bevy_ecs_macros::Component; use bevy_ptr::{OwningPtr, UnsafeCellDeref}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; use bevy_utils::{HashMap, TypeIdMap}; #[cfg(feature = "track_change_detection")] use std::panic::Location; use std::{ alloc::Layout, any::{Any, TypeId}, borrow::Cow, marker::PhantomData, mem::needs_drop, sync::Arc, }; use std::{cell::UnsafeCell, fmt::Debug}; /// A data type that can be used to store data for an [entity]. /// /// `Component` is a [derivable trait]: this means that a data type can implement it by applying a `#[derive(Component)]` attribute to it. /// However, components must always satisfy the `Send + Sync + 'static` trait bounds. /// /// [entity]: crate::entity /// [derivable trait]: https://doc.rust-lang.org/book/appendix-03-derivable-traits.html /// /// # Examples /// /// 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. /// The following examples show how components are laid out in code. /// /// ``` /// # use bevy_ecs::component::Component; /// # struct Color; /// # /// // A component can contain data... /// #[derive(Component)] /// struct LicensePlate(String); /// /// // ... but it can also be a zero-sized marker. /// #[derive(Component)] /// struct Car; /// /// // Components can also be structs with named fields... /// #[derive(Component)] /// struct VehiclePerformance { /// acceleration: f32, /// top_speed: f32, /// handling: f32, /// } /// /// // ... or enums. /// #[derive(Component)] /// enum WheelCount { /// Two, /// Three, /// Four, /// } /// ``` /// /// # Component and data access /// /// See the [`entity`] module level documentation to learn how to add or remove components from an entity. /// /// See the documentation for [`Query`] to learn how to access component data from a system. /// /// [`entity`]: crate::entity#usage /// [`Query`]: crate::system::Query /// /// # Choosing a storage type /// /// Components can be stored in the world using different strategies with their own performance implications. /// By default, components are added to the [`Table`] storage, which is optimized for query iteration. /// /// Alternatively, components can be added to the [`SparseSet`] storage, which is optimized for component insertion and removal. /// This is achieved by adding an additional `#[component(storage = "SparseSet")]` attribute to the derive one: /// /// ``` /// # use bevy_ecs::component::Component; /// # /// #[derive(Component)] /// #[component(storage = "SparseSet")] /// struct ComponentA; /// ``` /// /// [`Table`]: crate::storage::Table /// [`SparseSet`]: crate::storage::SparseSet /// /// # Required Components /// /// Components can specify Required Components. If some [`Component`] `A` requires [`Component`] `B`, then when `A` is inserted, /// `B` will _also_ be initialized and inserted (if it was not manually specified). /// /// The [`Default`] constructor will be used to initialize the component, by default: /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component)] /// #[require(B)] /// struct A; /// /// #[derive(Component, Default, PartialEq, Eq, Debug)] /// struct B(usize); /// /// # let mut world = World::default(); /// // This will implicitly also insert B with the Default constructor /// let id = world.spawn(A).id(); /// assert_eq!(&B(0), world.entity(id).get::().unwrap()); /// /// // This will _not_ implicitly insert B, because it was already provided /// world.spawn((A, B(11))); /// ``` /// /// Components can have more than one required component: /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component)] /// #[require(B, C)] /// struct A; /// /// #[derive(Component, Default, PartialEq, Eq, Debug)] /// #[require(C)] /// struct B(usize); /// /// #[derive(Component, Default, PartialEq, Eq, Debug)] /// struct C(u32); /// /// # let mut world = World::default(); /// // This will implicitly also insert B and C with their Default constructors /// let id = world.spawn(A).id(); /// assert_eq!(&B(0), world.entity(id).get::().unwrap()); /// assert_eq!(&C(0), world.entity(id).get::().unwrap()); /// ``` /// /// You can also define a custom constructor: /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component)] /// #[require(B(init_b))] /// struct A; /// /// #[derive(Component, PartialEq, Eq, Debug)] /// struct B(usize); /// /// fn init_b() -> B { /// B(10) /// } /// /// # let mut world = World::default(); /// // This will implicitly also insert B with the init_b() constructor /// let id = world.spawn(A).id(); /// assert_eq!(&B(10), world.entity(id).get::().unwrap()); /// ``` /// /// Required components are _recursive_. This means, if a Required Component has required components, /// those components will _also_ be inserted if they are missing: /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component)] /// #[require(B)] /// struct A; /// /// #[derive(Component, Default, PartialEq, Eq, Debug)] /// #[require(C)] /// struct B(usize); /// /// #[derive(Component, Default, PartialEq, Eq, Debug)] /// struct C(u32); /// /// # let mut world = World::default(); /// // This will implicitly also insert B and C with their Default constructors /// let id = world.spawn(A).id(); /// assert_eq!(&B(0), world.entity(id).get::().unwrap()); /// assert_eq!(&C(0), world.entity(id).get::().unwrap()); /// ``` /// /// Note that cycles in the "component require tree" will result in stack overflows when attempting to /// insert a component. /// /// This "multiple inheritance" pattern does mean that it is possible to have duplicate requires for a given type /// at different levels of the inheritance tree: /// /// ``` /// # use bevy_ecs::prelude::*; /// #[derive(Component)] /// struct X(usize); /// /// #[derive(Component, Default)] /// #[require(X(x1))] /// struct Y; /// /// fn x1() -> X { /// X(1) /// } /// /// #[derive(Component)] /// #[require( /// Y, /// X(x2), /// )] /// struct Z; /// /// fn x2() -> X { /// X(2) /// } /// /// # let mut world = World::default(); /// // In this case, the x2 constructor is used for X /// let id = world.spawn(Z).id(); /// assert_eq!(2, world.entity(id).get::().unwrap().0); /// ``` /// /// In general, this shouldn't happen often, but when it does the algorithm is simple and predictable: /// 1. Use all of the constructors (including default constructors) directly defined in the spawned component's require list /// 2. In the order the requires are defined in `#[require()]`, recursively visit the require list of each of the components in the list (this is a depth Depth First Search). When a constructor is found, it will only be used if one has not already been found. /// /// From a user perspective, just think about this as the following: /// 1. Specifying a required component constructor for Foo directly on a spawned component Bar will result in that constructor being used (and overriding existing constructors lower in the inheritance tree). This is the classic "inheritance override" behavior people expect. /// 2. For cases where "multiple inheritance" results in constructor clashes, Components should be listed in "importance order". List a component earlier in the requirement list to initialize its inheritance tree earlier. /// /// # Adding component's hooks /// /// See [`ComponentHooks`] for a detailed explanation of component's hooks. /// /// Alternatively to the example shown in [`ComponentHooks`]' documentation, hooks can be configured using following attributes: /// - `#[component(on_add = on_add_function)]` /// - `#[component(on_insert = on_insert_function)]` /// - `#[component(on_replace = on_replace_function)]` /// - `#[component(on_remove = on_remove_function)]` /// /// ``` /// # use bevy_ecs::component::Component; /// # use bevy_ecs::world::DeferredWorld; /// # use bevy_ecs::entity::Entity; /// # use bevy_ecs::component::ComponentId; /// # /// #[derive(Component)] /// #[component(on_add = my_on_add_hook)] /// #[component(on_insert = my_on_insert_hook)] /// // Another possible way of configuring hooks: /// // #[component(on_add = my_on_add_hook, on_insert = my_on_insert_hook)] /// // /// // We don't have a replace or remove hook, so we can leave them out: /// // #[component(on_replace = my_on_replace_hook, on_remove = my_on_remove_hook)] /// struct ComponentA; /// /// fn my_on_add_hook(world: DeferredWorld, entity: Entity, id: ComponentId) { /// // ... /// } /// /// // You can also omit writing some types using generics. /// fn my_on_insert_hook(world: DeferredWorld, _: T1, _: T2) { /// // ... /// } /// /// ``` /// /// # Implementing the trait for foreign types /// /// 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. /// This means that it is not possible to directly have a type defined in a third party library as a component. /// This important limitation can be easily worked around using the [newtype pattern]: /// this makes it possible to locally define and implement `Component` for a tuple struct that wraps the foreign type. /// The following example gives a demonstration of this pattern. /// /// ``` /// // `Component` is defined in the `bevy_ecs` crate. /// use bevy_ecs::component::Component; /// /// // `Duration` is defined in the `std` crate. /// use std::time::Duration; /// /// // It is not possible to implement `Component` for `Duration` from this position, as they are /// // both foreign items, defined in an external crate. However, nothing prevents to define a new /// // `Cooldown` type that wraps `Duration`. As `Cooldown` is defined in a local crate, it is /// // possible to implement `Component` for it. /// #[derive(Component)] /// struct Cooldown(Duration); /// ``` /// /// [orphan rule]: https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type /// [newtype pattern]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types /// /// # `!Sync` Components /// A `!Sync` type cannot implement `Component`. However, it is possible to wrap a `Send` but not `Sync` /// type in [`SyncCell`] or the currently unstable [`Exclusive`] to make it `Sync`. This forces only /// having mutable access (`&mut T` only, never `&T`), but makes it safe to reference across multiple /// threads. /// /// This will fail to compile since `RefCell` is `!Sync`. /// ```compile_fail /// # use std::cell::RefCell; /// # use bevy_ecs::component::Component; /// #[derive(Component)] /// struct NotSync { /// counter: RefCell, /// } /// ``` /// /// This will compile since the `RefCell` is wrapped with `SyncCell`. /// ``` /// # use std::cell::RefCell; /// # use bevy_ecs::component::Component; /// use bevy_utils::synccell::SyncCell; /// /// // This will compile. /// #[derive(Component)] /// struct ActuallySync { /// counter: SyncCell>, /// } /// ``` /// /// [`SyncCell`]: bevy_utils::synccell::SyncCell /// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html #[diagnostic::on_unimplemented( message = "`{Self}` is not a `Component`", label = "invalid `Component`", note = "consider annotating `{Self}` with `#[derive(Component)]`" )] pub trait Component: Send + Sync + 'static { /// A constant indicating the storage type used for this component. const STORAGE_TYPE: StorageType; /// Called when registering this component, allowing mutable access to its [`ComponentHooks`]. fn register_component_hooks(_hooks: &mut ComponentHooks) {} /// Registers required components. fn register_required_components( _components: &mut Components, _storages: &mut Storages, _required_components: &mut RequiredComponents, ) { } } /// The storage used for a specific component type. /// /// # Examples /// The [`StorageType`] for a component is configured via the derive attribute /// /// ``` /// # use bevy_ecs::{prelude::*, component::*}; /// #[derive(Component)] /// #[component(storage = "SparseSet")] /// struct A; /// ``` #[derive(Debug, Copy, Clone, Default, Eq, PartialEq)] pub enum StorageType { /// Provides fast and cache-friendly iteration, but slower addition and removal of components. /// This is the default storage type. #[default] Table, /// Provides fast addition and removal of components, but slower iteration. SparseSet, } /// The type used for [`Component`] lifecycle hooks such as `on_add`, `on_insert` or `on_remove` pub type ComponentHook = for<'w> fn(DeferredWorld<'w>, Entity, ComponentId); /// [`World`]-mutating functions that run as part of lifecycle events of a [`Component`]. /// /// Hooks are functions that run when a component is added, overwritten, or removed from an entity. /// These are intended to be used for structural side effects that need to happen when a component is added or removed, /// and are not intended for general-purpose logic. /// /// For example, you might use a hook to update a cached index when a component is added, /// to clean up resources when a component is removed, /// or to keep hierarchical data structures across entities in sync. /// /// This information is stored in the [`ComponentInfo`] of the associated component. /// /// There is two ways of configuring hooks for a component: /// 1. Defining the [`Component::register_component_hooks`] method (see [`Component`]) /// 2. Using the [`World::register_component_hooks`] method /// /// # Example 2 /// /// ``` /// use bevy_ecs::prelude::*; /// use bevy_utils::HashSet; /// /// #[derive(Component)] /// struct MyTrackedComponent; /// /// #[derive(Resource, Default)] /// struct TrackedEntities(HashSet); /// /// let mut world = World::new(); /// world.init_resource::(); /// /// // No entities with `MyTrackedComponent` have been added yet, so we can safely add component hooks /// let mut tracked_component_query = world.query::<&MyTrackedComponent>(); /// assert!(tracked_component_query.iter(&world).next().is_none()); /// /// world.register_component_hooks::().on_add(|mut world, entity, _component_id| { /// let mut tracked_entities = world.resource_mut::(); /// tracked_entities.0.insert(entity); /// }); /// /// world.register_component_hooks::().on_remove(|mut world, entity, _component_id| { /// let mut tracked_entities = world.resource_mut::(); /// tracked_entities.0.remove(&entity); /// }); /// /// let entity = world.spawn(MyTrackedComponent).id(); /// let tracked_entities = world.resource::(); /// assert!(tracked_entities.0.contains(&entity)); /// /// world.despawn(entity); /// let tracked_entities = world.resource::(); /// assert!(!tracked_entities.0.contains(&entity)); /// ``` #[derive(Debug, Clone, Default)] pub struct ComponentHooks { pub(crate) on_add: Option, pub(crate) on_insert: Option, pub(crate) on_replace: Option, pub(crate) on_remove: Option, } impl ComponentHooks { /// Register a [`ComponentHook`] that will be run when this component is added to an entity. /// An `on_add` hook will always run before `on_insert` hooks. Spawning an entity counts as /// adding all of its components. /// /// # Panics /// /// Will panic if the component already has an `on_add` hook pub fn on_add(&mut self, hook: ComponentHook) -> &mut Self { self.try_on_add(hook) .expect("Component id: {:?}, already has an on_add hook") } /// Register a [`ComponentHook`] that will be run when this component is added (with `.insert`) /// or replaced. /// /// An `on_insert` hook always runs after any `on_add` hooks (if the entity didn't already have the component). /// /// # Warning /// /// The hook won't run if the component is already present and is only mutated, such as in a system via a query. /// As a result, this is *not* an appropriate mechanism for reliably updating indexes and other caches. /// /// # Panics /// /// Will panic if the component already has an `on_insert` hook pub fn on_insert(&mut self, hook: ComponentHook) -> &mut Self { self.try_on_insert(hook) .expect("Component id: {:?}, already has an on_insert hook") } /// Register a [`ComponentHook`] that will be run when this component is about to be dropped, /// such as being replaced (with `.insert`) or removed. /// /// If this component is inserted onto an entity that already has it, this hook will run before the value is replaced, /// allowing access to the previous data just before it is dropped. /// This hook does *not* run if the entity did not already have this component. /// /// An `on_replace` hook always runs before any `on_remove` hooks (if the component is being removed from the entity). /// /// # Warning /// /// The hook won't run if the component is already present and is only mutated, such as in a system via a query. /// As a result, this is *not* an appropriate mechanism for reliably updating indexes and other caches. /// /// # Panics /// /// Will panic if the component already has an `on_replace` hook pub fn on_replace(&mut self, hook: ComponentHook) -> &mut Self { self.try_on_replace(hook) .expect("Component id: {:?}, already has an on_replace hook") } /// Register a [`ComponentHook`] that will be run when this component is removed from an entity. /// Despawning an entity counts as removing all of its components. /// /// # Panics /// /// Will panic if the component already has an `on_remove` hook pub fn on_remove(&mut self, hook: ComponentHook) -> &mut Self { self.try_on_remove(hook) .expect("Component id: {:?}, already has an on_remove hook") } /// Attempt to register a [`ComponentHook`] that will be run when this component is added to an entity. /// /// This is a fallible version of [`Self::on_add`]. /// /// Returns `None` if the component already has an `on_add` hook. pub fn try_on_add(&mut self, hook: ComponentHook) -> Option<&mut Self> { if self.on_add.is_some() { return None; } self.on_add = Some(hook); Some(self) } /// Attempt to register a [`ComponentHook`] that will be run when this component is added (with `.insert`) /// /// This is a fallible version of [`Self::on_insert`]. /// /// Returns `None` if the component already has an `on_insert` hook. pub fn try_on_insert(&mut self, hook: ComponentHook) -> Option<&mut Self> { if self.on_insert.is_some() { return None; } self.on_insert = Some(hook); Some(self) } /// Attempt to register a [`ComponentHook`] that will be run when this component is replaced (with `.insert`) or removed /// /// This is a fallible version of [`Self::on_replace`]. /// /// Returns `None` if the component already has an `on_replace` hook. pub fn try_on_replace(&mut self, hook: ComponentHook) -> Option<&mut Self> { if self.on_replace.is_some() { return None; } self.on_replace = Some(hook); Some(self) } /// Attempt to register a [`ComponentHook`] that will be run when this component is removed from an entity. /// /// This is a fallible version of [`Self::on_remove`]. /// /// Returns `None` if the component already has an `on_remove` hook. pub fn try_on_remove(&mut self, hook: ComponentHook) -> Option<&mut Self> { if self.on_remove.is_some() { return None; } self.on_remove = Some(hook); Some(self) } } /// Stores metadata for a type of component or resource stored in a specific [`World`]. #[derive(Debug, Clone)] pub struct ComponentInfo { id: ComponentId, descriptor: ComponentDescriptor, hooks: ComponentHooks, required_components: RequiredComponents, } impl ComponentInfo { /// Returns a value uniquely identifying the current component. #[inline] pub fn id(&self) -> ComponentId { self.id } /// Returns the name of the current component. #[inline] pub fn name(&self) -> &str { &self.descriptor.name } /// Returns the [`TypeId`] of the underlying component type. /// Returns `None` if the component does not correspond to a Rust type. #[inline] pub fn type_id(&self) -> Option { self.descriptor.type_id } /// Returns the layout used to store values of this component in memory. #[inline] pub fn layout(&self) -> Layout { self.descriptor.layout } #[inline] /// Get the function which should be called to clean up values of /// the underlying component type. This maps to the /// [`Drop`] implementation for 'normal' Rust components /// /// Returns `None` if values of the underlying component type don't /// need to be dropped, e.g. as reported by [`needs_drop`]. pub fn drop(&self) -> Option)> { self.descriptor.drop } /// Returns a value indicating the storage strategy for the current component. #[inline] pub fn storage_type(&self) -> StorageType { self.descriptor.storage_type } /// Returns `true` if the underlying component type can be freely shared between threads. /// If this returns `false`, then extra care must be taken to ensure that components /// are not accessed from the wrong thread. #[inline] pub fn is_send_and_sync(&self) -> bool { self.descriptor.is_send_and_sync } /// Create a new [`ComponentInfo`]. pub(crate) fn new(id: ComponentId, descriptor: ComponentDescriptor) -> Self { ComponentInfo { id, descriptor, hooks: Default::default(), required_components: Default::default(), } } /// Update the given flags to include any [`ComponentHook`] registered to self #[inline] pub(crate) fn update_archetype_flags(&self, flags: &mut ArchetypeFlags) { if self.hooks().on_add.is_some() { flags.insert(ArchetypeFlags::ON_ADD_HOOK); } if self.hooks().on_insert.is_some() { flags.insert(ArchetypeFlags::ON_INSERT_HOOK); } if self.hooks().on_replace.is_some() { flags.insert(ArchetypeFlags::ON_REPLACE_HOOK); } if self.hooks().on_remove.is_some() { flags.insert(ArchetypeFlags::ON_REMOVE_HOOK); } } /// Provides a reference to the collection of hooks associated with this [`Component`] pub fn hooks(&self) -> &ComponentHooks { &self.hooks } /// Retrieves the [`RequiredComponents`] collection, which contains all required components (and their constructors) /// needed by this component. This includes _recursive_ required components. pub fn required_components(&self) -> &RequiredComponents { &self.required_components } } /// A value which uniquely identifies the type of a [`Component`] or [`Resource`] within a /// [`World`]. /// /// Each time a new `Component` type is registered within a `World` using /// e.g. [`World::init_component`] or [`World::init_component_with_descriptor`] /// or a Resource with e.g. [`World::init_resource`], /// a corresponding `ComponentId` is created to track it. /// /// While the distinction between `ComponentId` and [`TypeId`] may seem superficial, breaking them /// into two separate but related concepts allows components to exist outside of Rust's type system. /// Each Rust type registered as a `Component` will have a corresponding `ComponentId`, but additional /// `ComponentId`s may exist in a `World` to track components which cannot be /// represented as Rust types for scripting or other advanced use-cases. /// /// A `ComponentId` is tightly coupled to its parent `World`. Attempting to use a `ComponentId` from /// one `World` to access the metadata of a `Component` in a different `World` is undefined behavior /// and must not be attempted. /// /// Given a type `T` which implements [`Component`], the `ComponentId` for `T` can be retrieved /// from a `World` using [`World::component_id()`] or via [`Components::component_id()`]. Access /// to the `ComponentId` for a [`Resource`] is available via [`Components::resource_id()`]. #[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] #[cfg_attr( feature = "bevy_reflect", derive(Reflect), reflect(Debug, Hash, PartialEq) )] pub struct ComponentId(usize); impl ComponentId { /// Creates a new [`ComponentId`]. /// /// The `index` is a unique value associated with each type of component in a given world. /// Usually, this value is taken from a counter incremented for each type of component registered with the world. #[inline] pub const fn new(index: usize) -> ComponentId { ComponentId(index) } /// Returns the index of the current component. #[inline] pub fn index(self) -> usize { self.0 } } impl SparseSetIndex for ComponentId { #[inline] fn sparse_set_index(&self) -> usize { self.index() } #[inline] fn get_sparse_set_index(value: usize) -> Self { Self(value) } } /// A value describing a component or resource, which may or may not correspond to a Rust type. #[derive(Clone)] pub struct ComponentDescriptor { name: Cow<'static, str>, // SAFETY: This must remain private. It must match the statically known StorageType of the // associated rust component type if one exists. storage_type: StorageType, // SAFETY: This must remain private. It must only be set to "true" if this component is // actually Send + Sync is_send_and_sync: bool, type_id: Option, layout: Layout, // SAFETY: this function must be safe to call with pointers pointing to items of the type // this descriptor describes. // None if the underlying type doesn't need to be dropped drop: Option unsafe fn(OwningPtr<'a>)>, } // We need to ignore the `drop` field in our `Debug` impl impl Debug for ComponentDescriptor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("ComponentDescriptor") .field("name", &self.name) .field("storage_type", &self.storage_type) .field("is_send_and_sync", &self.is_send_and_sync) .field("type_id", &self.type_id) .field("layout", &self.layout) .finish() } } impl ComponentDescriptor { /// # Safety /// /// `x` must point to a valid value of type `T`. unsafe fn drop_ptr(x: OwningPtr<'_>) { // SAFETY: Contract is required to be upheld by the caller. unsafe { x.drop_as::(); } } /// Create a new `ComponentDescriptor` for the type `T`. pub fn new() -> Self { Self { name: Cow::Borrowed(std::any::type_name::()), storage_type: T::STORAGE_TYPE, is_send_and_sync: true, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: needs_drop::().then_some(Self::drop_ptr:: as _), } } /// Create a new `ComponentDescriptor`. /// /// # Safety /// - the `drop` fn must be usable on a pointer with a value of the layout `layout` /// - the component type must be safe to access from any thread (Send + Sync in rust terms) pub unsafe fn new_with_layout( name: impl Into>, storage_type: StorageType, layout: Layout, drop: Option unsafe fn(OwningPtr<'a>)>, ) -> Self { Self { name: name.into(), storage_type, is_send_and_sync: true, type_id: None, layout, drop, } } /// Create a new `ComponentDescriptor` for a resource. /// /// The [`StorageType`] for resources is always [`StorageType::Table`]. pub fn new_resource() -> Self { Self { name: Cow::Borrowed(std::any::type_name::()), // PERF: `SparseStorage` may actually be a more // reasonable choice as `storage_type` for resources. storage_type: StorageType::Table, is_send_and_sync: true, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: needs_drop::().then_some(Self::drop_ptr:: as _), } } fn new_non_send(storage_type: StorageType) -> Self { Self { name: Cow::Borrowed(std::any::type_name::()), storage_type, is_send_and_sync: false, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: needs_drop::().then_some(Self::drop_ptr:: as _), } } /// Returns a value indicating the storage strategy for the current component. #[inline] pub fn storage_type(&self) -> StorageType { self.storage_type } /// Returns the [`TypeId`] of the underlying component type. /// Returns `None` if the component does not correspond to a Rust type. #[inline] pub fn type_id(&self) -> Option { self.type_id } /// Returns the name of the current component. #[inline] pub fn name(&self) -> &str { self.name.as_ref() } } /// Stores metadata associated with each kind of [`Component`] in a given [`World`]. #[derive(Debug, Default)] pub struct Components { components: Vec, indices: TypeIdMap, resource_indices: TypeIdMap, } impl Components { /// Initializes a component of type `T` with this instance. /// If a component of this type has already been initialized, this will return /// the ID of the pre-existing component. /// /// # See also /// /// * [`Components::component_id()`] /// * [`Components::init_component_with_descriptor()`] #[inline] pub fn init_component(&mut self, storages: &mut Storages) -> ComponentId { let mut registered = false; let id = { let Components { indices, components, .. } = self; let type_id = TypeId::of::(); *indices.entry(type_id).or_insert_with(|| { let id = Components::init_component_inner( components, storages, ComponentDescriptor::new::(), ); registered = true; id }) }; if registered { let mut required_components = RequiredComponents::default(); T::register_required_components(self, storages, &mut required_components); let info = &mut self.components[id.index()]; T::register_component_hooks(&mut info.hooks); info.required_components = required_components; } id } /// Initializes a component described by `descriptor`. /// /// ## Note /// /// If this method is called multiple times with identical descriptors, a distinct `ComponentId` /// will be created for each one. /// /// # See also /// /// * [`Components::component_id()`] /// * [`Components::init_component()`] pub fn init_component_with_descriptor( &mut self, storages: &mut Storages, descriptor: ComponentDescriptor, ) -> ComponentId { Components::init_component_inner(&mut self.components, storages, descriptor) } #[inline] fn init_component_inner( components: &mut Vec, storages: &mut Storages, descriptor: ComponentDescriptor, ) -> ComponentId { let component_id = ComponentId(components.len()); let info = ComponentInfo::new(component_id, descriptor); if info.descriptor.storage_type == StorageType::SparseSet { storages.sparse_sets.get_or_insert(&info); } components.push(info); component_id } /// Returns the number of components registered with this instance. #[inline] pub fn len(&self) -> usize { self.components.len() } /// Returns `true` if there are no components registered with this instance. Otherwise, this returns `false`. #[inline] pub fn is_empty(&self) -> bool { self.components.len() == 0 } /// Gets the metadata associated with the given component. /// /// 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. #[inline] pub fn get_info(&self, id: ComponentId) -> Option<&ComponentInfo> { self.components.get(id.0) } /// Returns the name associated with the given component. /// /// 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. #[inline] pub fn get_name(&self, id: ComponentId) -> Option<&str> { self.get_info(id).map(ComponentInfo::name) } /// Gets the metadata associated with the given component. /// # Safety /// /// `id` must be a valid [`ComponentId`] #[inline] pub unsafe fn get_info_unchecked(&self, id: ComponentId) -> &ComponentInfo { debug_assert!(id.index() < self.components.len()); // SAFETY: The caller ensures `id` is valid. unsafe { self.components.get_unchecked(id.0) } } #[inline] pub(crate) fn get_hooks_mut(&mut self, id: ComponentId) -> Option<&mut ComponentHooks> { self.components.get_mut(id.0).map(|info| &mut info.hooks) } /// Type-erased equivalent of [`Components::component_id()`]. #[inline] pub fn get_id(&self, type_id: TypeId) -> Option { self.indices.get(&type_id).copied() } /// Returns the [`ComponentId`] of the given [`Component`] type `T`. /// /// The returned `ComponentId` is specific to the `Components` instance /// it was retrieved from and should not be used with another `Components` /// instance. /// /// Returns [`None`] if the `Component` type has not /// yet been initialized using [`Components::init_component()`]. /// /// ``` /// use bevy_ecs::prelude::*; /// /// let mut world = World::new(); /// /// #[derive(Component)] /// struct ComponentA; /// /// let component_a_id = world.init_component::(); /// /// assert_eq!(component_a_id, world.components().component_id::().unwrap()) /// ``` /// /// # See also /// /// * [`Components::get_id()`] /// * [`Components::resource_id()`] /// * [`World::component_id()`] #[inline] pub fn component_id(&self) -> Option { self.get_id(TypeId::of::()) } /// Type-erased equivalent of [`Components::resource_id()`]. #[inline] pub fn get_resource_id(&self, type_id: TypeId) -> Option { self.resource_indices.get(&type_id).copied() } /// Returns the [`ComponentId`] of the given [`Resource`] type `T`. /// /// The returned `ComponentId` is specific to the `Components` instance /// it was retrieved from and should not be used with another `Components` /// instance. /// /// Returns [`None`] if the `Resource` type has not /// yet been initialized using [`Components::init_resource()`]. /// /// ``` /// use bevy_ecs::prelude::*; /// /// let mut world = World::new(); /// /// #[derive(Resource, Default)] /// struct ResourceA; /// /// let resource_a_id = world.init_resource::(); /// /// assert_eq!(resource_a_id, world.components().resource_id::().unwrap()) /// ``` /// /// # See also /// /// * [`Components::component_id()`] /// * [`Components::get_resource_id()`] #[inline] pub fn resource_id(&self) -> Option { self.get_resource_id(TypeId::of::()) } /// Initializes a [`Resource`] of type `T` with this instance. /// If a resource of this type has already been initialized, this will return /// the ID of the pre-existing resource. /// /// # See also /// /// * [`Components::resource_id()`] #[inline] pub fn init_resource(&mut self) -> ComponentId { // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`] unsafe { self.get_or_insert_resource_with(TypeId::of::(), || { ComponentDescriptor::new_resource::() }) } } /// Initializes a [non-send resource](crate::system::NonSend) of type `T` with this instance. /// If a resource of this type has already been initialized, this will return /// the ID of the pre-existing resource. #[inline] pub fn init_non_send(&mut self) -> ComponentId { // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`] unsafe { self.get_or_insert_resource_with(TypeId::of::(), || { ComponentDescriptor::new_non_send::(StorageType::default()) }) } } /// # Safety /// /// The [`ComponentDescriptor`] must match the [`TypeId`] #[inline] unsafe fn get_or_insert_resource_with( &mut self, type_id: TypeId, func: impl FnOnce() -> ComponentDescriptor, ) -> ComponentId { let components = &mut self.components; *self.resource_indices.entry(type_id).or_insert_with(|| { let descriptor = func(); let component_id = ComponentId(components.len()); components.push(ComponentInfo::new(component_id, descriptor)); component_id }) } /// Gets an iterator over all components registered with this instance. pub fn iter(&self) -> impl Iterator + '_ { self.components.iter() } } /// A value that tracks when a system ran relative to other systems. /// This is used to power change detection. /// /// *Note* that a system that hasn't been run yet has a `Tick` of 0. #[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialEq)] #[cfg_attr( feature = "bevy_reflect", derive(Reflect), reflect(Debug, Hash, PartialEq) )] pub struct Tick { tick: u32, } impl Tick { /// The maximum relative age for a change tick. /// The value of this is equal to [`MAX_CHANGE_AGE`]. /// /// Since change detection will not work for any ticks older than this, /// ticks are periodically scanned to ensure their relative values are below this. pub const MAX: Self = Self::new(MAX_CHANGE_AGE); /// Creates a new [`Tick`] wrapping the given value. #[inline] pub const fn new(tick: u32) -> Self { Self { tick } } /// Gets the value of this change tick. #[inline] pub const fn get(self) -> u32 { self.tick } /// Sets the value of this change tick. #[inline] pub fn set(&mut self, tick: u32) { self.tick = tick; } /// Returns `true` if this `Tick` occurred since the system's `last_run`. /// /// `this_run` is the current tick of the system, used as a reference to help deal with wraparound. #[inline] pub fn is_newer_than(self, last_run: Tick, this_run: Tick) -> bool { // This works even with wraparound because the world tick (`this_run`) is always "newer" than // `last_run` and `self.tick`, and we scan periodically to clamp `ComponentTicks` values // so they never get older than `u32::MAX` (the difference would overflow). // // The clamp here ensures determinism (since scans could differ between app runs). let ticks_since_insert = this_run.relative_to(self).tick.min(MAX_CHANGE_AGE); let ticks_since_system = this_run.relative_to(last_run).tick.min(MAX_CHANGE_AGE); ticks_since_system > ticks_since_insert } /// Returns a change tick representing the relationship between `self` and `other`. #[inline] pub(crate) fn relative_to(self, other: Self) -> Self { let tick = self.tick.wrapping_sub(other.tick); Self { tick } } /// Wraps this change tick's value if it exceeds [`Tick::MAX`]. /// /// Returns `true` if wrapping was performed. Otherwise, returns `false`. #[inline] pub(crate) fn check_tick(&mut self, tick: Tick) -> bool { let age = tick.relative_to(*self); // This comparison assumes that `age` has not overflowed `u32::MAX` before, which will be true // so long as this check always runs before that can happen. if age.get() > Self::MAX.get() { *self = tick.relative_to(Self::MAX); true } else { false } } } /// Interior-mutable access to the [`Tick`]s for a single component or resource. #[derive(Copy, Clone, Debug)] pub struct TickCells<'a> { /// The tick indicating when the value was added to the world. pub added: &'a UnsafeCell, /// The tick indicating the last time the value was modified. pub changed: &'a UnsafeCell, } impl<'a> TickCells<'a> { /// # Safety /// All cells contained within must uphold the safety invariants of [`UnsafeCellDeref::read`]. #[inline] pub(crate) unsafe fn read(&self) -> ComponentTicks { ComponentTicks { // SAFETY: The callers uphold the invariants for `read`. added: unsafe { self.added.read() }, // SAFETY: The callers uphold the invariants for `read`. changed: unsafe { self.changed.read() }, } } } /// Records when a component or resource was added and when it was last mutably dereferenced (or added). #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))] pub struct ComponentTicks { pub(crate) added: Tick, pub(crate) changed: Tick, } impl ComponentTicks { /// Returns `true` if the component or resource was added after the system last ran /// (or the system is running for the first time). #[inline] pub fn is_added(&self, last_run: Tick, this_run: Tick) -> bool { self.added.is_newer_than(last_run, this_run) } /// Returns `true` if the component or resource was added or mutably dereferenced after the system last ran /// (or the system is running for the first time). #[inline] pub fn is_changed(&self, last_run: Tick, this_run: Tick) -> bool { self.changed.is_newer_than(last_run, this_run) } /// Returns the tick recording the time this component or resource was most recently changed. #[inline] pub fn last_changed_tick(&self) -> Tick { self.changed } /// Returns the tick recording the time this component or resource was added. #[inline] pub fn added_tick(&self) -> Tick { self.added } pub(crate) fn new(change_tick: Tick) -> Self { Self { added: change_tick, changed: change_tick, } } /// Manually sets the change tick. /// /// This is normally done automatically via the [`DerefMut`](std::ops::DerefMut) implementation /// on [`Mut`](crate::change_detection::Mut), [`ResMut`](crate::change_detection::ResMut), etc. /// However, components and resources that make use of interior mutability might require manual updates. /// /// # Example /// ```no_run /// # use bevy_ecs::{world::World, component::ComponentTicks}; /// let world: World = unimplemented!(); /// let component_ticks: ComponentTicks = unimplemented!(); /// /// component_ticks.set_changed(world.read_change_tick()); /// ``` #[inline] pub fn set_changed(&mut self, change_tick: Tick) { self.changed = change_tick; } } /// A [`SystemParam`] that provides access to the [`ComponentId`] for a specific component type. /// /// # Example /// ``` /// # use bevy_ecs::{system::Local, component::{Component, ComponentId, ComponentIdFor}}; /// #[derive(Component)] /// struct Player; /// fn my_system(component_id: ComponentIdFor) { /// let component_id: ComponentId = component_id.get(); /// // ... /// } /// ``` #[derive(SystemParam)] pub struct ComponentIdFor<'s, T: Component>(Local<'s, InitComponentId>); impl ComponentIdFor<'_, T> { /// Gets the [`ComponentId`] for the type `T`. #[inline] pub fn get(&self) -> ComponentId { **self } } impl std::ops::Deref for ComponentIdFor<'_, T> { type Target = ComponentId; fn deref(&self) -> &Self::Target { &self.0.component_id } } impl From> for ComponentId { #[inline] fn from(to_component_id: ComponentIdFor) -> ComponentId { *to_component_id } } /// Initializes the [`ComponentId`] for a specific type when used with [`FromWorld`]. struct InitComponentId { component_id: ComponentId, marker: PhantomData, } impl FromWorld for InitComponentId { fn from_world(world: &mut World) -> Self { Self { component_id: world.init_component::(), marker: PhantomData, } } } /// A Required Component constructor. See [`Component`] for details. #[cfg(feature = "track_change_detection")] #[derive(Clone)] pub struct RequiredComponentConstructor( pub Arc)>, ); /// A Required Component constructor. See [`Component`] for details. #[cfg(not(feature = "track_change_detection"))] #[derive(Clone)] pub struct RequiredComponentConstructor( pub Arc, ); impl RequiredComponentConstructor { /// # Safety /// This is intended to only be called in the context of [`BundleInfo::write_components`] to initialized required components. /// Calling it _anywhere else_ should be considered unsafe. /// /// `table_row` and `entity` must correspond to a valid entity that currently needs a component initialized via the constructor stored /// on this [`RequiredComponentConstructor`]. The stored constructor must correspond to a component on `entity` that needs initialization. /// `table` and `sparse_sets` must correspond to storages on a world where `entity` needs this required component initialized. /// /// Again, don't call this anywhere but [`BundleInfo::write_components`]. pub(crate) unsafe fn initialize( &self, table: &mut Table, sparse_sets: &mut SparseSets, change_tick: Tick, table_row: TableRow, entity: Entity, #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>, ) { (self.0)( table, sparse_sets, change_tick, table_row, entity, #[cfg(feature = "track_change_detection")] caller, ); } } /// The collection of metadata for components that are required for a given component. /// /// For more information, see the "Required Components" section of [`Component`]. #[derive(Default, Clone)] pub struct RequiredComponents(pub(crate) HashMap); impl Debug for RequiredComponents { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("RequiredComponents") .field(&self.0.keys()) .finish() } } impl RequiredComponents { /// Registers a required component. If the component is already registered, the new registration /// passed in the arguments will be ignored. /// /// # Safety /// /// `component_id` must match the type initialized by `constructor`. /// `constructor` _must_ initialize a component for `component_id` in such a way that /// matches the storage type of the component. It must only use the given `table_row` or `Entity` to /// initialize the storage for `component_id` corresponding to the given entity. pub unsafe fn register_dynamic( &mut self, component_id: ComponentId, constructor: RequiredComponentConstructor, ) { self.0.entry(component_id).or_insert(constructor); } /// Registers a required component. If the component is already registered, the new registration /// passed in the arguments will be ignored. pub fn register( &mut self, components: &mut Components, storages: &mut Storages, constructor: fn() -> C, ) { let component_id = components.init_component::(storages); let erased: RequiredComponentConstructor = RequiredComponentConstructor(Arc::new( move |table, sparse_sets, change_tick, table_row, entity, #[cfg(feature = "track_change_detection")] caller| { OwningPtr::make(constructor(), |ptr| { // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will // pass in a valid table_row and entity requiring a C constructor // C::STORAGE_TYPE is the storage type associated with `component_id` / `C` // `ptr` points to valid `C` data, which matches the type associated with `component_id` unsafe { BundleInfo::initialize_required_component( table, sparse_sets, change_tick, table_row, entity, component_id, C::STORAGE_TYPE, ptr, #[cfg(feature = "track_change_detection")] caller, ); } }); }, )); // SAFETY: // `component_id` matches the type initialized by the `erased` constructor above. // `erased` initializes a component for `component_id` in such a way that // matches the storage type of the component. It only uses the given `table_row` or `Entity` to // initialize the storage corresponding to the given entity. unsafe { self.register_dynamic(component_id, erased) }; } /// Iterates the ids of all required components. This includes recursive required components. pub fn iter_ids(&self) -> impl Iterator + '_ { self.0.keys().copied() } /// Removes components that are explicitly provided in a given [`Bundle`]. These components should /// be logically treated as normal components, not "required components". /// /// [`Bundle`]: crate::bundle::Bundle pub(crate) fn remove_explicit_components(&mut self, components: &[ComponentId]) { for component in components { self.0.remove(component); } } // Merges `required_components` into this collection. This only inserts a required component // if it _did not already exist_. pub(crate) fn merge(&mut self, required_components: &RequiredComponents) { for (id, constructor) in &required_components.0 { self.0.entry(*id).or_insert_with(|| constructor.clone()); } } }