Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/bundle/mod.rs
6849 views
1
//! Types for handling [`Bundle`]s.
2
//!
3
//! This module contains the [`Bundle`] trait and some other helper types.
4
5
mod impls;
6
mod info;
7
mod insert;
8
mod remove;
9
mod spawner;
10
#[cfg(test)]
11
mod tests;
12
13
pub(crate) use insert::BundleInserter;
14
pub(crate) use remove::BundleRemover;
15
pub(crate) use spawner::BundleSpawner;
16
17
use bevy_ptr::MovingPtr;
18
use core::mem::MaybeUninit;
19
pub 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
/// ```
72
pub use bevy_ecs_macros::Bundle;
73
74
use crate::{
75
component::{ComponentId, Components, ComponentsRegistrator, StorageType},
76
world::EntityWorldMut,
77
};
78
use 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 &mdash; 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
)]
200
pub 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`].
223
pub 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.
239
pub 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.
292
pub trait NoBundleEffect {}
293
294