Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/reflect/entity_commands.rs
9408 views
1
use crate::{
2
prelude::Mut,
3
reflect::{AppTypeRegistry, ReflectBundle, ReflectComponent},
4
resource::Resource,
5
system::EntityCommands,
6
world::EntityWorldMut,
7
};
8
use alloc::{borrow::Cow, boxed::Box};
9
use bevy_reflect::{PartialReflect, Reflect, TypeRegistry};
10
11
/// An extension trait for [`EntityCommands`] for reflection related functions
12
pub trait ReflectCommandExt {
13
/// Adds the given boxed reflect component or bundle to the entity using the reflection data in
14
/// [`AppTypeRegistry`].
15
///
16
/// This will overwrite any previous component(s) of the same type.
17
///
18
/// # Panics
19
///
20
/// - If the entity doesn't exist.
21
/// - If [`AppTypeRegistry`] does not have the reflection data for the given
22
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
23
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
24
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
25
///
26
/// # Note
27
///
28
/// Prefer to use the typed [`EntityCommands::insert`] if possible. Adding a reflected component
29
/// is much slower.
30
///
31
/// # Example
32
///
33
/// ```
34
/// // Note that you need to register the component type in the AppTypeRegistry prior to using
35
/// // reflection. You can use the helpers on the App with `app.register_type::<ComponentA>()`
36
/// // or write to the TypeRegistry directly to register all your components
37
///
38
/// # use bevy_ecs::prelude::*;
39
/// # use bevy_ecs::reflect::{ReflectCommandExt, ReflectBundle};
40
/// # use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry};
41
/// // A resource that can hold any component that implements reflect as a boxed reflect component
42
/// #[derive(Resource)]
43
/// struct Prefab {
44
/// data: Box<dyn Reflect>,
45
/// }
46
/// #[derive(Component, Reflect, Default)]
47
/// #[reflect(Component)]
48
/// struct ComponentA(u32);
49
///
50
/// #[derive(Component, Reflect, Default)]
51
/// #[reflect(Component)]
52
/// struct ComponentB(String);
53
///
54
/// #[derive(Bundle, Reflect, Default)]
55
/// #[reflect(Bundle)]
56
/// struct BundleA {
57
/// a: ComponentA,
58
/// b: ComponentB,
59
/// }
60
///
61
/// fn insert_reflect_component(
62
/// mut commands: Commands,
63
/// mut prefab: ResMut<Prefab>
64
/// ) {
65
/// // Create a set of new boxed reflect components to use
66
/// let boxed_reflect_component_a: Box<dyn Reflect> = Box::new(ComponentA(916));
67
/// let boxed_reflect_component_b: Box<dyn Reflect> = Box::new(ComponentB("NineSixteen".to_string()));
68
/// let boxed_reflect_bundle_a: Box<dyn Reflect> = Box::new(BundleA {
69
/// a: ComponentA(24),
70
/// b: ComponentB("Twenty-Four".to_string()),
71
/// });
72
///
73
/// // You can overwrite the component in the resource with either ComponentA or ComponentB
74
/// prefab.data = boxed_reflect_component_a;
75
/// prefab.data = boxed_reflect_component_b;
76
///
77
/// // Or even with BundleA
78
/// prefab.data = boxed_reflect_bundle_a;
79
///
80
/// // No matter which component or bundle is in the resource and without knowing the exact type, you can
81
/// // use the insert_reflect entity command to insert that component/bundle into an entity.
82
/// commands
83
/// .spawn_empty()
84
/// .insert_reflect(prefab.data.reflect_clone().unwrap().into_partial_reflect());
85
/// }
86
/// ```
87
fn insert_reflect(&mut self, component: Box<dyn PartialReflect>) -> &mut Self;
88
89
/// Same as [`insert_reflect`](ReflectCommandExt::insert_reflect), but using the `T` resource as type registry instead of
90
/// `AppTypeRegistry`.
91
///
92
/// # Panics
93
///
94
/// - If the given [`Resource`] is not present in the [`World`](crate::world::World).
95
///
96
/// # Note
97
///
98
/// - The given [`Resource`] is removed from the [`World`](crate::world::World) before the command is applied.
99
fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
100
&mut self,
101
component: Box<dyn PartialReflect>,
102
) -> &mut Self;
103
104
/// Removes from the entity the component or bundle with the given type path registered in [`AppTypeRegistry`].
105
///
106
/// If the type is a bundle, it will remove any components in that bundle regardless if the entity
107
/// contains all the components.
108
///
109
/// Does nothing if the type is a component and the entity does not have a component of the same type,
110
/// if the type is a bundle and the entity does not contain any of the components in the bundle,
111
/// if [`AppTypeRegistry`] does not contain the reflection data for the given component,
112
/// or if the entity does not exist.
113
///
114
/// # Note
115
///
116
/// Prefer to use the typed [`EntityCommands::remove`] if possible. Removing a reflected component
117
/// is much slower.
118
///
119
/// # Example
120
///
121
/// ```
122
/// // Note that you need to register the component/bundle type in the AppTypeRegistry prior to using
123
/// // reflection. You can use the helpers on the App with `app.register_type::<ComponentA>()`
124
/// // or write to the TypeRegistry directly to register all your components and bundles
125
///
126
/// # use bevy_ecs::prelude::*;
127
/// # use bevy_ecs::reflect::{ReflectCommandExt, ReflectBundle};
128
/// # use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry};
129
///
130
/// // A resource that can hold any component or bundle that implements reflect as a boxed reflect
131
/// #[derive(Resource)]
132
/// struct Prefab{
133
/// entity: Entity,
134
/// data: Box<dyn Reflect>,
135
/// }
136
/// #[derive(Component, Reflect, Default)]
137
/// #[reflect(Component)]
138
/// struct ComponentA(u32);
139
/// #[derive(Component, Reflect, Default)]
140
/// #[reflect(Component)]
141
/// struct ComponentB(String);
142
/// #[derive(Bundle, Reflect, Default)]
143
/// #[reflect(Bundle)]
144
/// struct BundleA {
145
/// a: ComponentA,
146
/// b: ComponentB,
147
/// }
148
///
149
/// fn remove_reflect_component(
150
/// mut commands: Commands,
151
/// prefab: Res<Prefab>
152
/// ) {
153
/// // Prefab can hold any boxed reflect component or bundle. In this case either
154
/// // ComponentA, ComponentB, or BundleA. No matter which component or bundle is in the resource though,
155
/// // we can attempt to remove any component (or set of components in the case of a bundle)
156
/// // of that same type from an entity.
157
/// commands.entity(prefab.entity)
158
/// .remove_reflect(prefab.data.reflect_type_path().to_owned());
159
/// }
160
/// ```
161
fn remove_reflect(&mut self, component_type_path: impl Into<Cow<'static, str>>) -> &mut Self;
162
/// Same as [`remove_reflect`](ReflectCommandExt::remove_reflect), but using the `T` resource as type registry instead of
163
/// `AppTypeRegistry`.
164
fn remove_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
165
&mut self,
166
component_type_path: impl Into<Cow<'static, str>>,
167
) -> &mut Self;
168
}
169
170
impl ReflectCommandExt for EntityCommands<'_> {
171
fn insert_reflect(&mut self, component: Box<dyn PartialReflect>) -> &mut Self {
172
self.queue(move |mut entity: EntityWorldMut| {
173
entity.insert_reflect(component);
174
})
175
}
176
177
fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
178
&mut self,
179
component: Box<dyn PartialReflect>,
180
) -> &mut Self {
181
self.queue(move |mut entity: EntityWorldMut| {
182
entity.insert_reflect_with_registry::<T>(component);
183
})
184
}
185
186
fn remove_reflect(&mut self, component_type_path: impl Into<Cow<'static, str>>) -> &mut Self {
187
let component_type_path: Cow<'static, str> = component_type_path.into();
188
self.queue(move |mut entity: EntityWorldMut| {
189
entity.remove_reflect(component_type_path);
190
})
191
}
192
193
fn remove_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
194
&mut self,
195
component_type_path: impl Into<Cow<'static, str>>,
196
) -> &mut Self {
197
let component_type_path: Cow<'static, str> = component_type_path.into();
198
self.queue(move |mut entity: EntityWorldMut| {
199
entity.remove_reflect_with_registry::<T>(component_type_path);
200
})
201
}
202
}
203
204
impl<'w> EntityWorldMut<'w> {
205
/// Adds the given boxed reflect component or bundle to the entity using the reflection data in
206
/// [`AppTypeRegistry`].
207
///
208
/// This will overwrite any previous component(s) of the same type.
209
///
210
/// # Panics
211
///
212
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
213
/// - If [`AppTypeRegistry`] does not have the reflection data for the given
214
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
215
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
216
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
217
///
218
/// # Note
219
///
220
/// Prefer to use the typed [`EntityWorldMut::insert`] if possible. Adding a reflected component
221
/// is much slower.
222
pub fn insert_reflect(&mut self, component: Box<dyn PartialReflect>) -> &mut Self {
223
self.assert_not_despawned();
224
self.resource_scope(|entity, registry: Mut<AppTypeRegistry>| {
225
let type_registry = &registry.as_ref().read();
226
insert_reflect_with_registry_ref(entity, type_registry, component);
227
});
228
self
229
}
230
231
/// Same as [`insert_reflect`](EntityWorldMut::insert_reflect), but using
232
/// the `T` resource as type registry instead of [`AppTypeRegistry`].
233
///
234
/// This will overwrite any previous component(s) of the same type.
235
///
236
/// # Panics
237
///
238
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
239
/// - If the given [`Resource`] does not have the reflection data for the given
240
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
241
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
242
/// - If the given [`Resource`] is not present in the [`World`](crate::world::World).
243
pub fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
244
&mut self,
245
component: Box<dyn PartialReflect>,
246
) -> &mut Self {
247
self.assert_not_despawned();
248
self.resource_scope(|entity, registry: Mut<T>| {
249
let type_registry = registry.as_ref().as_ref();
250
insert_reflect_with_registry_ref(entity, type_registry, component);
251
});
252
self
253
}
254
255
/// Removes from the entity the component or bundle with the given type path registered in [`AppTypeRegistry`].
256
///
257
/// If the type is a bundle, it will remove any components in that bundle regardless if the entity
258
/// contains all the components.
259
///
260
/// Does nothing if the type is a component and the entity does not have a component of the same type,
261
/// if the type is a bundle and the entity does not contain any of the components in the bundle,
262
/// or if [`AppTypeRegistry`] does not contain the reflection data for the given component.
263
///
264
/// # Panics
265
///
266
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
267
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
268
///
269
/// # Note
270
///
271
/// Prefer to use the typed [`EntityWorldMut::remove`] if possible. Removing a reflected component
272
/// is much slower.
273
pub fn remove_reflect(&mut self, component_type_path: Cow<'static, str>) -> &mut Self {
274
self.assert_not_despawned();
275
self.resource_scope(|entity, registry: Mut<AppTypeRegistry>| {
276
let type_registry = &registry.as_ref().read();
277
remove_reflect_with_registry_ref(entity, type_registry, component_type_path);
278
});
279
self
280
}
281
282
/// Same as [`remove_reflect`](EntityWorldMut::remove_reflect), but using
283
/// the `T` resource as type registry instead of `AppTypeRegistry`.
284
///
285
/// If the given type is a bundle, it will remove any components in that bundle regardless if the entity
286
/// contains all the components.
287
///
288
/// Does nothing if the type is a component and the entity does not have a component of the same type,
289
/// if the type is a bundle and the entity does not contain any of the components in the bundle,
290
/// or if [`AppTypeRegistry`] does not contain the reflection data for the given component.
291
///
292
/// # Panics
293
///
294
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
295
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
296
pub fn remove_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
297
&mut self,
298
component_type_path: Cow<'static, str>,
299
) -> &mut Self {
300
self.assert_not_despawned();
301
self.resource_scope(|entity, registry: Mut<T>| {
302
let type_registry = registry.as_ref().as_ref();
303
remove_reflect_with_registry_ref(entity, type_registry, component_type_path);
304
});
305
self
306
}
307
308
/// Takes from the entity the component or bundle with the given type path registered in [`AppTypeRegistry`].
309
///
310
/// Does nothing and returns None if the type is a component and the entity does not have a component of the same type,
311
/// if the type is a bundle and the entity does not contain **every** component in the bundle,
312
/// or if [`AppTypeRegistry`] does not contain the reflection data for the given component.
313
///
314
/// # Panics
315
///
316
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
317
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
318
///
319
/// # Note
320
///
321
/// Prefer to use the typed [`EntityWorldMut::take`] if possible. Taking a reflected component
322
/// is much slower.
323
pub fn take_reflect(
324
&mut self,
325
component_type_path: Cow<'static, str>,
326
) -> Option<Box<dyn Reflect>> {
327
self.assert_not_despawned();
328
self.resource_scope(|entity, registry: Mut<AppTypeRegistry>| {
329
let type_registry = &registry.as_ref().read();
330
take_reflect_with_registry_ref(entity, type_registry, component_type_path)
331
})
332
}
333
334
/// Same as [`take_reflect`](EntityWorldMut::take_reflect), but using
335
/// the `T` resource as type registry instead of `AppTypeRegistry`.
336
///
337
/// Does nothing and returns None if the type is a component and the entity does not have a component of the same type,
338
/// if the type is a bundle and the entity does not contain **every** component in the bundle,
339
/// or if [`AppTypeRegistry`] does not contain the reflection data for the given component.
340
///
341
/// # Panics
342
///
343
/// - If the entity has been despawned while this `EntityWorldMut` is still alive.
344
/// - If [`AppTypeRegistry`] is not present in the [`World`](crate::world::World).
345
pub fn take_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
346
&mut self,
347
component_type_path: Cow<'static, str>,
348
) -> Option<Box<dyn Reflect>> {
349
self.assert_not_despawned();
350
self.resource_scope(|entity, registry: Mut<T>| {
351
let type_registry = registry.as_ref().as_ref();
352
take_reflect_with_registry_ref(entity, type_registry, component_type_path)
353
})
354
}
355
}
356
357
/// Helper function to add a reflect component or bundle to a given entity
358
fn insert_reflect_with_registry_ref(
359
entity: &mut EntityWorldMut,
360
type_registry: &TypeRegistry,
361
component: Box<dyn PartialReflect>,
362
) {
363
let type_info = component
364
.get_represented_type_info()
365
.expect("component should represent a type.");
366
let type_path = type_info.type_path();
367
let Some(type_registration) = type_registry.get(type_info.type_id()) else {
368
panic!("`{type_path}` should be registered in type registry via `App::register_type<{type_path}>`");
369
};
370
371
if let Some(reflect_component) = type_registration.data::<ReflectComponent>() {
372
reflect_component.insert(entity, component.as_partial_reflect(), type_registry);
373
} else if let Some(reflect_bundle) = type_registration.data::<ReflectBundle>() {
374
reflect_bundle.insert(entity, component.as_partial_reflect(), type_registry);
375
} else {
376
panic!("`{type_path}` should have #[reflect(Component)] or #[reflect(Bundle)]");
377
}
378
}
379
380
/// Helper function to remove a reflect component or bundle from a given entity
381
fn remove_reflect_with_registry_ref(
382
entity: &mut EntityWorldMut,
383
type_registry: &TypeRegistry,
384
component_type_path: Cow<'static, str>,
385
) {
386
let Some(type_registration) = type_registry.get_with_type_path(&component_type_path) else {
387
return;
388
};
389
if let Some(reflect_component) = type_registration.data::<ReflectComponent>() {
390
reflect_component.remove(entity);
391
} else if let Some(reflect_bundle) = type_registration.data::<ReflectBundle>() {
392
reflect_bundle.remove(entity);
393
}
394
}
395
396
/// Helper function to take a reflect component or bundle from a given entity
397
fn take_reflect_with_registry_ref(
398
entity: &mut EntityWorldMut,
399
type_registry: &TypeRegistry,
400
component_type_path: Cow<'static, str>,
401
) -> Option<Box<dyn Reflect>> {
402
let type_registration = type_registry.get_with_type_path(&component_type_path)?;
403
if let Some(reflect_component) = type_registration.data::<ReflectComponent>() {
404
reflect_component.take(entity)
405
} else if let Some(reflect_bundle) = type_registration.data::<ReflectBundle>() {
406
reflect_bundle.take(entity)
407
} else {
408
None
409
}
410
}
411
412
#[cfg(test)]
413
mod tests {
414
use crate::{
415
bundle::Bundle,
416
component::Component,
417
prelude::{AppTypeRegistry, ReflectComponent},
418
reflect::{ReflectBundle, ReflectCommandExt},
419
system::{Commands, SystemState},
420
world::World,
421
};
422
use alloc::{borrow::ToOwned, boxed::Box};
423
use bevy_ecs_macros::Resource;
424
use bevy_reflect::{PartialReflect, Reflect, TypeRegistry};
425
426
#[derive(Resource)]
427
struct TypeRegistryResource {
428
type_registry: TypeRegistry,
429
}
430
431
impl AsRef<TypeRegistry> for TypeRegistryResource {
432
fn as_ref(&self) -> &TypeRegistry {
433
&self.type_registry
434
}
435
}
436
437
#[derive(Component, Reflect, Default, PartialEq, Eq, Debug)]
438
#[reflect(Component)]
439
struct ComponentA(u32);
440
441
#[derive(Component, Reflect, Default, PartialEq, Eq, Debug)]
442
#[reflect(Component)]
443
struct ComponentB(u32);
444
445
#[derive(Bundle, Reflect, Default, Debug, PartialEq)]
446
#[reflect(Bundle)]
447
struct BundleA {
448
a: ComponentA,
449
b: ComponentB,
450
}
451
452
#[test]
453
fn insert_reflected() {
454
let mut world = World::new();
455
456
let type_registry = AppTypeRegistry::default();
457
{
458
let mut registry = type_registry.write();
459
registry.register::<ComponentA>();
460
registry.register_type_data::<ComponentA, ReflectComponent>();
461
}
462
world.insert_resource(type_registry);
463
464
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
465
let mut commands = system_state.get_mut(&mut world);
466
467
let entity = commands.spawn_empty().id();
468
let entity2 = commands.spawn_empty().id();
469
let entity3 = commands.spawn_empty().id();
470
471
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn PartialReflect>;
472
let boxed_reflect_component_a_clone = boxed_reflect_component_a.reflect_clone().unwrap();
473
let boxed_reflect_component_a_dynamic = boxed_reflect_component_a.to_dynamic();
474
475
commands
476
.entity(entity)
477
.insert_reflect(boxed_reflect_component_a);
478
commands
479
.entity(entity2)
480
.insert_reflect(boxed_reflect_component_a_clone.into_partial_reflect());
481
commands
482
.entity(entity3)
483
.insert_reflect(boxed_reflect_component_a_dynamic);
484
system_state.apply(&mut world);
485
486
assert_eq!(
487
world.entity(entity).get::<ComponentA>(),
488
world.entity(entity2).get::<ComponentA>(),
489
);
490
assert_eq!(
491
world.entity(entity).get::<ComponentA>(),
492
world.entity(entity3).get::<ComponentA>(),
493
);
494
}
495
496
#[test]
497
fn insert_reflected_with_registry() {
498
let mut world = World::new();
499
500
let mut type_registry = TypeRegistryResource {
501
type_registry: TypeRegistry::new(),
502
};
503
504
type_registry.type_registry.register::<ComponentA>();
505
type_registry
506
.type_registry
507
.register_type_data::<ComponentA, ReflectComponent>();
508
world.insert_resource(type_registry);
509
510
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
511
let mut commands = system_state.get_mut(&mut world);
512
513
let entity = commands.spawn_empty().id();
514
515
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn PartialReflect>;
516
517
commands
518
.entity(entity)
519
.insert_reflect_with_registry::<TypeRegistryResource>(boxed_reflect_component_a);
520
system_state.apply(&mut world);
521
522
assert_eq!(
523
world.entity(entity).get::<ComponentA>(),
524
Some(&ComponentA(916))
525
);
526
}
527
528
#[test]
529
fn remove_reflected() {
530
let mut world = World::new();
531
532
let type_registry = AppTypeRegistry::default();
533
{
534
let mut registry = type_registry.write();
535
registry.register::<ComponentA>();
536
registry.register_type_data::<ComponentA, ReflectComponent>();
537
}
538
world.insert_resource(type_registry);
539
540
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
541
let mut commands = system_state.get_mut(&mut world);
542
543
let entity = commands.spawn(ComponentA(0)).id();
544
545
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn Reflect>;
546
547
commands
548
.entity(entity)
549
.remove_reflect(boxed_reflect_component_a.reflect_type_path().to_owned());
550
system_state.apply(&mut world);
551
552
assert_eq!(world.entity(entity).get::<ComponentA>(), None);
553
}
554
555
#[test]
556
fn remove_reflected_with_registry() {
557
let mut world = World::new();
558
559
let mut type_registry = TypeRegistryResource {
560
type_registry: TypeRegistry::new(),
561
};
562
563
type_registry.type_registry.register::<ComponentA>();
564
type_registry
565
.type_registry
566
.register_type_data::<ComponentA, ReflectComponent>();
567
world.insert_resource(type_registry);
568
569
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
570
let mut commands = system_state.get_mut(&mut world);
571
572
let entity = commands.spawn(ComponentA(0)).id();
573
574
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn Reflect>;
575
576
commands
577
.entity(entity)
578
.remove_reflect_with_registry::<TypeRegistryResource>(
579
boxed_reflect_component_a.reflect_type_path().to_owned(),
580
);
581
system_state.apply(&mut world);
582
583
assert_eq!(world.entity(entity).get::<ComponentA>(), None);
584
}
585
586
#[test]
587
fn insert_reflect_bundle() {
588
let mut world = World::new();
589
590
let type_registry = AppTypeRegistry::default();
591
{
592
let mut registry = type_registry.write();
593
registry.register::<BundleA>();
594
registry.register_type_data::<BundleA, ReflectBundle>();
595
}
596
world.insert_resource(type_registry);
597
598
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
599
let mut commands = system_state.get_mut(&mut world);
600
601
let entity = commands.spawn_empty().id();
602
let bundle = Box::new(BundleA {
603
a: ComponentA(31),
604
b: ComponentB(20),
605
}) as Box<dyn PartialReflect>;
606
commands.entity(entity).insert_reflect(bundle);
607
608
system_state.apply(&mut world);
609
610
assert_eq!(world.get::<ComponentA>(entity), Some(&ComponentA(31)));
611
assert_eq!(world.get::<ComponentB>(entity), Some(&ComponentB(20)));
612
}
613
614
#[test]
615
fn insert_reflect_bundle_with_registry() {
616
let mut world = World::new();
617
618
let mut type_registry = TypeRegistryResource {
619
type_registry: TypeRegistry::new(),
620
};
621
622
type_registry.type_registry.register::<BundleA>();
623
type_registry
624
.type_registry
625
.register_type_data::<BundleA, ReflectBundle>();
626
world.insert_resource(type_registry);
627
628
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
629
let mut commands = system_state.get_mut(&mut world);
630
631
let entity = commands.spawn_empty().id();
632
let bundle = Box::new(BundleA {
633
a: ComponentA(31),
634
b: ComponentB(20),
635
}) as Box<dyn PartialReflect>;
636
637
commands
638
.entity(entity)
639
.insert_reflect_with_registry::<TypeRegistryResource>(bundle);
640
system_state.apply(&mut world);
641
642
assert_eq!(world.get::<ComponentA>(entity), Some(&ComponentA(31)));
643
assert_eq!(world.get::<ComponentB>(entity), Some(&ComponentB(20)));
644
}
645
646
#[test]
647
fn remove_reflected_bundle() {
648
let mut world = World::new();
649
650
let type_registry = AppTypeRegistry::default();
651
{
652
let mut registry = type_registry.write();
653
registry.register::<BundleA>();
654
registry.register_type_data::<BundleA, ReflectBundle>();
655
}
656
world.insert_resource(type_registry);
657
658
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
659
let mut commands = system_state.get_mut(&mut world);
660
661
let entity = commands
662
.spawn(BundleA {
663
a: ComponentA(31),
664
b: ComponentB(20),
665
})
666
.id();
667
668
let boxed_reflect_bundle_a = Box::new(BundleA {
669
a: ComponentA(1),
670
b: ComponentB(23),
671
}) as Box<dyn Reflect>;
672
673
commands
674
.entity(entity)
675
.remove_reflect(boxed_reflect_bundle_a.reflect_type_path().to_owned());
676
system_state.apply(&mut world);
677
678
assert_eq!(world.entity(entity).get::<ComponentA>(), None);
679
assert_eq!(world.entity(entity).get::<ComponentB>(), None);
680
}
681
682
#[test]
683
fn remove_reflected_bundle_with_registry() {
684
let mut world = World::new();
685
686
let mut type_registry = TypeRegistryResource {
687
type_registry: TypeRegistry::new(),
688
};
689
690
type_registry.type_registry.register::<BundleA>();
691
type_registry
692
.type_registry
693
.register_type_data::<BundleA, ReflectBundle>();
694
world.insert_resource(type_registry);
695
696
let mut system_state: SystemState<Commands> = SystemState::new(&mut world);
697
let mut commands = system_state.get_mut(&mut world);
698
699
let entity = commands
700
.spawn(BundleA {
701
a: ComponentA(31),
702
b: ComponentB(20),
703
})
704
.id();
705
706
let boxed_reflect_bundle_a = Box::new(BundleA {
707
a: ComponentA(1),
708
b: ComponentB(23),
709
}) as Box<dyn Reflect>;
710
711
commands
712
.entity(entity)
713
.remove_reflect_with_registry::<TypeRegistryResource>(
714
boxed_reflect_bundle_a.reflect_type_path().to_owned(),
715
);
716
system_state.apply(&mut world);
717
718
assert_eq!(world.entity(entity).get::<ComponentA>(), None);
719
assert_eq!(world.entity(entity).get::<ComponentB>(), None);
720
}
721
}
722
723