bevy_ecs/
bundle.rs

1//! Types for handling [`Bundle`]s.
2//!
3//! This module contains the [`Bundle`] trait and some other helper types.
4
5use std::any::TypeId;
6
7pub use bevy_ecs_macros::Bundle;
8
9use crate::{
10    archetype::{
11        AddBundle, Archetype, ArchetypeId, Archetypes, BundleComponentStatus, ComponentStatus,
12        SpawnBundleStatus,
13    },
14    component::{Component, ComponentId, Components, StorageType, Tick},
15    entity::{Entities, Entity, EntityLocation},
16    observer::Observers,
17    prelude::World,
18    query::DebugCheckedUnwrap,
19    storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
20    world::{unsafe_world_cell::UnsafeWorldCell, ON_ADD, ON_INSERT},
21};
22
23use bevy_ptr::{ConstNonNull, OwningPtr};
24use bevy_utils::{all_tuples, HashMap, HashSet, TypeIdMap};
25use std::ptr::NonNull;
26
27/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
28///
29/// Implementors of the `Bundle` trait are called 'bundles'.
30///
31/// Each bundle represents a static set of [`Component`] types.
32/// Currently, bundles can only contain one of each [`Component`], and will
33/// panic once initialised if this is not met.
34///
35/// ## Insertion
36///
37/// The primary use for bundles is to add a useful collection of components to an entity.
38///
39/// Adding a value of bundle to an entity will add the components from the set it
40/// represents to the entity.
41/// The values of these components are taken from the bundle.
42/// If an entity already had one of these components, the entity's original component value
43/// will be overwritten.
44///
45/// Importantly, bundles are only their constituent set of components.
46/// You **should not** use bundles as a unit of behavior.
47/// The behavior of your app can only be considered in terms of components, as systems,
48/// which drive the behavior of a `bevy` application, operate on combinations of
49/// components.
50///
51/// This rule is also important because multiple bundles may contain the same component type,
52/// calculated in different ways — adding both of these bundles to one entity
53/// would create incoherent behavior.
54/// This would be unexpected if bundles were treated as an abstraction boundary, as
55/// the abstraction would be unmaintainable for these cases.
56/// For example, both `Camera3dBundle` and `Camera2dBundle` contain the `CameraRenderGraph`
57/// component, but specifying different render graphs to use.
58/// If the bundles were both added to the same entity, only one of these two bundles would work.
59///
60/// For this reason, there is intentionally no [`Query`] to match whether an entity
61/// contains the components of a bundle.
62/// Queries should instead only select the components they logically operate on.
63///
64/// ## Removal
65///
66/// Bundles are also used when removing components from an entity.
67///
68/// Removing a bundle from an entity will remove any of its components attached
69/// to the entity from the entity.
70/// That is, if the entity does not have all the components of the bundle, those
71/// which are present will be removed.
72///
73/// # Implementors
74///
75/// Every type which implements [`Component`] also implements `Bundle`, since
76/// [`Component`] types can be added to or removed from an entity.
77///
78/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
79/// These bundles contain the items of the 'inner' bundles.
80/// This is a convenient shorthand which is primarily used when spawning entities.
81/// For example, spawning an entity using the bundle `(SpriteBundle {...}, PlayerMarker)`
82/// will spawn an entity with components required for a 2d sprite, and the `PlayerMarker` component.
83///
84/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
85/// can also be considered as the empty tuple).
86/// This can be useful for spawning large numbers of empty entities using
87/// [`World::spawn_batch`](crate::world::World::spawn_batch).
88///
89/// Tuple bundles can be nested, which can be used to create an anonymous bundle with more than
90/// 15 items.
91/// However, in most cases where this is required, the derive macro [`derive@Bundle`] should be
92/// used instead.
93/// The derived `Bundle` implementation contains the items of its fields, which all must
94/// implement `Bundle`.
95/// As explained above, this includes any [`Component`] type, and other derived bundles.
96///
97/// If you want to add `PhantomData` to your `Bundle` you have to mark it with `#[bundle(ignore)]`.
98/// ```
99/// # use std::marker::PhantomData;
100/// use bevy_ecs::{component::Component, bundle::Bundle};
101///
102/// #[derive(Component)]
103/// struct XPosition(i32);
104/// #[derive(Component)]
105/// struct YPosition(i32);
106///
107/// #[derive(Bundle)]
108/// struct PositionBundle {
109///     // A bundle can contain components
110///     x: XPosition,
111///     y: YPosition,
112/// }
113///
114/// // You have to implement `Default` for ignored field types in bundle structs.
115/// #[derive(Default)]
116/// struct Other(f32);
117///
118/// #[derive(Bundle)]
119/// struct NamedPointBundle<T: Send + Sync + 'static> {
120///     // Or other bundles
121///     a: PositionBundle,
122///     // In addition to more components
123///     z: PointName,
124///
125///     // when you need to use `PhantomData` you have to mark it as ignored
126///     #[bundle(ignore)]
127///     _phantom_data: PhantomData<T>
128/// }
129///
130/// #[derive(Component)]
131/// struct PointName(String);
132/// ```
133///
134/// # Safety
135///
136/// Manual implementations of this trait are unsupported.
137/// That is, there is no safe way to implement this trait, and you must not do so.
138/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
139///
140/// [`Query`]: crate::system::Query
141// Some safety points:
142// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
143// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
144// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
145//   [`Bundle::component_ids`].
146#[diagnostic::on_unimplemented(
147    message = "`{Self}` is not a `Bundle`",
148    label = "invalid `Bundle`",
149    note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
150)]
151pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
152    /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s
153    #[doc(hidden)]
154    fn component_ids(
155        components: &mut Components,
156        storages: &mut Storages,
157        ids: &mut impl FnMut(ComponentId),
158    );
159
160    /// Gets this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered.
161    fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>));
162
163    /// Calls `func`, which should return data for each component in the bundle, in the order of
164    /// this bundle's [`Component`]s
165    ///
166    /// # Safety
167    /// Caller must return data for each component in the bundle, in the order of this bundle's
168    /// [`Component`]s
169    #[doc(hidden)]
170    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
171    where
172        // Ensure that the `OwningPtr` is used correctly
173        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
174        Self: Sized;
175}
176
177/// The parts from [`Bundle`] that don't require statically knowing the components of the bundle.
178pub trait DynamicBundle {
179    // SAFETY:
180    // The `StorageType` argument passed into [`Bundle::get_components`] must be correct for the
181    // component being fetched.
182    //
183    /// Calls `func` on each value, in the order of this bundle's [`Component`]s. This passes
184    /// ownership of the component values to `func`.
185    #[doc(hidden)]
186    fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>));
187}
188
189// SAFETY:
190// - `Bundle::component_ids` calls `ids` for C's component id (and nothing else)
191// - `Bundle::get_components` is called exactly once for C and passes the component's storage type based on its associated constant.
192// - `Bundle::from_components` calls `func` exactly once for C, which is the exact value returned by `Bundle::component_ids`.
193unsafe impl<C: Component> Bundle for C {
194    fn component_ids(
195        components: &mut Components,
196        storages: &mut Storages,
197        ids: &mut impl FnMut(ComponentId),
198    ) {
199        ids(components.init_component::<C>(storages));
200    }
201
202    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
203    where
204        // Ensure that the `OwningPtr` is used correctly
205        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
206        Self: Sized,
207    {
208        let ptr = func(ctx);
209        // Safety: The id given in `component_ids` is for `Self`
210        unsafe { ptr.read() }
211    }
212
213    fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)) {
214        ids(components.get_id(TypeId::of::<C>()));
215    }
216}
217
218impl<C: Component> DynamicBundle for C {
219    #[inline]
220    fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) {
221        OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, ptr));
222    }
223}
224
225macro_rules! tuple_impl {
226    ($($name: ident),*) => {
227        // SAFETY:
228        // - `Bundle::component_ids` calls `ids` for each component type in the
229        // bundle, in the exact order that `DynamicBundle::get_components` is called.
230        // - `Bundle::from_components` calls `func` exactly once for each `ComponentId` returned by `Bundle::component_ids`.
231        // - `Bundle::get_components` is called exactly once for each member. Relies on the above implementation to pass the correct
232        //   `StorageType` into the callback.
233        unsafe impl<$($name: Bundle),*> Bundle for ($($name,)*) {
234            #[allow(unused_variables)]
235            fn component_ids(components: &mut Components, storages: &mut Storages, ids: &mut impl FnMut(ComponentId)){
236                $(<$name as Bundle>::component_ids(components, storages, ids);)*
237            }
238
239            #[allow(unused_variables)]
240            fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)){
241                $(<$name as Bundle>::get_component_ids(components, ids);)*
242            }
243
244            #[allow(unused_variables, unused_mut)]
245            #[allow(clippy::unused_unit)]
246            unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
247            where
248                F: FnMut(&mut T) -> OwningPtr<'_>
249            {
250                #[allow(unused_unsafe)]
251                // SAFETY: Rust guarantees that tuple calls are evaluated 'left to right'.
252                // https://doc.rust-lang.org/reference/expressions.html#evaluation-order-of-operands
253                unsafe { ($(<$name as Bundle>::from_components(ctx, func),)*) }
254            }
255        }
256
257        impl<$($name: Bundle),*> DynamicBundle for ($($name,)*) {
258            #[allow(unused_variables, unused_mut)]
259            #[inline(always)]
260            fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) {
261                #[allow(non_snake_case)]
262                let ($(mut $name,)*) = self;
263                $(
264                    $name.get_components(&mut *func);
265                )*
266            }
267        }
268    }
269}
270
271all_tuples!(tuple_impl, 0, 15, B);
272
273/// For a specific [`World`], this stores a unique value identifying a type of a registered [`Bundle`].
274///
275/// [`World`]: crate::world::World
276#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
277pub struct BundleId(usize);
278
279impl BundleId {
280    /// Returns the index of the associated [`Bundle`] type.
281    ///
282    /// Note that this is unique per-world, and should not be reused across them.
283    #[inline]
284    pub fn index(self) -> usize {
285        self.0
286    }
287}
288
289impl SparseSetIndex for BundleId {
290    #[inline]
291    fn sparse_set_index(&self) -> usize {
292        self.index()
293    }
294
295    #[inline]
296    fn get_sparse_set_index(value: usize) -> Self {
297        Self(value)
298    }
299}
300
301/// Stores metadata associated with a specific type of [`Bundle`] for a given [`World`].
302///
303/// [`World`]: crate::world::World
304pub struct BundleInfo {
305    id: BundleId,
306    // SAFETY: Every ID in this list must be valid within the World that owns the BundleInfo,
307    // must have its storage initialized (i.e. columns created in tables, sparse set created),
308    // and must be in the same order as the source bundle type writes its components in.
309    component_ids: Vec<ComponentId>,
310}
311
312impl BundleInfo {
313    /// Create a new [`BundleInfo`].
314    ///
315    /// # Safety
316    ///
317    /// Every ID in `component_ids` must be valid within the World that owns the `BundleInfo`,
318    /// must have its storage initialized (i.e. columns created in tables, sparse set created),
319    /// and must be in the same order as the source bundle type writes its components in.
320    unsafe fn new(
321        bundle_type_name: &'static str,
322        components: &Components,
323        component_ids: Vec<ComponentId>,
324        id: BundleId,
325    ) -> BundleInfo {
326        let mut deduped = component_ids.clone();
327        deduped.sort();
328        deduped.dedup();
329
330        if deduped.len() != component_ids.len() {
331            // TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
332            let mut seen = HashSet::new();
333            let mut dups = Vec::new();
334            for id in component_ids {
335                if !seen.insert(id) {
336                    dups.push(id);
337                }
338            }
339
340            let names = dups
341                .into_iter()
342                .map(|id| {
343                    // SAFETY: the caller ensures component_id is valid.
344                    unsafe { components.get_info_unchecked(id).name() }
345                })
346                .collect::<Vec<_>>()
347                .join(", ");
348
349            panic!("Bundle {bundle_type_name} has duplicate components: {names}");
350        }
351
352        // SAFETY: The caller ensures that component_ids:
353        // - is valid for the associated world
354        // - has had its storage initialized
355        // - is in the same order as the source bundle type
356        BundleInfo { id, component_ids }
357    }
358
359    /// Returns a value identifying the associated [`Bundle`] type.
360    #[inline]
361    pub const fn id(&self) -> BundleId {
362        self.id
363    }
364
365    /// Returns the [ID](ComponentId) of each component stored in this bundle.
366    #[inline]
367    pub fn components(&self) -> &[ComponentId] {
368        &self.component_ids
369    }
370
371    /// Returns an iterator over the [ID](ComponentId) of each component stored in this bundle.
372    #[inline]
373    pub fn iter_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
374        self.component_ids.iter().cloned()
375    }
376
377    /// This writes components from a given [`Bundle`] to the given entity.
378    ///
379    /// # Safety
380    ///
381    /// `bundle_component_status` must return the "correct" [`ComponentStatus`] for each component
382    /// in the [`Bundle`], with respect to the entity's original archetype (prior to the bundle being added)
383    /// For example, if the original archetype already has `ComponentA` and `T` also has `ComponentA`, the status
384    /// should be `Mutated`. If the original archetype does not have `ComponentA`, the status should be `Added`.
385    /// When "inserting" a bundle into an existing entity, [`AddBundle`]
386    /// should be used, which will report `Added` vs `Mutated` status based on the current archetype's structure.
387    /// When spawning a bundle, [`SpawnBundleStatus`] can be used instead, which removes the need
388    /// to look up the [`AddBundle`] in the archetype graph, which requires
389    /// ownership of the entity's current archetype.
390    ///
391    /// `table` must be the "new" table for `entity`. `table_row` must have space allocated for the
392    /// `entity`, `bundle` must match this [`BundleInfo`]'s type
393    #[inline]
394    #[allow(clippy::too_many_arguments)]
395    unsafe fn write_components<T: DynamicBundle, S: BundleComponentStatus>(
396        &self,
397        table: &mut Table,
398        sparse_sets: &mut SparseSets,
399        bundle_component_status: &S,
400        entity: Entity,
401        table_row: TableRow,
402        change_tick: Tick,
403        bundle: T,
404    ) {
405        // NOTE: get_components calls this closure on each component in "bundle order".
406        // bundle_info.component_ids are also in "bundle order"
407        let mut bundle_component = 0;
408        bundle.get_components(&mut |storage_type, component_ptr| {
409            let component_id = *self.component_ids.get_unchecked(bundle_component);
410            match storage_type {
411                StorageType::Table => {
412                    let column =
413                        // SAFETY: If component_id is in self.component_ids, BundleInfo::new requires that
414                        // the target table contains the component.
415                        unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
416                    // SAFETY: bundle_component is a valid index for this bundle
417                    let status = unsafe { bundle_component_status.get_status(bundle_component) };
418                    match status {
419                        ComponentStatus::Added => {
420                            column.initialize(table_row, component_ptr, change_tick);
421                        }
422                        ComponentStatus::Mutated => {
423                            column.replace(table_row, component_ptr, change_tick);
424                        }
425                    }
426                }
427                StorageType::SparseSet => {
428                    let sparse_set =
429                        // SAFETY: If component_id is in self.component_ids, BundleInfo::new requires that
430                        // a sparse set exists for the component.
431                        unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
432                    sparse_set.insert(entity, component_ptr, change_tick);
433                }
434            }
435            bundle_component += 1;
436        });
437    }
438
439    /// Adds a bundle to the given archetype and returns the resulting archetype. This could be the
440    /// same [`ArchetypeId`], in the event that adding the given bundle does not result in an
441    /// [`Archetype`] change. Results are cached in the [`Archetype`] graph to avoid redundant work.
442    /// # Safety
443    /// `components` must be the same components as passed in [`Self::new`]
444    pub(crate) unsafe fn add_bundle_to_archetype(
445        &self,
446        archetypes: &mut Archetypes,
447        storages: &mut Storages,
448        components: &Components,
449        observers: &Observers,
450        archetype_id: ArchetypeId,
451    ) -> ArchetypeId {
452        if let Some(add_bundle_id) = archetypes[archetype_id].edges().get_add_bundle(self.id) {
453            return add_bundle_id;
454        }
455        let mut new_table_components = Vec::new();
456        let mut new_sparse_set_components = Vec::new();
457        let mut bundle_status = Vec::with_capacity(self.component_ids.len());
458        let mut added = Vec::new();
459
460        let current_archetype = &mut archetypes[archetype_id];
461        for component_id in self.component_ids.iter().cloned() {
462            if current_archetype.contains(component_id) {
463                bundle_status.push(ComponentStatus::Mutated);
464            } else {
465                bundle_status.push(ComponentStatus::Added);
466                added.push(component_id);
467                // SAFETY: component_id exists
468                let component_info = unsafe { components.get_info_unchecked(component_id) };
469                match component_info.storage_type() {
470                    StorageType::Table => new_table_components.push(component_id),
471                    StorageType::SparseSet => new_sparse_set_components.push(component_id),
472                }
473            }
474        }
475
476        if new_table_components.is_empty() && new_sparse_set_components.is_empty() {
477            let edges = current_archetype.edges_mut();
478            // the archetype does not change when we add this bundle
479            edges.insert_add_bundle(self.id, archetype_id, bundle_status, added);
480            archetype_id
481        } else {
482            let table_id;
483            let table_components;
484            let sparse_set_components;
485            // the archetype changes when we add this bundle. prepare the new archetype and storages
486            {
487                let current_archetype = &archetypes[archetype_id];
488                table_components = if new_table_components.is_empty() {
489                    // if there are no new table components, we can keep using this table
490                    table_id = current_archetype.table_id();
491                    current_archetype.table_components().collect()
492                } else {
493                    new_table_components.extend(current_archetype.table_components());
494                    // sort to ignore order while hashing
495                    new_table_components.sort();
496                    // SAFETY: all component ids in `new_table_components` exist
497                    table_id = unsafe {
498                        storages
499                            .tables
500                            .get_id_or_insert(&new_table_components, components)
501                    };
502
503                    new_table_components
504                };
505
506                sparse_set_components = if new_sparse_set_components.is_empty() {
507                    current_archetype.sparse_set_components().collect()
508                } else {
509                    new_sparse_set_components.extend(current_archetype.sparse_set_components());
510                    // sort to ignore order while hashing
511                    new_sparse_set_components.sort();
512                    new_sparse_set_components
513                };
514            };
515            // SAFETY: ids in self must be valid
516            let new_archetype_id = archetypes.get_id_or_insert(
517                components,
518                observers,
519                table_id,
520                table_components,
521                sparse_set_components,
522            );
523            // add an edge from the old archetype to the new archetype
524            archetypes[archetype_id].edges_mut().insert_add_bundle(
525                self.id,
526                new_archetype_id,
527                bundle_status,
528                added,
529            );
530            new_archetype_id
531        }
532    }
533}
534
535// SAFETY: We have exclusive world access so our pointers can't be invalidated externally
536pub(crate) struct BundleInserter<'w> {
537    world: UnsafeWorldCell<'w>,
538    bundle_info: ConstNonNull<BundleInfo>,
539    add_bundle: ConstNonNull<AddBundle>,
540    table: NonNull<Table>,
541    archetype: NonNull<Archetype>,
542    result: InsertBundleResult,
543    change_tick: Tick,
544}
545
546pub(crate) enum InsertBundleResult {
547    SameArchetype,
548    NewArchetypeSameTable {
549        new_archetype: NonNull<Archetype>,
550    },
551    NewArchetypeNewTable {
552        new_archetype: NonNull<Archetype>,
553        new_table: NonNull<Table>,
554    },
555}
556
557impl<'w> BundleInserter<'w> {
558    #[inline]
559    pub(crate) fn new<T: Bundle>(
560        world: &'w mut World,
561        archetype_id: ArchetypeId,
562        change_tick: Tick,
563    ) -> Self {
564        let bundle_id = world
565            .bundles
566            .init_info::<T>(&mut world.components, &mut world.storages);
567        // SAFETY: We just ensured this bundle exists
568        unsafe { Self::new_with_id(world, archetype_id, bundle_id, change_tick) }
569    }
570
571    /// Creates a new [`BundleInserter`].
572    ///
573    /// # Safety
574    /// - Caller must ensure that `bundle_id` exists in `world.bundles`.
575    #[inline]
576    pub(crate) unsafe fn new_with_id(
577        world: &'w mut World,
578        archetype_id: ArchetypeId,
579        bundle_id: BundleId,
580        change_tick: Tick,
581    ) -> Self {
582        // SAFETY: We will not make any accesses to the command queue, component or resource data of this world
583        let bundle_info = world.bundles.get_unchecked(bundle_id);
584        let bundle_id = bundle_info.id();
585        let new_archetype_id = bundle_info.add_bundle_to_archetype(
586            &mut world.archetypes,
587            &mut world.storages,
588            &world.components,
589            &world.observers,
590            archetype_id,
591        );
592        if new_archetype_id == archetype_id {
593            let archetype = &mut world.archetypes[archetype_id];
594            // SAFETY: The edge is assured to be initialized when we called add_bundle_to_archetype
595            let add_bundle = unsafe {
596                archetype
597                    .edges()
598                    .get_add_bundle_internal(bundle_id)
599                    .debug_checked_unwrap()
600            };
601            let table_id = archetype.table_id();
602            let table = &mut world.storages.tables[table_id];
603            Self {
604                add_bundle: add_bundle.into(),
605                archetype: archetype.into(),
606                bundle_info: bundle_info.into(),
607                table: table.into(),
608                result: InsertBundleResult::SameArchetype,
609                change_tick,
610                world: world.as_unsafe_world_cell(),
611            }
612        } else {
613            let (archetype, new_archetype) =
614                world.archetypes.get_2_mut(archetype_id, new_archetype_id);
615            // SAFETY: The edge is assured to be initialized when we called add_bundle_to_archetype
616            let add_bundle = unsafe {
617                archetype
618                    .edges()
619                    .get_add_bundle_internal(bundle_id)
620                    .debug_checked_unwrap()
621            };
622            let table_id = archetype.table_id();
623            let new_table_id = new_archetype.table_id();
624            if table_id == new_table_id {
625                let table = &mut world.storages.tables[table_id];
626                Self {
627                    add_bundle: add_bundle.into(),
628                    archetype: archetype.into(),
629                    bundle_info: bundle_info.into(),
630                    table: table.into(),
631                    result: InsertBundleResult::NewArchetypeSameTable {
632                        new_archetype: new_archetype.into(),
633                    },
634                    change_tick,
635                    world: world.as_unsafe_world_cell(),
636                }
637            } else {
638                let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id);
639                Self {
640                    add_bundle: add_bundle.into(),
641                    archetype: archetype.into(),
642                    bundle_info: bundle_info.into(),
643                    table: table.into(),
644                    result: InsertBundleResult::NewArchetypeNewTable {
645                        new_archetype: new_archetype.into(),
646                        new_table: new_table.into(),
647                    },
648                    change_tick,
649                    world: world.as_unsafe_world_cell(),
650                }
651            }
652        }
653    }
654
655    /// # Safety
656    /// `entity` must currently exist in the source archetype for this inserter. `location`
657    /// must be `entity`'s location in the archetype. `T` must match this [`BundleInfo`]'s type
658    #[inline]
659    pub(crate) unsafe fn insert<T: DynamicBundle>(
660        &mut self,
661        entity: Entity,
662        location: EntityLocation,
663        bundle: T,
664    ) -> EntityLocation {
665        let bundle_info = self.bundle_info.as_ref();
666        let add_bundle = self.add_bundle.as_ref();
667        let table = self.table.as_mut();
668        let archetype = self.archetype.as_mut();
669
670        let (new_archetype, new_location) = match &mut self.result {
671            InsertBundleResult::SameArchetype => {
672                // SAFETY: Mutable references do not alias and will be dropped after this block
673                let sparse_sets = {
674                    let world = self.world.world_mut();
675                    &mut world.storages.sparse_sets
676                };
677
678                bundle_info.write_components(
679                    table,
680                    sparse_sets,
681                    add_bundle,
682                    entity,
683                    location.table_row,
684                    self.change_tick,
685                    bundle,
686                );
687
688                (archetype, location)
689            }
690            InsertBundleResult::NewArchetypeSameTable { new_archetype } => {
691                let new_archetype = new_archetype.as_mut();
692
693                // SAFETY: Mutable references do not alias and will be dropped after this block
694                let (sparse_sets, entities) = {
695                    let world = self.world.world_mut();
696                    (&mut world.storages.sparse_sets, &mut world.entities)
697                };
698
699                let result = archetype.swap_remove(location.archetype_row);
700                if let Some(swapped_entity) = result.swapped_entity {
701                    let swapped_location =
702                        // SAFETY: If the swap was successful, swapped_entity must be valid.
703                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
704                    entities.set(
705                        swapped_entity.index(),
706                        EntityLocation {
707                            archetype_id: swapped_location.archetype_id,
708                            archetype_row: location.archetype_row,
709                            table_id: swapped_location.table_id,
710                            table_row: swapped_location.table_row,
711                        },
712                    );
713                }
714                let new_location = new_archetype.allocate(entity, result.table_row);
715                entities.set(entity.index(), new_location);
716                bundle_info.write_components(
717                    table,
718                    sparse_sets,
719                    add_bundle,
720                    entity,
721                    result.table_row,
722                    self.change_tick,
723                    bundle,
724                );
725
726                (new_archetype, new_location)
727            }
728            InsertBundleResult::NewArchetypeNewTable {
729                new_archetype,
730                new_table,
731            } => {
732                let new_table = new_table.as_mut();
733                let new_archetype = new_archetype.as_mut();
734
735                // SAFETY: Mutable references do not alias and will be dropped after this block
736                let (archetypes_ptr, sparse_sets, entities) = {
737                    let world = self.world.world_mut();
738                    let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr();
739                    (
740                        archetype_ptr,
741                        &mut world.storages.sparse_sets,
742                        &mut world.entities,
743                    )
744                };
745                let result = archetype.swap_remove(location.archetype_row);
746                if let Some(swapped_entity) = result.swapped_entity {
747                    let swapped_location =
748                        // SAFETY: If the swap was successful, swapped_entity must be valid.
749                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
750                    entities.set(
751                        swapped_entity.index(),
752                        EntityLocation {
753                            archetype_id: swapped_location.archetype_id,
754                            archetype_row: location.archetype_row,
755                            table_id: swapped_location.table_id,
756                            table_row: swapped_location.table_row,
757                        },
758                    );
759                }
760                // PERF: store "non bundle" components in edge, then just move those to avoid
761                // redundant copies
762                let move_result = table.move_to_superset_unchecked(result.table_row, new_table);
763                let new_location = new_archetype.allocate(entity, move_result.new_row);
764                entities.set(entity.index(), new_location);
765
766                // if an entity was moved into this entity's table spot, update its table row
767                if let Some(swapped_entity) = move_result.swapped_entity {
768                    let swapped_location =
769                        // SAFETY: If the swap was successful, swapped_entity must be valid.
770                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
771
772                    entities.set(
773                        swapped_entity.index(),
774                        EntityLocation {
775                            archetype_id: swapped_location.archetype_id,
776                            archetype_row: swapped_location.archetype_row,
777                            table_id: swapped_location.table_id,
778                            table_row: result.table_row,
779                        },
780                    );
781
782                    if archetype.id() == swapped_location.archetype_id {
783                        archetype
784                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
785                    } else if new_archetype.id() == swapped_location.archetype_id {
786                        new_archetype
787                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
788                    } else {
789                        // SAFETY: the only two borrowed archetypes are above and we just did collision checks
790                        (*archetypes_ptr.add(swapped_location.archetype_id.index()))
791                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
792                    }
793                }
794
795                bundle_info.write_components(
796                    new_table,
797                    sparse_sets,
798                    add_bundle,
799                    entity,
800                    move_result.new_row,
801                    self.change_tick,
802                    bundle,
803                );
804
805                (new_archetype, new_location)
806            }
807        };
808
809        let new_archetype = &*new_archetype;
810        // SAFETY: We have no outstanding mutable references to world as they were dropped
811        let mut deferred_world = unsafe { self.world.into_deferred() };
812
813        // SAFETY: All components in the bundle are guaranteed to exist in the World
814        // as they must be initialized before creating the BundleInfo.
815        unsafe {
816            deferred_world.trigger_on_add(new_archetype, entity, add_bundle.added.iter().cloned());
817            if new_archetype.has_add_observer() {
818                deferred_world.trigger_observers(ON_ADD, entity, add_bundle.added.iter().cloned());
819            }
820            deferred_world.trigger_on_insert(new_archetype, entity, bundle_info.iter_components());
821            if new_archetype.has_insert_observer() {
822                deferred_world.trigger_observers(ON_INSERT, entity, bundle_info.iter_components());
823            }
824        }
825
826        new_location
827    }
828
829    #[inline]
830    pub(crate) fn entities(&mut self) -> &mut Entities {
831        // SAFETY: No outstanding references to self.world, changes to entities cannot invalidate our internal pointers
832        unsafe { &mut self.world.world_mut().entities }
833    }
834}
835
836// SAFETY: We have exclusive world access so our pointers can't be invalidated externally
837pub(crate) struct BundleSpawner<'w> {
838    world: UnsafeWorldCell<'w>,
839    bundle_info: ConstNonNull<BundleInfo>,
840    table: NonNull<Table>,
841    archetype: NonNull<Archetype>,
842    change_tick: Tick,
843}
844
845impl<'w> BundleSpawner<'w> {
846    #[inline]
847    pub fn new<T: Bundle>(world: &'w mut World, change_tick: Tick) -> Self {
848        let bundle_id = world
849            .bundles
850            .init_info::<T>(&mut world.components, &mut world.storages);
851        // SAFETY: we initialized this bundle_id in `init_info`
852        unsafe { Self::new_with_id(world, bundle_id, change_tick) }
853    }
854
855    /// Creates a new [`BundleSpawner`].
856    ///
857    /// # Safety
858    /// Caller must ensure that `bundle_id` exists in `world.bundles`
859    #[inline]
860    pub(crate) unsafe fn new_with_id(
861        world: &'w mut World,
862        bundle_id: BundleId,
863        change_tick: Tick,
864    ) -> Self {
865        let bundle_info = world.bundles.get_unchecked(bundle_id);
866        let new_archetype_id = bundle_info.add_bundle_to_archetype(
867            &mut world.archetypes,
868            &mut world.storages,
869            &world.components,
870            &world.observers,
871            ArchetypeId::EMPTY,
872        );
873        let archetype = &mut world.archetypes[new_archetype_id];
874        let table = &mut world.storages.tables[archetype.table_id()];
875        Self {
876            bundle_info: bundle_info.into(),
877            table: table.into(),
878            archetype: archetype.into(),
879            change_tick,
880            world: world.as_unsafe_world_cell(),
881        }
882    }
883
884    #[inline]
885    pub fn reserve_storage(&mut self, additional: usize) {
886        // SAFETY: There are no outstanding world references
887        let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) };
888        archetype.reserve(additional);
889        table.reserve(additional);
890    }
891
892    /// # Safety
893    /// `entity` must be allocated (but non-existent), `T` must match this [`BundleInfo`]'s type
894    #[inline]
895    pub unsafe fn spawn_non_existent<T: DynamicBundle>(
896        &mut self,
897        entity: Entity,
898        bundle: T,
899    ) -> EntityLocation {
900        // SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid
901        let bundle_info = self.bundle_info.as_ref();
902        let location = {
903            let table = self.table.as_mut();
904            let archetype = self.archetype.as_mut();
905
906            // SAFETY: Mutable references do not alias and will be dropped after this block
907            let (sparse_sets, entities) = {
908                let world = self.world.world_mut();
909                (&mut world.storages.sparse_sets, &mut world.entities)
910            };
911            let table_row = table.allocate(entity);
912            let location = archetype.allocate(entity, table_row);
913            bundle_info.write_components(
914                table,
915                sparse_sets,
916                &SpawnBundleStatus,
917                entity,
918                table_row,
919                self.change_tick,
920                bundle,
921            );
922            entities.set(entity.index(), location);
923            location
924        };
925
926        // SAFETY: We have no outstanding mutable references to world as they were dropped
927        let mut deferred_world = unsafe { self.world.into_deferred() };
928        // SAFETY: `DeferredWorld` cannot provide mutable access to `Archetypes`.
929        let archetype = self.archetype.as_ref();
930        // SAFETY: All components in the bundle are guaranteed to exist in the World
931        // as they must be initialized before creating the BundleInfo.
932        unsafe {
933            deferred_world.trigger_on_add(archetype, entity, bundle_info.iter_components());
934            if archetype.has_add_observer() {
935                deferred_world.trigger_observers(ON_ADD, entity, bundle_info.iter_components());
936            }
937            deferred_world.trigger_on_insert(archetype, entity, bundle_info.iter_components());
938            if archetype.has_insert_observer() {
939                deferred_world.trigger_observers(ON_INSERT, entity, bundle_info.iter_components());
940            }
941        };
942
943        location
944    }
945
946    /// # Safety
947    /// `T` must match this [`BundleInfo`]'s type
948    #[inline]
949    pub unsafe fn spawn<T: Bundle>(&mut self, bundle: T) -> Entity {
950        let entity = self.entities().alloc();
951        // SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type
952        unsafe {
953            self.spawn_non_existent(entity, bundle);
954        }
955        entity
956    }
957
958    #[inline]
959    pub(crate) fn entities(&mut self) -> &mut Entities {
960        // SAFETY: No outstanding references to self.world, changes to entities cannot invalidate our internal pointers
961        unsafe { &mut self.world.world_mut().entities }
962    }
963
964    /// # Safety:
965    /// - `Self` must be dropped after running this function as it may invalidate internal pointers.
966    #[inline]
967    pub(crate) unsafe fn flush_commands(&mut self) {
968        // SAFETY: pointers on self can be invalidated,
969        self.world.world_mut().flush();
970    }
971}
972
973/// Metadata for bundles. Stores a [`BundleInfo`] for each type of [`Bundle`] in a given world.
974#[derive(Default)]
975pub struct Bundles {
976    bundle_infos: Vec<BundleInfo>,
977    /// Cache static [`BundleId`]
978    bundle_ids: TypeIdMap<BundleId>,
979    /// Cache dynamic [`BundleId`] with multiple components
980    dynamic_bundle_ids: HashMap<Box<[ComponentId]>, BundleId>,
981    dynamic_bundle_storages: HashMap<BundleId, Vec<StorageType>>,
982    /// Cache optimized dynamic [`BundleId`] with single component
983    dynamic_component_bundle_ids: HashMap<ComponentId, BundleId>,
984    dynamic_component_storages: HashMap<BundleId, StorageType>,
985}
986
987impl Bundles {
988    /// Gets the metadata associated with a specific type of bundle.
989    /// Returns `None` if the bundle is not registered with the world.
990    #[inline]
991    pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> {
992        self.bundle_infos.get(bundle_id.index())
993    }
994
995    /// Gets the value identifying a specific type of bundle.
996    /// Returns `None` if the bundle does not exist in the world,
997    /// or if `type_id` does not correspond to a type of bundle.
998    #[inline]
999    pub fn get_id(&self, type_id: TypeId) -> Option<BundleId> {
1000        self.bundle_ids.get(&type_id).cloned()
1001    }
1002
1003    /// Initializes a new [`BundleInfo`] for a statically known type.
1004    ///
1005    /// Also initializes all the components in the bundle.
1006    pub(crate) fn init_info<T: Bundle>(
1007        &mut self,
1008        components: &mut Components,
1009        storages: &mut Storages,
1010    ) -> BundleId {
1011        let bundle_infos = &mut self.bundle_infos;
1012        let id = *self.bundle_ids.entry(TypeId::of::<T>()).or_insert_with(|| {
1013            let mut component_ids = Vec::new();
1014            T::component_ids(components, storages, &mut |id| component_ids.push(id));
1015            let id = BundleId(bundle_infos.len());
1016            let bundle_info =
1017                // SAFETY: T::component_id ensures:
1018                // - its info was created
1019                // - appropriate storage for it has been initialized.
1020                // - it was created in the same order as the components in T
1021                unsafe { BundleInfo::new(std::any::type_name::<T>(), components, component_ids, id) };
1022            bundle_infos.push(bundle_info);
1023            id
1024        });
1025        id
1026    }
1027
1028    /// # Safety
1029    /// A `BundleInfo` with the given `BundleId` must have been initialized for this instance of `Bundles`.
1030    pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
1031        self.bundle_infos.get_unchecked(id.0)
1032    }
1033
1034    pub(crate) unsafe fn get_storage_unchecked(&self, id: BundleId) -> StorageType {
1035        *self
1036            .dynamic_component_storages
1037            .get(&id)
1038            .debug_checked_unwrap()
1039    }
1040
1041    pub(crate) unsafe fn get_storages_unchecked(&mut self, id: BundleId) -> &mut Vec<StorageType> {
1042        self.dynamic_bundle_storages
1043            .get_mut(&id)
1044            .debug_checked_unwrap()
1045    }
1046
1047    /// Initializes a new [`BundleInfo`] for a dynamic [`Bundle`].
1048    ///
1049    /// # Panics
1050    ///
1051    /// Panics if any of the provided [`ComponentId`]s do not exist in the
1052    /// provided [`Components`].
1053    pub(crate) fn init_dynamic_info(
1054        &mut self,
1055        components: &Components,
1056        component_ids: &[ComponentId],
1057    ) -> BundleId {
1058        let bundle_infos = &mut self.bundle_infos;
1059
1060        // Use `raw_entry_mut` to avoid cloning `component_ids` to access `Entry`
1061        let (_, bundle_id) = self
1062            .dynamic_bundle_ids
1063            .raw_entry_mut()
1064            .from_key(component_ids)
1065            .or_insert_with(|| {
1066                let (id, storages) =
1067                    initialize_dynamic_bundle(bundle_infos, components, Vec::from(component_ids));
1068                self.dynamic_bundle_storages
1069                    .insert_unique_unchecked(id, storages);
1070                (component_ids.into(), id)
1071            });
1072        *bundle_id
1073    }
1074
1075    /// Initializes a new [`BundleInfo`] for a dynamic [`Bundle`] with single component.
1076    ///
1077    /// # Panics
1078    ///
1079    /// Panics if the provided [`ComponentId`] does not exist in the provided [`Components`].
1080    pub(crate) fn init_component_info(
1081        &mut self,
1082        components: &Components,
1083        component_id: ComponentId,
1084    ) -> BundleId {
1085        let bundle_infos = &mut self.bundle_infos;
1086        let bundle_id = self
1087            .dynamic_component_bundle_ids
1088            .entry(component_id)
1089            .or_insert_with(|| {
1090                let (id, storage_type) =
1091                    initialize_dynamic_bundle(bundle_infos, components, vec![component_id]);
1092                self.dynamic_component_storages.insert(id, storage_type[0]);
1093                id
1094            });
1095        *bundle_id
1096    }
1097}
1098
1099/// Asserts that all components are part of [`Components`]
1100/// and initializes a [`BundleInfo`].
1101fn initialize_dynamic_bundle(
1102    bundle_infos: &mut Vec<BundleInfo>,
1103    components: &Components,
1104    component_ids: Vec<ComponentId>,
1105) -> (BundleId, Vec<StorageType>) {
1106    // Assert component existence
1107    let storage_types = component_ids.iter().map(|&id| {
1108        components.get_info(id).unwrap_or_else(|| {
1109            panic!(
1110                "init_dynamic_info called with component id {id:?} which doesn't exist in this world"
1111            )
1112        }).storage_type()
1113    }).collect();
1114
1115    let id = BundleId(bundle_infos.len());
1116    let bundle_info =
1117        // SAFETY: `component_ids` are valid as they were just checked
1118        unsafe { BundleInfo::new("<dynamic bundle>", components, component_ids, id) };
1119    bundle_infos.push(bundle_info);
1120
1121    (id, storage_types)
1122}
1123
1124#[cfg(test)]
1125mod tests {
1126    use crate as bevy_ecs;
1127    use crate::prelude::*;
1128
1129    #[derive(Component)]
1130    struct A;
1131
1132    #[derive(Component)]
1133    struct B;
1134
1135    #[derive(Component)]
1136    struct C;
1137
1138    #[derive(Component)]
1139    struct D;
1140
1141    #[derive(Resource, Default)]
1142    struct R(usize);
1143
1144    impl R {
1145        #[track_caller]
1146        fn assert_order(&mut self, count: usize) {
1147            assert_eq!(count, self.0);
1148            self.0 += 1;
1149        }
1150    }
1151
1152    #[test]
1153    fn component_hook_order_spawn_despawn() {
1154        let mut world = World::new();
1155        world.init_resource::<R>();
1156        world
1157            .register_component_hooks::<A>()
1158            .on_add(|mut world, _, _| {
1159                world.resource_mut::<R>().assert_order(0);
1160            })
1161            .on_insert(|mut world, _, _| world.resource_mut::<R>().assert_order(1))
1162            .on_remove(|mut world, _, _| world.resource_mut::<R>().assert_order(2));
1163
1164        let entity = world.spawn(A).id();
1165        world.despawn(entity);
1166        assert_eq!(3, world.resource::<R>().0);
1167    }
1168
1169    #[test]
1170    fn component_hook_order_insert_remove() {
1171        let mut world = World::new();
1172        world.init_resource::<R>();
1173        world
1174            .register_component_hooks::<A>()
1175            .on_add(|mut world, _, _| {
1176                world.resource_mut::<R>().assert_order(0);
1177            })
1178            .on_insert(|mut world, _, _| {
1179                world.resource_mut::<R>().assert_order(1);
1180            })
1181            .on_remove(|mut world, _, _| {
1182                world.resource_mut::<R>().assert_order(2);
1183            });
1184
1185        let mut entity = world.spawn_empty();
1186        entity.insert(A);
1187        entity.remove::<A>();
1188        entity.flush();
1189        assert_eq!(3, world.resource::<R>().0);
1190    }
1191
1192    #[test]
1193    fn component_hook_order_recursive() {
1194        let mut world = World::new();
1195        world.init_resource::<R>();
1196        world
1197            .register_component_hooks::<A>()
1198            .on_add(|mut world, entity, _| {
1199                world.resource_mut::<R>().assert_order(0);
1200                world.commands().entity(entity).insert(B);
1201            })
1202            .on_remove(|mut world, entity, _| {
1203                world.resource_mut::<R>().assert_order(2);
1204                world.commands().entity(entity).remove::<B>();
1205            });
1206
1207        world
1208            .register_component_hooks::<B>()
1209            .on_add(|mut world, entity, _| {
1210                world.resource_mut::<R>().assert_order(1);
1211                world.commands().entity(entity).remove::<A>();
1212            })
1213            .on_remove(|mut world, _, _| {
1214                world.resource_mut::<R>().assert_order(3);
1215            });
1216
1217        let entity = world.spawn(A).flush();
1218        let entity = world.get_entity(entity).unwrap();
1219        assert!(!entity.contains::<A>());
1220        assert!(!entity.contains::<B>());
1221        assert_eq!(4, world.resource::<R>().0);
1222    }
1223
1224    #[test]
1225    fn component_hook_order_recursive_multiple() {
1226        let mut world = World::new();
1227        world.init_resource::<R>();
1228        world
1229            .register_component_hooks::<A>()
1230            .on_add(|mut world, entity, _| {
1231                world.resource_mut::<R>().assert_order(0);
1232                world.commands().entity(entity).insert(B).insert(C);
1233            });
1234
1235        world
1236            .register_component_hooks::<B>()
1237            .on_add(|mut world, entity, _| {
1238                world.resource_mut::<R>().assert_order(1);
1239                world.commands().entity(entity).insert(D);
1240            });
1241
1242        world
1243            .register_component_hooks::<C>()
1244            .on_add(|mut world, _, _| {
1245                world.resource_mut::<R>().assert_order(3);
1246            });
1247
1248        world
1249            .register_component_hooks::<D>()
1250            .on_add(|mut world, _, _| {
1251                world.resource_mut::<R>().assert_order(2);
1252            });
1253
1254        world.spawn(A).flush();
1255        assert_eq!(4, world.resource::<R>().0);
1256    }
1257}