@@ -14,124 +14,208 @@ use bevy_ecs_macros::all_tuples;
14
14
use bevy_ptr:: OwningPtr ;
15
15
use std:: { any:: TypeId , collections:: HashMap } ;
16
16
17
- /// An ordered collection of [`Component`]s.
17
+ /// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity .
18
18
///
19
- /// Commonly used for spawning entities and adding and removing components in bulk. This
20
- /// trait is automatically implemented for tuples of components: `(ComponentA, ComponentB)`
21
- /// is a very convenient shorthand when working with one-off collections of components. Note
22
- /// that both the unit type `()` and `(ComponentA, )` are valid bundles. The unit bundle is
23
- /// particularly useful for spawning multiple empty entities by using
24
- /// [`Commands::spawn_batch`](crate::system::Commands::spawn_batch).
19
+ /// Implementors of the `Bundle` trait are called 'bundles'.
25
20
///
26
- /// # Examples
21
+ /// Each bundle represents a static set of [`Component`] types.
22
+ /// Currently, bundles can only contain one of each [`Component`], and will
23
+ /// panic once initialised if this is not met.
27
24
///
28
- /// Typically, you will simply use `#[derive(Bundle)]` when creating your own `Bundle`. Each
29
- /// struct field is a component:
25
+ /// ## Insertion
30
26
///
31
- /// ```
32
- /// # use bevy_ecs::prelude::*;
33
- /// # #[derive(Component)]
34
- /// # struct ComponentA;
35
- /// # #[derive(Component)]
36
- /// # struct ComponentB;
37
- /// # #[derive(Component)]
38
- /// # struct ComponentC;
39
- /// #
40
- /// #[derive(Bundle)]
41
- /// struct MyBundle {
42
- /// a: ComponentA,
43
- /// b: ComponentB,
44
- /// c: ComponentC,
45
- /// }
46
- /// ```
27
+ /// The primary use for bundles is to add a useful collection of components to an entity.
28
+ ///
29
+ /// Adding a value of bundle to an entity will add the components from the set it
30
+ /// represents to the entity.
31
+ /// The values of these components are taken from the bundle.
32
+ /// If an entity already had one of these components, the entity's original component value
33
+ /// will be overwritten.
34
+ ///
35
+ /// Importantly, bundles are only their constituent set of components.
36
+ /// You **should not** use bundles as a unit of behaviour.
37
+ /// The behaviour of your app can only be considered in terms of components, as systems,
38
+ /// which drive the behaviour of a `bevy` application, operate on combinations of
39
+ /// components.
40
+ ///
41
+ /// This rule is also important because multiple bundles may contain the same component type,
42
+ /// calculated in different ways — adding both of these bundles to one entity
43
+ /// would create incoherent behaviour.
44
+ /// This would be unexpected if bundles were treated as an abstraction boundary, as
45
+ /// the abstraction would be unmaintainable for these cases.
46
+ /// For example, both `Camera3dBundle` and `Camera2dBundle` contain the `CameraRenderGraph`
47
+ /// component, but specifying different render graphs to use.
48
+ /// If the bundles were both added to the same entity, only one of these two bundles would work.
49
+ ///
50
+ /// For this reason, There is intentionally no [`Query`] to match whether an entity
51
+ /// contains the components of a bundle.
52
+ /// Queries should instead only select the components they logically operate on.
53
+ ///
54
+ /// ## Removal
55
+ ///
56
+ /// Bundles are also used when removing components from an entity.
57
+ ///
58
+ /// Removing a bundle from an entity will remove any of its components attached
59
+ /// to the entity from the entity.
60
+ /// That is, if the entity does not have all the components of the bundle, those
61
+ /// which are present will be removed.
62
+ ///
63
+ /// # Implementors
64
+ ///
65
+ /// Every type which implements [`Component`] also implements `Bundle`, since
66
+ /// [`Component`] types can be added to or removed from an entity.
67
+ ///
68
+ /// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
69
+ /// These bundles contain the items of the 'inner' bundles.
70
+ /// This is a convenient shorthand which is primarily used when spawning entities.
71
+ /// For example, spawning an entity using the bundle `(SpriteBundle {...}, PlayerMarker)`
72
+ /// will spawn an entity with components required for a 2d sprite, and the `PlayerMarker` component.
73
+ ///
74
+ /// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
75
+ /// can also be considered as the empty tuple).
76
+ /// This can be useful for spawning large numbers of empty entities using
77
+ /// [`World::spawn_batch`](crate::world::World::spawn_batch).
78
+ ///
79
+ /// Tuple bundles can be nested, which can be used to create an anonymous bundle with more than
80
+ /// 15 items.
81
+ /// However, in most cases where this is required, the derive macro [`derive@Bundle`] should be
82
+ /// used instead.
83
+ /// The derived `Bundle` implementation contains the items of its fields, which all must
84
+ /// implement `Bundle`.
85
+ /// As explained above, this includes any [`Component`] type, and other derived bundles:
47
86
///
48
- /// You can nest bundles using the `#[bundle]` attribute:
49
87
/// ```
50
88
/// # use bevy_ecs::{component::Component, bundle::Bundle};
51
89
///
52
90
/// #[derive(Component)]
53
- /// struct X (i32);
91
+ /// struct XPosition (i32);
54
92
/// #[derive(Component)]
55
- /// struct Y(u64);
56
- /// #[derive(Component)]
57
- /// struct Z(String);
93
+ /// struct YPosition(i32);
58
94
///
59
95
/// #[derive(Bundle)]
60
- /// struct A {
61
- /// x: X,
62
- /// y: Y,
96
+ /// struct PositionBundle {
97
+ /// // A bundle can contain components
98
+ /// x: XPosition,
99
+ /// y: YPosition,
63
100
/// }
64
101
///
65
102
/// #[derive(Bundle)]
66
- /// struct B {
67
- /// #[bundle]
68
- /// a: A,
69
- /// z: Z,
103
+ /// struct NamedPointBundle {
104
+ /// // Or other bundles
105
+ /// a: PositionBundle,
106
+ /// // In addition to more components
107
+ /// z: PointName,
70
108
/// }
109
+ ///
110
+ /// #[derive(Component)]
111
+ /// struct PointName(String);
71
112
/// ```
72
113
///
73
114
/// # Safety
74
115
///
75
- /// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
76
- /// bundle, in the _exact_ order that [`Bundle::get_components`] is called.
77
- /// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
78
- /// [`Bundle::component_ids`].
116
+ /// Manual implementations of this trait are unsupported.
117
+ /// That is, there is no safe way to implement this trait, and you must not do so.
118
+ /// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
119
+ ///
120
+ ///
121
+ /// [`Query`]: crate::system::Query
122
+ // Some safety points:
123
+ // - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
124
+ // bundle, in the _exact_ order that [`Bundle::get_components`] is called.
125
+ // - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
126
+ // [`Bundle::component_ids`].
79
127
pub unsafe trait Bundle : Send + Sync + ' static {
80
128
/// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s
81
- fn component_ids ( components : & mut Components , storages : & mut Storages ) -> Vec < ComponentId > ;
129
+ #[ doc( hidden) ]
130
+ fn component_ids (
131
+ components : & mut Components ,
132
+ storages : & mut Storages ,
133
+ ids : & mut impl FnMut ( ComponentId ) ,
134
+ ) ;
82
135
83
136
/// Calls `func`, which should return data for each component in the bundle, in the order of
84
137
/// this bundle's [`Component`]s
85
138
///
86
139
/// # Safety
87
140
/// Caller must return data for each component in the bundle, in the order of this bundle's
88
141
/// [`Component`]s
89
- unsafe fn from_components < T , F > ( ctx : & mut T , func : F ) -> Self
142
+ #[ doc( hidden) ]
143
+ unsafe fn from_components < T , F > ( ctx : & mut T , func : & mut F ) -> Self
90
144
where
91
- F : FnMut ( & mut T ) -> OwningPtr < ' _ > ,
145
+ // Ensure that the `OwningPtr` is used correctly
146
+ F : for < ' a > FnMut ( & ' a mut T ) -> OwningPtr < ' a > ,
92
147
Self : Sized ;
93
148
94
- /// Calls `func` on each value, in the order of this bundle's [`Component`]s. This will
95
- /// [`std::mem::forget`] the bundle fields, so callers are responsible for dropping the fields
96
- /// if that is desirable.
97
- fn get_components ( self , func : impl FnMut ( OwningPtr < ' _ > ) ) ;
149
+ /// Calls `func` on each value, in the order of this bundle's [`Component`]s. This passes
150
+ /// ownership of the component values to `func`.
151
+ #[ doc( hidden) ]
152
+ fn get_components ( self , func : & mut impl FnMut ( OwningPtr < ' _ > ) ) ;
153
+ }
154
+
155
+ // SAFETY:
156
+ // - `Bundle::component_ids` calls `ids` for C's component id (and nothing else)
157
+ // - `Bundle::get_components` is called exactly once for C.
158
+ // - `Bundle::from_components` calls `func` exactly once for C, which is the exact value returned by `Bundle::component_ids`.
159
+ unsafe impl < C : Component > Bundle for C {
160
+ fn component_ids (
161
+ components : & mut Components ,
162
+ storages : & mut Storages ,
163
+ ids : & mut impl FnMut ( ComponentId ) ,
164
+ ) {
165
+ ids ( components. init_component :: < C > ( storages) ) ;
166
+ }
167
+
168
+ unsafe fn from_components < T , F > ( ctx : & mut T , func : & mut F ) -> Self
169
+ where
170
+ // Ensure that the `OwningPtr` is used correctly
171
+ F : for < ' a > FnMut ( & ' a mut T ) -> OwningPtr < ' a > ,
172
+ Self : Sized ,
173
+ {
174
+ // Safety: The id given in `component_ids` is for `Self`
175
+ func ( ctx) . read ( )
176
+ }
177
+
178
+ fn get_components ( self , func : & mut impl FnMut ( OwningPtr < ' _ > ) ) {
179
+ OwningPtr :: make ( self , func) ;
180
+ }
98
181
}
99
182
100
183
macro_rules! tuple_impl {
101
184
( $( $name: ident) ,* ) => {
102
185
// SAFETY:
103
- // - `Bundle::component_ids` returns the `ComponentId`s for each component type in the
186
+ // - `Bundle::component_ids` calls `ids` for each component type in the
104
187
// bundle, in the exact order that `Bundle::get_components` is called.
105
188
// - `Bundle::from_components` calls `func` exactly once for each `ComponentId` returned by `Bundle::component_ids`.
106
- unsafe impl <$( $name: Component ) ,* > Bundle for ( $( $name, ) * ) {
189
+ unsafe impl <$( $name: Bundle ) ,* > Bundle for ( $( $name, ) * ) {
107
190
#[ allow( unused_variables) ]
108
- fn component_ids( components: & mut Components , storages: & mut Storages ) -> Vec < ComponentId > {
109
- vec! [ $ ( components . init_component :: <$name> ( storages) ) , * ]
191
+ fn component_ids( components: & mut Components , storages: & mut Storages , ids : & mut impl FnMut ( ComponentId ) ) {
192
+ $ ( <$name as Bundle > :: component_ids ( components , storages, ids ) ; ) *
110
193
}
111
194
112
195
#[ allow( unused_variables, unused_mut) ]
113
196
#[ allow( clippy:: unused_unit) ]
114
- unsafe fn from_components<T , F >( ctx: & mut T , mut func: F ) -> Self
197
+ unsafe fn from_components<T , F >( ctx: & mut T , func: & mut F ) -> Self
115
198
where
116
199
F : FnMut ( & mut T ) -> OwningPtr <' _>
117
200
{
118
- #[ allow( non_snake_case) ]
119
- ( $( func( ctx) . read:: <$name>( ) , ) * )
201
+ // Rust guarantees that tuple calls are evaluated 'left to right'.
202
+ // https://doc.rust-lang.org/reference/expressions.html#evaluation-order-of-operands
203
+ ( $( <$name as Bundle >:: from_components( ctx, func) , ) * )
120
204
}
121
205
122
206
#[ allow( unused_variables, unused_mut) ]
123
- fn get_components( self , mut func: impl FnMut ( OwningPtr <' _>) ) {
207
+ fn get_components( self , func: & mut impl FnMut ( OwningPtr <' _>) ) {
124
208
#[ allow( non_snake_case) ]
125
209
let ( $( mut $name, ) * ) = self ;
126
210
$(
127
- OwningPtr :: make ( $name, & mut func) ;
211
+ $name. get_components ( & mut * func) ;
128
212
) *
129
213
}
130
214
}
131
215
}
132
216
}
133
217
134
- all_tuples ! ( tuple_impl, 0 , 15 , C ) ;
218
+ all_tuples ! ( tuple_impl, 0 , 15 , B ) ;
135
219
136
220
#[ derive( Debug , Clone , Copy , Eq , PartialEq , Hash ) ]
137
221
pub struct BundleId ( usize ) ;
@@ -279,7 +363,7 @@ impl BundleInfo {
279
363
// NOTE: get_components calls this closure on each component in "bundle order".
280
364
// bundle_info.component_ids are also in "bundle order"
281
365
let mut bundle_component = 0 ;
282
- bundle. get_components ( |component_ptr| {
366
+ bundle. get_components ( & mut |component_ptr| {
283
367
let component_id = * self . component_ids . get_unchecked ( bundle_component) ;
284
368
match self . storage_types [ bundle_component] {
285
369
StorageType :: Table => {
@@ -601,7 +685,8 @@ impl Bundles {
601
685
) -> & ' a BundleInfo {
602
686
let bundle_infos = & mut self . bundle_infos ;
603
687
let id = self . bundle_ids . entry ( TypeId :: of :: < T > ( ) ) . or_insert_with ( || {
604
- let component_ids = T :: component_ids ( components, storages) ;
688
+ let mut component_ids = Vec :: new ( ) ;
689
+ T :: component_ids ( components, storages, & mut |id| component_ids. push ( id) ) ;
605
690
let id = BundleId ( bundle_infos. len ( ) ) ;
606
691
// SAFETY: T::component_id ensures info was created
607
692
let bundle_info = unsafe {
0 commit comments