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}