1
1
//! Types that enable reflection support.
2
2
3
+ use crate :: bundle:: Bundle ;
3
4
use crate :: {
4
5
change_detection:: Mut ,
5
6
component:: Component ,
@@ -8,9 +9,10 @@ use crate::{
8
9
world:: { FromWorld , World } ,
9
10
} ;
10
11
use bevy_reflect:: {
11
- impl_from_reflect_value, impl_reflect_value, FromType , Reflect , ReflectDeserialize ,
12
- ReflectSerialize ,
12
+ impl_from_reflect_value, impl_reflect_value, FromType , Reflect , ReflectDeserialize , ReflectRef ,
13
+ ReflectSerialize , TypeRegistry ,
13
14
} ;
15
+ use std:: any:: TypeId ;
14
16
15
17
/// A struct used to operate on reflected [`Component`] of a type.
16
18
///
@@ -225,6 +227,212 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
225
227
}
226
228
}
227
229
230
+ /// A struct used to operate on reflected [`Bundle`] of a type.
231
+ ///
232
+ /// A [`ReflectBundle`] for type `T` can be obtained via
233
+ /// [`bevy_reflect::TypeRegistration::data`].
234
+ #[ derive( Clone ) ]
235
+ pub struct ReflectBundle ( ReflectBundleFns ) ;
236
+
237
+ /// The raw function pointers needed to make up a [`ReflectBundle`].
238
+ ///
239
+ /// This is used when creating custom implementations of [`ReflectBundle`] with
240
+ /// [`ReflectBundle::new()`].
241
+ ///
242
+ /// > **Note:**
243
+ /// > Creating custom implementations of [`ReflectBundle`] is an advanced feature that most users
244
+ /// > will not need.
245
+ /// > Usually a [`ReflectBundle`] is created for a type by deriving [`Reflect`]
246
+ /// > and adding the `#[reflect(Bundle)]` attribute.
247
+ /// > After adding the bundle to the [`TypeRegistry`][bevy_reflect::TypeRegistry],
248
+ /// > its [`ReflectBundle`] can then be retrieved when needed.
249
+ ///
250
+ /// Creating a custom [`ReflectBundle`] may be useful if you need to create new bundle types
251
+ /// at runtime, for example, for scripting implementations.
252
+ ///
253
+ /// By creating a custom [`ReflectBundle`] and inserting it into a type's
254
+ /// [`TypeRegistration`][bevy_reflect::TypeRegistration],
255
+ /// you can modify the way that reflected bundles of that type will be inserted into the Bevy
256
+ /// world.
257
+ #[ derive( Clone ) ]
258
+ pub struct ReflectBundleFns {
259
+ /// Function pointer implementing [`ReflectBundle::insert()`].
260
+ pub insert : fn ( & mut World , Entity , & dyn Reflect ) ,
261
+ /// Function pointer implementing [`ReflectBundle::apply()`].
262
+ pub apply : fn ( & mut World , Entity , & dyn Reflect , & TypeRegistry ) ,
263
+ /// Function pointer implementing [`ReflectBundle::apply_or_insert()`].
264
+ pub apply_or_insert : fn ( & mut World , Entity , & dyn Reflect , & TypeRegistry ) ,
265
+ /// Function pointer implementing [`ReflectBundle::remove()`].
266
+ pub remove : fn ( & mut World , Entity ) ,
267
+ }
268
+
269
+ impl ReflectBundleFns {
270
+ /// Get the default set of [`ReflectComponentFns`] for a specific component type using its
271
+ /// [`FromType`] implementation.
272
+ ///
273
+ /// This is useful if you want to start with the default implementation before overriding some
274
+ /// of the functions to create a custom implementation.
275
+ pub fn new < T : Bundle + Reflect + FromWorld > ( ) -> Self {
276
+ <ReflectBundle as FromType < T > >:: from_type ( ) . 0
277
+ }
278
+ }
279
+
280
+ impl ReflectBundle {
281
+ /// Insert a reflected [`Bundle`] into the entity like [`insert()`](crate::world::EntityMut::insert).
282
+ ///
283
+ /// # Panics
284
+ ///
285
+ /// Panics if there is no such entity.
286
+ pub fn insert ( & self , world : & mut World , entity : Entity , bundle : & dyn Reflect ) {
287
+ ( self . 0 . insert ) ( world, entity, bundle) ;
288
+ }
289
+
290
+ /// Uses reflection to set the value of this [`Bundle`] type in the entity to the given value.
291
+ ///
292
+ /// # Panics
293
+ ///
294
+ /// Panics if there is no [`Bundle`] of the given type or the `entity` does not exist.
295
+ pub fn apply (
296
+ & self ,
297
+ world : & mut World ,
298
+ entity : Entity ,
299
+ bundle : & dyn Reflect ,
300
+ registry : & TypeRegistry ,
301
+ ) {
302
+ ( self . 0 . apply ) ( world, entity, bundle, registry) ;
303
+ }
304
+
305
+ /// Uses reflection to set the value of this [`Bundle`] type in the entity to the given value or insert a new one if it does not exist.
306
+ ///
307
+ /// # Panics
308
+ ///
309
+ /// Panics if the `entity` does not exist.
310
+ pub fn apply_or_insert (
311
+ & self ,
312
+ world : & mut World ,
313
+ entity : Entity ,
314
+ bundle : & dyn Reflect ,
315
+ registry : & TypeRegistry ,
316
+ ) {
317
+ ( self . 0 . apply_or_insert ) ( world, entity, bundle, registry) ;
318
+ }
319
+
320
+ /// Removes this [`Bundle`] type from the entity. Does nothing if it doesn't exist.
321
+ ///
322
+ /// # Panics
323
+ ///
324
+ /// Panics if there is no [`Bundle`] of the given type or the `entity` does not exist.
325
+ pub fn remove ( & self , world : & mut World , entity : Entity ) {
326
+ ( self . 0 . remove ) ( world, entity) ;
327
+ }
328
+
329
+ /// Create a custom implementation of [`ReflectBundle`].
330
+ ///
331
+ /// This is an advanced feature,
332
+ /// useful for scripting implementations,
333
+ /// that should not be used by most users
334
+ /// unless you know what you are doing.
335
+ ///
336
+ /// Usually you should derive [`Reflect`] and add the `#[reflect(Bundle)]` component
337
+ /// to generate a [`ReflectBundle`] implementation automatically.
338
+ ///
339
+ /// See [`ReflectComponentFns`] for more information.
340
+ pub fn new ( fns : ReflectBundleFns ) -> Self {
341
+ Self ( fns)
342
+ }
343
+ }
344
+
345
+ impl < C : Bundle + Reflect + FromWorld > FromType < C > for ReflectBundle {
346
+ fn from_type ( ) -> Self {
347
+ ReflectBundle ( ReflectBundleFns {
348
+ insert : |world, entity, reflected_bundle| {
349
+ let mut bundle = C :: from_world ( world) ;
350
+ bundle. apply ( reflected_bundle) ;
351
+ world. entity_mut ( entity) . insert ( bundle) ;
352
+ } ,
353
+ apply : |world, entity, reflected_bundle, registry| {
354
+ let mut bundle = C :: from_world ( world) ;
355
+ bundle. apply ( reflected_bundle) ;
356
+
357
+ if let ReflectRef :: Struct ( bundle) = bundle. reflect_ref ( ) {
358
+ for field in bundle. iter_fields ( ) {
359
+ if let Some ( reflect_component) =
360
+ registry. get_type_data :: < ReflectComponent > ( field. type_id ( ) )
361
+ {
362
+ reflect_component. apply ( world, entity, field) ;
363
+ } else if let Some ( reflect_bundle) =
364
+ registry. get_type_data :: < ReflectBundle > ( field. type_id ( ) )
365
+ {
366
+ reflect_bundle. apply ( world, entity, field, registry) ;
367
+ } else {
368
+ if let Some ( id) = world. bundles ( ) . get_id ( TypeId :: of :: < C > ( ) ) {
369
+ let info = world. bundles ( ) . get ( id) . unwrap ( ) ;
370
+ if info. components ( ) . is_empty ( ) {
371
+ panic ! (
372
+ "no `ReflectComponent` registration found for `{}`" ,
373
+ field. type_name( )
374
+ ) ;
375
+ }
376
+ } ;
377
+
378
+ panic ! (
379
+ "no `ReflectBundle` registration found for `{}`" ,
380
+ field. type_name( )
381
+ )
382
+ }
383
+ }
384
+ } else {
385
+ panic ! (
386
+ "expected bundle `{}` to be named struct" ,
387
+ std:: any:: type_name:: <C >( )
388
+ ) ;
389
+ }
390
+ } ,
391
+ apply_or_insert : |world, entity, reflected_bundle, registry| {
392
+ let mut bundle = C :: from_world ( world) ;
393
+ bundle. apply ( reflected_bundle) ;
394
+
395
+ if let ReflectRef :: Struct ( bundle) = bundle. reflect_ref ( ) {
396
+ for field in bundle. iter_fields ( ) {
397
+ if let Some ( reflect_component) =
398
+ registry. get_type_data :: < ReflectComponent > ( field. type_id ( ) )
399
+ {
400
+ reflect_component. apply_or_insert ( world, entity, field) ;
401
+ } else if let Some ( reflect_bundle) =
402
+ registry. get_type_data :: < ReflectBundle > ( field. type_id ( ) )
403
+ {
404
+ reflect_bundle. apply_or_insert ( world, entity, field, registry) ;
405
+ } else {
406
+ if let Some ( id) = world. bundles ( ) . get_id ( TypeId :: of :: < C > ( ) ) {
407
+ let info = world. bundles ( ) . get ( id) . unwrap ( ) ;
408
+ if info. components ( ) . is_empty ( ) {
409
+ panic ! (
410
+ "no `ReflectComponent` registration found for `{}`" ,
411
+ field. type_name( )
412
+ ) ;
413
+ }
414
+ } ;
415
+
416
+ panic ! (
417
+ "no `ReflectBundle` registration found for `{}`" ,
418
+ field. type_name( )
419
+ )
420
+ }
421
+ }
422
+ } else {
423
+ panic ! (
424
+ "expected bundle `{}` to be named struct" ,
425
+ std:: any:: type_name:: <C >( )
426
+ ) ;
427
+ }
428
+ } ,
429
+ remove : |world, entity| {
430
+ world. entity_mut ( entity) . remove :: < C > ( ) ;
431
+ } ,
432
+ } )
433
+ }
434
+ }
435
+
228
436
/// A struct used to operate on reflected [`Resource`] of a type.
229
437
///
230
438
/// A [`ReflectResource`] for type `T` can be obtained via
0 commit comments