Skip to main content

bevy_ecs/bundle/
mod.rs

1//! Types for handling [`Bundle`]s.
2//!
3//! This module contains the [`Bundle`] trait and some other helper types.
4
5mod impls;
6mod info;
7mod insert;
8mod remove;
9mod spawner;
10#[cfg(test)]
11mod tests;
12mod writer;
13
14pub(crate) use insert::BundleInserter;
15pub(crate) use remove::BundleRemover;
16pub(crate) use spawner::BundleSpawner;
17
18use bevy_ptr::MovingPtr;
19use core::mem::MaybeUninit;
20pub use info::*;
21pub use writer::*;
22
23/// Derive the [`Bundle`] trait
24///
25/// You can apply this derive macro to structs that are
26/// composed of [`Component`](crate::component::Component)s or
27/// other [`Bundle`]s.
28///
29/// ## Attributes
30///
31/// Sometimes parts of the Bundle should not be inserted.
32/// Those can be marked with `#[bundle(ignore)]`, and they will be skipped.
33/// In that case, the field needs to implement [`Default`] unless you also ignore
34/// the [`BundleFromComponents`] implementation.
35///
36/// ```rust
37/// # use bevy_ecs::prelude::{Component, Bundle};
38/// # #[derive(Component)]
39/// # struct Hitpoint;
40/// #
41/// #[derive(Bundle)]
42/// struct HitpointMarker {
43///     hitpoints: Hitpoint,
44///
45///     #[bundle(ignore)]
46///     creator: Option<String>
47/// }
48/// ```
49///
50/// Some fields may be bundles that do not implement
51/// [`BundleFromComponents`]. This happens for bundles that cannot be extracted.
52/// For example with [`SpawnRelatedBundle`](bevy_ecs::spawn::SpawnRelatedBundle), see below for an
53/// example usage.
54/// In those cases you can either ignore it as above,
55/// or you can opt out the whole Struct by marking it as ignored with
56/// `#[bundle(ignore_from_components)]`.
57///
58/// ```rust
59/// # use bevy_ecs::prelude::{Component, Bundle, ChildOf, Spawn};
60/// # #[derive(Component)]
61/// # struct Hitpoint;
62/// # #[derive(Component)]
63/// # struct Marker;
64/// #
65/// use bevy_ecs::spawn::SpawnRelatedBundle;
66///
67/// #[derive(Bundle)]
68/// #[bundle(ignore_from_components)]
69/// struct HitpointMarker {
70///     hitpoints: Hitpoint,
71///     related_spawner: SpawnRelatedBundle<ChildOf, Spawn<Marker>>,
72/// }
73/// ```
74pub use bevy_ecs_macros::Bundle;
75
76use crate::{
77    component::{ComponentId, Components, ComponentsRegistrator, StorageType},
78    world::EntityWorldMut,
79};
80use bevy_ptr::OwningPtr;
81
82/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
83///
84/// Implementers of the `Bundle` trait are called 'bundles'.
85///
86/// Each bundle represents a static set of [`Component`] types.
87/// Currently, bundles can only contain one of each [`Component`], and will
88/// panic once initialized if this is not met.
89///
90/// ## Insertion
91///
92/// The primary use for bundles is to add a useful collection of components to an entity.
93///
94/// Adding a value of bundle to an entity will add the components from the set it
95/// represents to the entity.
96/// The values of these components are taken from the bundle.
97/// If an entity already had one of these components, the entity's original component value
98/// will be overwritten.
99///
100/// Importantly, bundles are only their constituent set of components.
101/// You **should not** use bundles as a unit of behavior.
102/// The behavior of your app can only be considered in terms of components, as systems,
103/// which drive the behavior of a `bevy` application, operate on combinations of
104/// components.
105///
106/// This rule is also important because multiple bundles may contain the same component type,
107/// calculated in different ways &mdash; adding both of these bundles to one entity
108/// would create incoherent behavior.
109/// This would be unexpected if bundles were treated as an abstraction boundary, as
110/// the abstraction would be unmaintainable for these cases.
111///
112/// For this reason, there is intentionally no [`Query`] to match whether an entity
113/// contains the components of a bundle.
114/// Queries should instead only select the components they logically operate on.
115///
116/// ## Removal
117///
118/// Bundles are also used when removing components from an entity.
119///
120/// Removing a bundle from an entity will remove any of its components attached
121/// to the entity from the entity.
122/// That is, if the entity does not have all the components of the bundle, those
123/// which are present will be removed.
124///
125/// # Implementers
126///
127/// Every type which implements [`Component`] also implements `Bundle`, since
128/// [`Component`] types can be added to or removed from an entity.
129///
130/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
131/// These bundles contain the items of the 'inner' bundles.
132/// This is a convenient shorthand which is primarily used when spawning entities.
133///
134/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
135/// can also be considered as the empty tuple).
136/// This can be useful for spawning large numbers of empty entities using
137/// [`World::spawn_batch`](crate::world::World::spawn_batch).
138///
139/// Tuple bundles can be nested, which can be used to create an anonymous bundle with more than
140/// 15 items.
141/// However, in most cases where this is required, the derive macro [`derive@Bundle`] should be
142/// used instead.
143/// The derived `Bundle` implementation contains the items of its fields, which all must
144/// implement `Bundle`.
145/// As explained above, this includes any [`Component`] type, and other derived bundles.
146///
147/// If you want to add `PhantomData` to your `Bundle` you have to mark it with `#[bundle(ignore)]`.
148/// ```
149/// # use std::marker::PhantomData;
150/// use bevy_ecs::{component::Component, bundle::Bundle};
151///
152/// #[derive(Component)]
153/// struct XPosition(i32);
154/// #[derive(Component)]
155/// struct YPosition(i32);
156///
157/// #[derive(Bundle)]
158/// struct PositionBundle {
159///     // A bundle can contain components
160///     x: XPosition,
161///     y: YPosition,
162/// }
163///
164/// // You have to implement `Default` for ignored field types in bundle structs.
165/// #[derive(Default)]
166/// struct Other(f32);
167///
168/// #[derive(Bundle)]
169/// struct NamedPointBundle<T: Send + Sync + 'static> {
170///     // Or other bundles
171///     a: PositionBundle,
172///     // In addition to more components
173///     z: PointName,
174///
175///     // when you need to use `PhantomData` you have to mark it as ignored
176///     #[bundle(ignore)]
177///     _phantom_data: PhantomData<T>
178/// }
179///
180/// #[derive(Component)]
181/// struct PointName(String);
182/// ```
183///
184/// # Safety
185///
186/// Manual implementations of this trait are unsupported.
187/// That is, there is no safe way to implement this trait, and you must not do so.
188/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
189///
190/// [`Component`]: crate::component::Component
191/// [`Query`]: crate::system::Query
192// Some safety points:
193// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
194// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
195// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
196//   [`Bundle::component_ids`].
197#[diagnostic::on_unimplemented(
198    message = "`{Self}` is not a `Bundle`",
199    label = "invalid `Bundle`",
200    note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
201)]
202pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
203    /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s
204    /// This will register the component if it doesn't exist.
205    #[doc(hidden)]
206    fn component_ids(
207        components: &mut ComponentsRegistrator,
208    ) -> impl Iterator<Item = ComponentId> + use<Self>;
209
210    /// Returns an iterator over this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered.
211    fn get_component_ids(components: &Components) -> impl Iterator<Item = Option<ComponentId>>;
212}
213
214/// Creates a [`Bundle`] by taking it from internal storage.
215///
216/// # Safety
217///
218/// Manual implementations of this trait are unsupported.
219/// That is, there is no safe way to implement this trait, and you must not do so.
220/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
221///
222/// [`Query`]: crate::system::Query
223// Some safety points:
224// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
225// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
226// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
227//   [`Bundle::component_ids`].
228pub unsafe trait BundleFromComponents {
229    /// Calls `func`, which should return data for each component in the bundle, in the order of
230    /// this bundle's [`Component`]s
231    ///
232    /// # Safety
233    /// Caller must return data for each component in the bundle, in the order of this bundle's
234    /// [`Component`]s
235    #[doc(hidden)]
236    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
237    where
238        // Ensure that the `OwningPtr` is used correctly
239        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
240        Self: Sized;
241}
242
243/// The parts from [`Bundle`] that don't require statically knowing the components of the bundle.
244pub trait DynamicBundle: Sized {
245    /// An operation on the entity that happens _after_ inserting this bundle.
246    type Effect;
247
248    /// Moves the components out of the bundle.
249    ///
250    /// # Safety
251    /// For callers:
252    /// - Must be called exactly once before `apply_effect`
253    /// - The `StorageType` argument passed into `func` must be correct for the component being fetched.
254    /// - `apply_effect` must be called exactly once after this has been called if `Effect: !NoBundleEffect`
255    ///
256    /// For implementors:
257    ///  - Implementors of this function must convert `ptr` into pointers to individual components stored within
258    ///    `Self` and call `func` on each of them in exactly the same order as [`Bundle::get_component_ids`] and
259    ///    [`BundleFromComponents::from_components`].
260    ///  - If any part of `ptr` is to be accessed in `apply_effect`, it must *not* be dropped at any point in this
261    ///    function. Calling [`bevy_ptr::deconstruct_moving_ptr`] in this function automatically ensures this.
262    ///
263    /// [`Component`]: crate::component::Component
264    // This function explicitly uses `MovingPtr` to avoid potentially large stack copies of the bundle
265    // when inserting into ECS storage. See https://github.com/bevyengine/bevy/issues/20571 for more
266    // information.
267    unsafe fn get_components(
268        ptr: MovingPtr<'_, Self>,
269        func: &mut impl FnMut(StorageType, OwningPtr<'_>),
270    );
271
272    /// Applies the after-effects of spawning this bundle.
273    ///
274    /// This is applied after all residual changes to the [`World`], including flushing the internal command
275    /// queue.
276    ///
277    /// # Safety
278    /// For callers:
279    /// - Must be called exactly once after `get_components` has been called.
280    /// - `ptr` must point to the instance of `Self` that `get_components` was called on,
281    ///   all of fields that were moved out of in `get_components` will not be valid anymore.
282    ///
283    /// For implementors:
284    ///  - If any part of `ptr` is to be accessed in this function, it must *not* be dropped at any point in
285    ///    `get_components`. Calling [`bevy_ptr::deconstruct_moving_ptr`] in `get_components` automatically
286    ///    ensures this is the case.
287    ///  - Note that `entity` may already have been despawned by hooks or observers at this point,
288    ///    so check [`EntityWorldMut::is_spawned`] before trusting it.
289    ///
290    /// [`World`]: crate::world::World
291    // This function explicitly uses `MovingPtr` to avoid potentially large stack copies of the bundle
292    // when inserting into ECS storage. See https://github.com/bevyengine/bevy/issues/20571 for more
293    // information.
294    unsafe fn apply_effect(ptr: MovingPtr<'_, MaybeUninit<Self>>, entity: &mut EntityWorldMut);
295}
296
297/// A trait implemented for [`DynamicBundle::Effect`] implementations that do nothing. This is used as a type constraint for
298/// [`Bundle`] APIs that do not / cannot run [`DynamicBundle::Effect`], such as "batch spawn" APIs.
299pub trait NoBundleEffect {}