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