Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/hierarchy.rs
6849 views
1
//! The canonical "parent-child" [`Relationship`] for entities, driven by
2
//! the [`ChildOf`] [`Relationship`] and the [`Children`] [`RelationshipTarget`].
3
//!
4
//! See [`ChildOf`] for a full description of the relationship and how to use it.
5
//!
6
//! [`Relationship`]: crate::relationship::Relationship
7
//! [`RelationshipTarget`]: crate::relationship::RelationshipTarget
8
9
#[cfg(feature = "bevy_reflect")]
10
use crate::reflect::{ReflectComponent, ReflectFromWorld};
11
use crate::{
12
bundle::Bundle,
13
component::Component,
14
entity::Entity,
15
lifecycle::HookContext,
16
relationship::{RelatedSpawner, RelatedSpawnerCommands},
17
system::EntityCommands,
18
world::{DeferredWorld, EntityWorldMut, FromWorld, World},
19
};
20
use alloc::{format, string::String, vec::Vec};
21
#[cfg(feature = "bevy_reflect")]
22
use bevy_reflect::std_traits::ReflectDefault;
23
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
24
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
25
use bevy_utils::prelude::DebugName;
26
use core::ops::Deref;
27
use core::slice;
28
use log::warn;
29
30
/// Stores the parent entity of this child entity with this component.
31
///
32
/// This is a [`Relationship`] component, and creates the canonical
33
/// "parent / child" hierarchy. This is the "source of truth" component, and it pairs with
34
/// the [`Children`] [`RelationshipTarget`](crate::relationship::RelationshipTarget).
35
///
36
/// This relationship should be used for things like:
37
///
38
/// 1. Organizing entities in a scene
39
/// 2. Propagating configuration or data inherited from a parent, such as "visibility" or "world-space global transforms".
40
/// 3. Ensuring a hierarchy is despawned when an entity is despawned.
41
///
42
/// [`ChildOf`] contains a single "target" [`Entity`]. When [`ChildOf`] is inserted on a "source" entity,
43
/// the "target" entity will automatically (and immediately, via a component hook) have a [`Children`]
44
/// component inserted, and the "source" entity will be added to that [`Children`] instance.
45
///
46
/// If the [`ChildOf`] component is replaced with a different "target" entity, the old target's [`Children`]
47
/// will be automatically (and immediately, via a component hook) be updated to reflect that change.
48
///
49
/// Likewise, when the [`ChildOf`] component is removed, the "source" entity will be removed from the old
50
/// target's [`Children`]. If this results in [`Children`] being empty, [`Children`] will be automatically removed.
51
///
52
/// When a parent is despawned, all children (and their descendants) will _also_ be despawned.
53
///
54
/// You can create parent-child relationships in a variety of ways. The most direct way is to insert a [`ChildOf`] component:
55
///
56
/// ```
57
/// # use bevy_ecs::prelude::*;
58
/// # let mut world = World::new();
59
/// let root = world.spawn_empty().id();
60
/// let child1 = world.spawn(ChildOf(root)).id();
61
/// let child2 = world.spawn(ChildOf(root)).id();
62
/// let grandchild = world.spawn(ChildOf(child1)).id();
63
///
64
/// assert_eq!(&**world.entity(root).get::<Children>().unwrap(), &[child1, child2]);
65
/// assert_eq!(&**world.entity(child1).get::<Children>().unwrap(), &[grandchild]);
66
///
67
/// world.entity_mut(child2).remove::<ChildOf>();
68
/// assert_eq!(&**world.entity(root).get::<Children>().unwrap(), &[child1]);
69
///
70
/// world.entity_mut(root).despawn();
71
/// assert!(world.get_entity(root).is_err());
72
/// assert!(world.get_entity(child1).is_err());
73
/// assert!(world.get_entity(grandchild).is_err());
74
/// ```
75
///
76
/// However if you are spawning many children, you might want to use the [`EntityWorldMut::with_children`] helper instead:
77
///
78
/// ```
79
/// # use bevy_ecs::prelude::*;
80
/// # let mut world = World::new();
81
/// let mut child1 = Entity::PLACEHOLDER;
82
/// let mut child2 = Entity::PLACEHOLDER;
83
/// let mut grandchild = Entity::PLACEHOLDER;
84
/// let root = world.spawn_empty().with_children(|p| {
85
/// child1 = p.spawn_empty().with_children(|p| {
86
/// grandchild = p.spawn_empty().id();
87
/// }).id();
88
/// child2 = p.spawn_empty().id();
89
/// }).id();
90
///
91
/// assert_eq!(&**world.entity(root).get::<Children>().unwrap(), &[child1, child2]);
92
/// assert_eq!(&**world.entity(child1).get::<Children>().unwrap(), &[grandchild]);
93
/// ```
94
///
95
/// [`Relationship`]: crate::relationship::Relationship
96
#[derive(Component, Clone, PartialEq, Eq, Debug)]
97
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
98
#[cfg_attr(
99
feature = "bevy_reflect",
100
reflect(Component, PartialEq, Debug, FromWorld, Clone)
101
)]
102
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
103
#[cfg_attr(
104
all(feature = "serialize", feature = "bevy_reflect"),
105
reflect(Serialize, Deserialize)
106
)]
107
#[relationship(relationship_target = Children)]
108
#[doc(alias = "IsChild", alias = "Parent")]
109
pub struct ChildOf(#[entities] pub Entity);
110
111
impl ChildOf {
112
/// The parent entity of this child entity.
113
#[inline]
114
pub fn parent(&self) -> Entity {
115
self.0
116
}
117
}
118
119
// TODO: We need to impl either FromWorld or Default so ChildOf can be registered as Reflect.
120
// This is because Reflect deserialize by creating an instance and apply a patch on top.
121
// However ChildOf should only ever be set with a real user-defined entity. Its worth looking into
122
// better ways to handle cases like this.
123
impl FromWorld for ChildOf {
124
#[inline(always)]
125
fn from_world(_world: &mut World) -> Self {
126
ChildOf(Entity::PLACEHOLDER)
127
}
128
}
129
130
/// Tracks which entities are children of this parent entity.
131
///
132
/// A [`RelationshipTarget`] collection component that is populated
133
/// with entities that "target" this entity with the [`ChildOf`] [`Relationship`] component.
134
///
135
/// Together, these components form the "canonical parent-child hierarchy". See the [`ChildOf`] component for the full
136
/// description of this relationship and instructions on how to use it.
137
///
138
/// # Usage
139
///
140
/// Like all [`RelationshipTarget`] components, this data should not be directly manipulated to avoid desynchronization.
141
/// Instead, modify the [`ChildOf`] components on the "source" entities.
142
///
143
/// To access the children of an entity, you can iterate over the [`Children`] component,
144
/// using the [`IntoIterator`] trait.
145
/// For more complex access patterns, see the [`RelationshipTarget`] trait.
146
///
147
/// [`Relationship`]: crate::relationship::Relationship
148
/// [`RelationshipTarget`]: crate::relationship::RelationshipTarget
149
#[derive(Component, Default, Debug, PartialEq, Eq)]
150
#[relationship_target(relationship = ChildOf, linked_spawn)]
151
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
152
#[cfg_attr(feature = "bevy_reflect", reflect(Component, FromWorld, Default))]
153
#[doc(alias = "IsParent")]
154
pub struct Children(Vec<Entity>);
155
156
impl Children {
157
/// Swaps the child at `a_index` with the child at `b_index`.
158
#[inline]
159
pub fn swap(&mut self, a_index: usize, b_index: usize) {
160
self.0.swap(a_index, b_index);
161
}
162
163
/// Sorts children [stably](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)
164
/// in place using the provided comparator function.
165
///
166
/// For the underlying implementation, see [`slice::sort_by`].
167
///
168
/// For the unstable version, see [`sort_unstable_by`](Children::sort_unstable_by).
169
///
170
/// See also [`sort_by_key`](Children::sort_by_key), [`sort_by_cached_key`](Children::sort_by_cached_key).
171
#[inline]
172
pub fn sort_by<F>(&mut self, compare: F)
173
where
174
F: FnMut(&Entity, &Entity) -> core::cmp::Ordering,
175
{
176
self.0.sort_by(compare);
177
}
178
179
/// Sorts children [stably](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)
180
/// in place using the provided key extraction function.
181
///
182
/// For the underlying implementation, see [`slice::sort_by_key`].
183
///
184
/// For the unstable version, see [`sort_unstable_by_key`](Children::sort_unstable_by_key).
185
///
186
/// See also [`sort_by`](Children::sort_by), [`sort_by_cached_key`](Children::sort_by_cached_key).
187
#[inline]
188
pub fn sort_by_key<K, F>(&mut self, compare: F)
189
where
190
F: FnMut(&Entity) -> K,
191
K: Ord,
192
{
193
self.0.sort_by_key(compare);
194
}
195
196
/// Sorts children [stably](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)
197
/// in place using the provided key extraction function. Only evaluates each key at most
198
/// once per sort, caching the intermediate results in memory.
199
///
200
/// For the underlying implementation, see [`slice::sort_by_cached_key`].
201
///
202
/// See also [`sort_by`](Children::sort_by), [`sort_by_key`](Children::sort_by_key).
203
#[inline]
204
pub fn sort_by_cached_key<K, F>(&mut self, compare: F)
205
where
206
F: FnMut(&Entity) -> K,
207
K: Ord,
208
{
209
self.0.sort_by_cached_key(compare);
210
}
211
212
/// Sorts children [unstably](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)
213
/// in place using the provided comparator function.
214
///
215
/// For the underlying implementation, see [`slice::sort_unstable_by`].
216
///
217
/// For the stable version, see [`sort_by`](Children::sort_by).
218
///
219
/// See also [`sort_unstable_by_key`](Children::sort_unstable_by_key).
220
#[inline]
221
pub fn sort_unstable_by<F>(&mut self, compare: F)
222
where
223
F: FnMut(&Entity, &Entity) -> core::cmp::Ordering,
224
{
225
self.0.sort_unstable_by(compare);
226
}
227
228
/// Sorts children [unstably](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)
229
/// in place using the provided key extraction function.
230
///
231
/// For the underlying implementation, see [`slice::sort_unstable_by_key`].
232
///
233
/// For the stable version, see [`sort_by_key`](Children::sort_by_key).
234
///
235
/// See also [`sort_unstable_by`](Children::sort_unstable_by).
236
#[inline]
237
pub fn sort_unstable_by_key<K, F>(&mut self, compare: F)
238
where
239
F: FnMut(&Entity) -> K,
240
K: Ord,
241
{
242
self.0.sort_unstable_by_key(compare);
243
}
244
}
245
246
impl<'a> IntoIterator for &'a Children {
247
type Item = <Self::IntoIter as Iterator>::Item;
248
249
type IntoIter = slice::Iter<'a, Entity>;
250
251
#[inline(always)]
252
fn into_iter(self) -> Self::IntoIter {
253
self.0.iter()
254
}
255
}
256
257
impl Deref for Children {
258
type Target = [Entity];
259
260
fn deref(&self) -> &Self::Target {
261
&self.0
262
}
263
}
264
265
/// A type alias over [`RelatedSpawner`] used to spawn child entities containing a [`ChildOf`] relationship.
266
pub type ChildSpawner<'w> = RelatedSpawner<'w, ChildOf>;
267
268
/// A type alias over [`RelatedSpawnerCommands`] used to spawn child entities containing a [`ChildOf`] relationship.
269
pub type ChildSpawnerCommands<'w> = RelatedSpawnerCommands<'w, ChildOf>;
270
271
impl<'w> EntityWorldMut<'w> {
272
/// Spawns children of this entity (with a [`ChildOf`] relationship) by taking a function that operates on a [`ChildSpawner`].
273
/// See also [`with_related`](Self::with_related).
274
pub fn with_children(&mut self, func: impl FnOnce(&mut ChildSpawner)) -> &mut Self {
275
self.with_related_entities(func);
276
self
277
}
278
279
/// Adds the given children to this entity
280
/// See also [`add_related`](Self::add_related).
281
pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
282
self.add_related::<ChildOf>(children)
283
}
284
285
/// Removes all the children from this entity.
286
/// See also [`clear_related`](Self::clear_related)
287
pub fn clear_children(&mut self) -> &mut Self {
288
self.clear_related::<ChildOf>()
289
}
290
291
/// Insert children at specific index.
292
/// See also [`insert_related`](Self::insert_related).
293
pub fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
294
self.insert_related::<ChildOf>(index, children)
295
}
296
297
/// Insert child at specific index.
298
/// See also [`insert_related`](Self::insert_related).
299
pub fn insert_child(&mut self, index: usize, child: Entity) -> &mut Self {
300
self.insert_related::<ChildOf>(index, &[child])
301
}
302
303
/// Adds the given child to this entity
304
/// See also [`add_related`](Self::add_related).
305
pub fn add_child(&mut self, child: Entity) -> &mut Self {
306
self.add_related::<ChildOf>(&[child])
307
}
308
309
/// Removes the relationship between this entity and the given entities.
310
pub fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
311
self.remove_related::<ChildOf>(children)
312
}
313
314
/// Removes the relationship between this entity and the given entity.
315
pub fn remove_child(&mut self, child: Entity) -> &mut Self {
316
self.remove_related::<ChildOf>(&[child])
317
}
318
319
/// Replaces all the related children with a new set of children.
320
pub fn replace_children(&mut self, children: &[Entity]) -> &mut Self {
321
self.replace_related::<ChildOf>(children)
322
}
323
324
/// Replaces all the related children with a new set of children.
325
///
326
/// # Warning
327
///
328
/// Failing to maintain the functions invariants may lead to erratic engine behavior including random crashes.
329
/// Refer to [`Self::replace_related_with_difference`] for a list of these invariants.
330
///
331
/// # Panics
332
///
333
/// Panics when debug assertions are enabled if an invariant is broken and the command is executed.
334
pub fn replace_children_with_difference(
335
&mut self,
336
entities_to_unrelate: &[Entity],
337
entities_to_relate: &[Entity],
338
newly_related_entities: &[Entity],
339
) -> &mut Self {
340
self.replace_related_with_difference::<ChildOf>(
341
entities_to_unrelate,
342
entities_to_relate,
343
newly_related_entities,
344
)
345
}
346
347
/// Spawns the passed bundle and adds it to this entity as a child.
348
///
349
/// For efficient spawning of multiple children, use [`with_children`].
350
///
351
/// [`with_children`]: EntityWorldMut::with_children
352
pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
353
let parent = self.id();
354
self.world_scope(|world| {
355
world.spawn((bundle, ChildOf(parent)));
356
});
357
self
358
}
359
}
360
361
impl<'a> EntityCommands<'a> {
362
/// Spawns children of this entity (with a [`ChildOf`] relationship) by taking a function that operates on a [`ChildSpawner`].
363
pub fn with_children(
364
&mut self,
365
func: impl FnOnce(&mut RelatedSpawnerCommands<ChildOf>),
366
) -> &mut Self {
367
self.with_related_entities(func);
368
self
369
}
370
371
/// Adds the given children to this entity
372
pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
373
self.add_related::<ChildOf>(children)
374
}
375
376
/// Removes all the children from this entity.
377
/// See also [`clear_related`](Self::clear_related)
378
pub fn clear_children(&mut self) -> &mut Self {
379
self.clear_related::<ChildOf>()
380
}
381
382
/// Insert children at specific index.
383
/// See also [`insert_related`](Self::insert_related).
384
pub fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
385
self.insert_related::<ChildOf>(index, children)
386
}
387
388
/// Insert children at specific index.
389
/// See also [`insert_related`](Self::insert_related).
390
pub fn insert_child(&mut self, index: usize, child: Entity) -> &mut Self {
391
self.insert_related::<ChildOf>(index, &[child])
392
}
393
394
/// Adds the given child to this entity
395
pub fn add_child(&mut self, child: Entity) -> &mut Self {
396
self.add_related::<ChildOf>(&[child])
397
}
398
399
/// Removes the relationship between this entity and the given entities.
400
pub fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
401
self.remove_related::<ChildOf>(children)
402
}
403
404
/// Removes the relationship between this entity and the given entity.
405
pub fn remove_child(&mut self, child: Entity) -> &mut Self {
406
self.remove_related::<ChildOf>(&[child])
407
}
408
409
/// Replaces the children on this entity with a new list of children.
410
pub fn replace_children(&mut self, children: &[Entity]) -> &mut Self {
411
self.replace_related::<ChildOf>(children)
412
}
413
414
/// Replaces all the related entities with a new set of entities.
415
///
416
/// # Warning
417
///
418
/// Failing to maintain the functions invariants may lead to erratic engine behavior including random crashes.
419
/// Refer to [`EntityWorldMut::replace_related_with_difference`] for a list of these invariants.
420
///
421
/// # Panics
422
///
423
/// Panics when debug assertions are enabled if an invariant is broken and the command is executed.
424
pub fn replace_children_with_difference(
425
&mut self,
426
entities_to_unrelate: &[Entity],
427
entities_to_relate: &[Entity],
428
newly_related_entities: &[Entity],
429
) -> &mut Self {
430
self.replace_related_with_difference::<ChildOf>(
431
entities_to_unrelate,
432
entities_to_relate,
433
newly_related_entities,
434
)
435
}
436
437
/// Spawns the passed bundle and adds it to this entity as a child.
438
///
439
/// For efficient spawning of multiple children, use [`with_children`].
440
///
441
/// [`with_children`]: EntityCommands::with_children
442
pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
443
self.with_related::<ChildOf>(bundle);
444
self
445
}
446
}
447
448
/// An `on_insert` component hook that when run, will validate that the parent of a given entity
449
/// contains component `C`. This will print a warning if the parent does not contain `C`.
450
pub fn validate_parent_has_component<C: Component>(
451
world: DeferredWorld,
452
HookContext { entity, caller, .. }: HookContext,
453
) {
454
let entity_ref = world.entity(entity);
455
let Some(child_of) = entity_ref.get::<ChildOf>() else {
456
return;
457
};
458
let parent = child_of.parent();
459
if !world.get_entity(parent).is_ok_and(|e| e.contains::<C>()) {
460
// TODO: print name here once Name lives in bevy_ecs
461
let name: Option<String> = None;
462
let debug_name = DebugName::type_name::<C>();
463
warn!(
464
"warning[B0004]: {}{name} with the {ty_name} component has a parent ({parent}) without {ty_name}.\n\
465
This will cause inconsistent behaviors! See: https://bevy.org/learn/errors/b0004",
466
caller.map(|c| format!("{c}: ")).unwrap_or_default(),
467
ty_name = debug_name.shortname(),
468
name = name.map_or_else(
469
|| format!("Entity {entity}"),
470
|s| format!("The {s} entity")
471
),
472
);
473
}
474
}
475
476
/// Returns a [`SpawnRelatedBundle`] that will insert the [`Children`] component, spawn a [`SpawnableList`] of entities with given bundles that
477
/// relate to the [`Children`] entity via the [`ChildOf`] component, and reserve space in the [`Children`] for each spawned entity.
478
///
479
/// Any additional arguments will be interpreted as bundles to be spawned.
480
///
481
/// Also see [`related`](crate::related) for a version of this that works with any [`RelationshipTarget`] type.
482
///
483
/// ```
484
/// # use bevy_ecs::hierarchy::Children;
485
/// # use bevy_ecs::name::Name;
486
/// # use bevy_ecs::world::World;
487
/// # use bevy_ecs::children;
488
/// # use bevy_ecs::spawn::{Spawn, SpawnRelated};
489
/// let mut world = World::new();
490
/// world.spawn((
491
/// Name::new("Root"),
492
/// children![
493
/// Name::new("Child1"),
494
/// (
495
/// Name::new("Child2"),
496
/// children![Name::new("Grandchild")]
497
/// )
498
/// ]
499
/// ));
500
/// ```
501
///
502
/// [`RelationshipTarget`]: crate::relationship::RelationshipTarget
503
/// [`SpawnRelatedBundle`]: crate::spawn::SpawnRelatedBundle
504
/// [`SpawnableList`]: crate::spawn::SpawnableList
505
#[macro_export]
506
macro_rules! children {
507
[$($child:expr),*$(,)?] => {
508
$crate::hierarchy::Children::spawn($crate::recursive_spawn!($($child),*))
509
};
510
}
511
512
#[cfg(test)]
513
mod tests {
514
use crate::{
515
entity::Entity,
516
hierarchy::{ChildOf, Children},
517
relationship::{RelationshipHookMode, RelationshipTarget},
518
spawn::{Spawn, SpawnRelated},
519
world::World,
520
};
521
use alloc::{vec, vec::Vec};
522
523
#[derive(PartialEq, Eq, Debug)]
524
struct Node {
525
entity: Entity,
526
children: Vec<Node>,
527
}
528
529
impl Node {
530
fn new(entity: Entity) -> Self {
531
Self {
532
entity,
533
children: Vec::new(),
534
}
535
}
536
537
fn new_with(entity: Entity, children: Vec<Node>) -> Self {
538
Self { entity, children }
539
}
540
}
541
542
fn get_hierarchy(world: &World, entity: Entity) -> Node {
543
Node {
544
entity,
545
children: world
546
.entity(entity)
547
.get::<Children>()
548
.map_or_else(Default::default, |c| {
549
c.iter().map(|e| get_hierarchy(world, e)).collect()
550
}),
551
}
552
}
553
554
#[test]
555
fn hierarchy() {
556
let mut world = World::new();
557
let root = world.spawn_empty().id();
558
let child1 = world.spawn(ChildOf(root)).id();
559
let grandchild = world.spawn(ChildOf(child1)).id();
560
let child2 = world.spawn(ChildOf(root)).id();
561
562
// Spawn
563
let hierarchy = get_hierarchy(&world, root);
564
assert_eq!(
565
hierarchy,
566
Node::new_with(
567
root,
568
vec![
569
Node::new_with(child1, vec![Node::new(grandchild)]),
570
Node::new(child2)
571
]
572
)
573
);
574
575
// Removal
576
world.entity_mut(child1).remove::<ChildOf>();
577
let hierarchy = get_hierarchy(&world, root);
578
assert_eq!(hierarchy, Node::new_with(root, vec![Node::new(child2)]));
579
580
// Insert
581
world.entity_mut(child1).insert(ChildOf(root));
582
let hierarchy = get_hierarchy(&world, root);
583
assert_eq!(
584
hierarchy,
585
Node::new_with(
586
root,
587
vec![
588
Node::new(child2),
589
Node::new_with(child1, vec![Node::new(grandchild)])
590
]
591
)
592
);
593
594
// Recursive Despawn
595
world.entity_mut(root).despawn();
596
assert!(world.get_entity(root).is_err());
597
assert!(world.get_entity(child1).is_err());
598
assert!(world.get_entity(child2).is_err());
599
assert!(world.get_entity(grandchild).is_err());
600
}
601
602
#[test]
603
fn with_children() {
604
let mut world = World::new();
605
let mut child1 = Entity::PLACEHOLDER;
606
let mut child2 = Entity::PLACEHOLDER;
607
let root = world
608
.spawn_empty()
609
.with_children(|p| {
610
child1 = p.spawn_empty().id();
611
child2 = p.spawn_empty().id();
612
})
613
.id();
614
615
let hierarchy = get_hierarchy(&world, root);
616
assert_eq!(
617
hierarchy,
618
Node::new_with(root, vec![Node::new(child1), Node::new(child2)])
619
);
620
}
621
622
#[test]
623
fn add_children() {
624
let mut world = World::new();
625
let child1 = world.spawn_empty().id();
626
let child2 = world.spawn_empty().id();
627
let root = world.spawn_empty().add_children(&[child1, child2]).id();
628
629
let hierarchy = get_hierarchy(&world, root);
630
assert_eq!(
631
hierarchy,
632
Node::new_with(root, vec![Node::new(child1), Node::new(child2)])
633
);
634
}
635
636
#[test]
637
fn insert_children() {
638
let mut world = World::new();
639
let child1 = world.spawn_empty().id();
640
let child2 = world.spawn_empty().id();
641
let child3 = world.spawn_empty().id();
642
let child4 = world.spawn_empty().id();
643
644
let mut entity_world_mut = world.spawn_empty();
645
646
let first_children = entity_world_mut.add_children(&[child1, child2]);
647
648
let root = first_children.insert_children(1, &[child3, child4]).id();
649
650
let hierarchy = get_hierarchy(&world, root);
651
assert_eq!(
652
hierarchy,
653
Node::new_with(
654
root,
655
vec![
656
Node::new(child1),
657
Node::new(child3),
658
Node::new(child4),
659
Node::new(child2)
660
]
661
)
662
);
663
}
664
665
#[test]
666
fn insert_child() {
667
let mut world = World::new();
668
let child1 = world.spawn_empty().id();
669
let child2 = world.spawn_empty().id();
670
let child3 = world.spawn_empty().id();
671
672
let mut entity_world_mut = world.spawn_empty();
673
674
let first_children = entity_world_mut.add_children(&[child1, child2]);
675
676
let root = first_children.insert_child(1, child3).id();
677
678
let hierarchy = get_hierarchy(&world, root);
679
assert_eq!(
680
hierarchy,
681
Node::new_with(
682
root,
683
vec![Node::new(child1), Node::new(child3), Node::new(child2)]
684
)
685
);
686
}
687
688
// regression test for https://github.com/bevyengine/bevy/pull/19134
689
#[test]
690
fn insert_children_index_bound() {
691
let mut world = World::new();
692
let child1 = world.spawn_empty().id();
693
let child2 = world.spawn_empty().id();
694
let child3 = world.spawn_empty().id();
695
let child4 = world.spawn_empty().id();
696
697
let mut entity_world_mut = world.spawn_empty();
698
699
let first_children = entity_world_mut.add_children(&[child1, child2]).id();
700
let hierarchy = get_hierarchy(&world, first_children);
701
assert_eq!(
702
hierarchy,
703
Node::new_with(first_children, vec![Node::new(child1), Node::new(child2)])
704
);
705
706
let root = world
707
.entity_mut(first_children)
708
.insert_children(usize::MAX, &[child3, child4])
709
.id();
710
let hierarchy = get_hierarchy(&world, root);
711
assert_eq!(
712
hierarchy,
713
Node::new_with(
714
root,
715
vec![
716
Node::new(child1),
717
Node::new(child2),
718
Node::new(child3),
719
Node::new(child4),
720
]
721
)
722
);
723
}
724
725
#[test]
726
fn remove_children() {
727
let mut world = World::new();
728
let child1 = world.spawn_empty().id();
729
let child2 = world.spawn_empty().id();
730
let child3 = world.spawn_empty().id();
731
let child4 = world.spawn_empty().id();
732
733
let mut root = world.spawn_empty();
734
root.add_children(&[child1, child2, child3, child4]);
735
root.remove_children(&[child2, child3]);
736
let root = root.id();
737
738
let hierarchy = get_hierarchy(&world, root);
739
assert_eq!(
740
hierarchy,
741
Node::new_with(root, vec![Node::new(child1), Node::new(child4)])
742
);
743
}
744
745
#[test]
746
fn remove_child() {
747
let mut world = World::new();
748
let child1 = world.spawn_empty().id();
749
let child2 = world.spawn_empty().id();
750
let child3 = world.spawn_empty().id();
751
752
let mut root = world.spawn_empty();
753
root.add_children(&[child1, child2, child3]);
754
root.remove_child(child2);
755
let root = root.id();
756
757
let hierarchy = get_hierarchy(&world, root);
758
assert_eq!(
759
hierarchy,
760
Node::new_with(root, vec![Node::new(child1), Node::new(child3)])
761
);
762
}
763
764
#[test]
765
fn self_parenting_invalid() {
766
let mut world = World::new();
767
let id = world.spawn_empty().id();
768
world.entity_mut(id).insert(ChildOf(id));
769
assert!(
770
world.entity(id).get::<ChildOf>().is_none(),
771
"invalid ChildOf relationships should self-remove"
772
);
773
}
774
775
#[test]
776
fn missing_parent_invalid() {
777
let mut world = World::new();
778
let parent = world.spawn_empty().id();
779
world.entity_mut(parent).despawn();
780
let id = world.spawn(ChildOf(parent)).id();
781
assert!(
782
world.entity(id).get::<ChildOf>().is_none(),
783
"invalid ChildOf relationships should self-remove"
784
);
785
}
786
787
#[test]
788
fn reinsert_same_parent() {
789
let mut world = World::new();
790
let parent = world.spawn_empty().id();
791
let id = world.spawn(ChildOf(parent)).id();
792
world.entity_mut(id).insert(ChildOf(parent));
793
assert_eq!(
794
Some(&ChildOf(parent)),
795
world.entity(id).get::<ChildOf>(),
796
"ChildOf should still be there"
797
);
798
}
799
800
#[test]
801
fn spawn_children() {
802
let mut world = World::new();
803
let id = world.spawn(Children::spawn((Spawn(()), Spawn(())))).id();
804
assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 2,);
805
}
806
807
#[test]
808
fn spawn_many_children() {
809
let mut world = World::new();
810
811
// ensure an empty set can be mentioned
812
world.spawn(children![]);
813
814
// 12 children should result in a flat tuple
815
let id = world
816
.spawn(children![(), (), (), (), (), (), (), (), (), (), (), ()])
817
.id();
818
819
assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 12,);
820
821
// 13 will start nesting, but should nonetheless produce a flat hierarchy
822
let id = world
823
.spawn(children![
824
(),
825
(),
826
(),
827
(),
828
(),
829
(),
830
(),
831
(),
832
(),
833
(),
834
(),
835
(),
836
(),
837
])
838
.id();
839
840
assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 13,);
841
}
842
843
#[test]
844
fn replace_children() {
845
let mut world = World::new();
846
let parent = world.spawn(Children::spawn((Spawn(()), Spawn(())))).id();
847
let &[child_a, child_b] = &world.entity(parent).get::<Children>().unwrap().0[..] else {
848
panic!("Tried to spawn 2 children on an entity and didn't get 2 children");
849
};
850
851
let child_c = world.spawn_empty().id();
852
853
world
854
.entity_mut(parent)
855
.replace_children(&[child_a, child_c]);
856
857
let children = world.entity(parent).get::<Children>().unwrap();
858
859
assert!(children.contains(&child_a));
860
assert!(children.contains(&child_c));
861
assert!(!children.contains(&child_b));
862
863
assert_eq!(
864
world.entity(child_a).get::<ChildOf>().unwrap(),
865
&ChildOf(parent)
866
);
867
assert_eq!(
868
world.entity(child_c).get::<ChildOf>().unwrap(),
869
&ChildOf(parent)
870
);
871
assert!(world.entity(child_b).get::<ChildOf>().is_none());
872
}
873
874
#[test]
875
fn replace_children_with_nothing() {
876
let mut world = World::new();
877
let parent = world.spawn_empty().id();
878
let child_a = world.spawn_empty().id();
879
let child_b = world.spawn_empty().id();
880
881
world.entity_mut(parent).add_children(&[child_a, child_b]);
882
883
assert_eq!(world.entity(parent).get::<Children>().unwrap().len(), 2);
884
885
world.entity_mut(parent).replace_children(&[]);
886
887
assert!(world.entity(child_a).get::<ChildOf>().is_none());
888
assert!(world.entity(child_b).get::<ChildOf>().is_none());
889
}
890
891
#[test]
892
fn insert_same_child_twice() {
893
let mut world = World::new();
894
895
let parent = world.spawn_empty().id();
896
let child = world.spawn_empty().id();
897
898
world.entity_mut(parent).add_child(child);
899
world.entity_mut(parent).add_child(child);
900
901
let children = world.get::<Children>(parent).unwrap();
902
assert_eq!(children.0, [child]);
903
assert_eq!(
904
world.entity(child).get::<ChildOf>().unwrap(),
905
&ChildOf(parent)
906
);
907
}
908
909
#[test]
910
fn replace_with_difference() {
911
let mut world = World::new();
912
913
let parent = world.spawn_empty().id();
914
let child_a = world.spawn_empty().id();
915
let child_b = world.spawn_empty().id();
916
let child_c = world.spawn_empty().id();
917
let child_d = world.spawn_empty().id();
918
919
// Test inserting new relations
920
world.entity_mut(parent).replace_children_with_difference(
921
&[],
922
&[child_a, child_b],
923
&[child_a, child_b],
924
);
925
926
assert_eq!(
927
world.entity(child_a).get::<ChildOf>().unwrap(),
928
&ChildOf(parent)
929
);
930
assert_eq!(
931
world.entity(child_b).get::<ChildOf>().unwrap(),
932
&ChildOf(parent)
933
);
934
assert_eq!(
935
world.entity(parent).get::<Children>().unwrap().0,
936
[child_a, child_b]
937
);
938
939
// Test replacing relations and changing order
940
world.entity_mut(parent).replace_children_with_difference(
941
&[child_b],
942
&[child_d, child_c, child_a],
943
&[child_c, child_d],
944
);
945
assert_eq!(
946
world.entity(child_a).get::<ChildOf>().unwrap(),
947
&ChildOf(parent)
948
);
949
assert_eq!(
950
world.entity(child_c).get::<ChildOf>().unwrap(),
951
&ChildOf(parent)
952
);
953
assert_eq!(
954
world.entity(child_d).get::<ChildOf>().unwrap(),
955
&ChildOf(parent)
956
);
957
assert_eq!(
958
world.entity(parent).get::<Children>().unwrap().0,
959
[child_d, child_c, child_a]
960
);
961
assert!(!world.entity(child_b).contains::<ChildOf>());
962
963
// Test removing relationships
964
world.entity_mut(parent).replace_children_with_difference(
965
&[child_a, child_d, child_c],
966
&[],
967
&[],
968
);
969
assert!(!world.entity(parent).contains::<Children>());
970
assert!(!world.entity(child_a).contains::<ChildOf>());
971
assert!(!world.entity(child_b).contains::<ChildOf>());
972
assert!(!world.entity(child_c).contains::<ChildOf>());
973
assert!(!world.entity(child_d).contains::<ChildOf>());
974
}
975
976
#[test]
977
fn replace_with_difference_on_empty() {
978
let mut world = World::new();
979
980
let parent = world.spawn_empty().id();
981
let child_a = world.spawn_empty().id();
982
983
world
984
.entity_mut(parent)
985
.replace_children_with_difference(&[child_a], &[], &[]);
986
987
assert!(!world.entity(parent).contains::<Children>());
988
assert!(!world.entity(child_a).contains::<ChildOf>());
989
}
990
991
#[test]
992
fn replace_with_difference_totally_new_children() {
993
let mut world = World::new();
994
995
let parent = world.spawn_empty().id();
996
let child_a = world.spawn_empty().id();
997
let child_b = world.spawn_empty().id();
998
let child_c = world.spawn_empty().id();
999
let child_d = world.spawn_empty().id();
1000
1001
// Test inserting new relations
1002
world.entity_mut(parent).replace_children_with_difference(
1003
&[],
1004
&[child_a, child_b],
1005
&[child_a, child_b],
1006
);
1007
1008
assert_eq!(
1009
world.entity(child_a).get::<ChildOf>().unwrap(),
1010
&ChildOf(parent)
1011
);
1012
assert_eq!(
1013
world.entity(child_b).get::<ChildOf>().unwrap(),
1014
&ChildOf(parent)
1015
);
1016
assert_eq!(
1017
world.entity(parent).get::<Children>().unwrap().0,
1018
[child_a, child_b]
1019
);
1020
1021
// Test replacing relations and changing order
1022
world.entity_mut(parent).replace_children_with_difference(
1023
&[child_b, child_a],
1024
&[child_d, child_c],
1025
&[child_c, child_d],
1026
);
1027
assert_eq!(
1028
world.entity(child_c).get::<ChildOf>().unwrap(),
1029
&ChildOf(parent)
1030
);
1031
assert_eq!(
1032
world.entity(child_d).get::<ChildOf>().unwrap(),
1033
&ChildOf(parent)
1034
);
1035
assert_eq!(
1036
world.entity(parent).get::<Children>().unwrap().0,
1037
[child_d, child_c]
1038
);
1039
assert!(!world.entity(child_a).contains::<ChildOf>());
1040
assert!(!world.entity(child_b).contains::<ChildOf>());
1041
}
1042
1043
#[test]
1044
fn replace_children_order() {
1045
let mut world = World::new();
1046
1047
let parent = world.spawn_empty().id();
1048
let child_a = world.spawn_empty().id();
1049
let child_b = world.spawn_empty().id();
1050
let child_c = world.spawn_empty().id();
1051
let child_d = world.spawn_empty().id();
1052
1053
let initial_order = [child_a, child_b, child_c, child_d];
1054
world.entity_mut(parent).add_children(&initial_order);
1055
1056
assert_eq!(
1057
world.entity_mut(parent).get::<Children>().unwrap().0,
1058
initial_order
1059
);
1060
1061
let new_order = [child_d, child_b, child_a, child_c];
1062
world.entity_mut(parent).replace_children(&new_order);
1063
1064
assert_eq!(world.entity(parent).get::<Children>().unwrap().0, new_order);
1065
}
1066
1067
#[test]
1068
#[should_panic]
1069
#[cfg_attr(
1070
not(debug_assertions),
1071
ignore = "we don't check invariants if debug assertions are off"
1072
)]
1073
fn replace_diff_invariant_overlapping_unrelate_with_relate() {
1074
let mut world = World::new();
1075
1076
let parent = world.spawn_empty().id();
1077
let child_a = world.spawn_empty().id();
1078
1079
world
1080
.entity_mut(parent)
1081
.replace_children_with_difference(&[], &[child_a], &[child_a]);
1082
1083
// This should panic
1084
world
1085
.entity_mut(parent)
1086
.replace_children_with_difference(&[child_a], &[child_a], &[]);
1087
}
1088
1089
#[test]
1090
#[should_panic]
1091
#[cfg_attr(
1092
not(debug_assertions),
1093
ignore = "we don't check invariants if debug assertions are off"
1094
)]
1095
fn replace_diff_invariant_overlapping_unrelate_with_newly() {
1096
let mut world = World::new();
1097
1098
let parent = world.spawn_empty().id();
1099
let child_a = world.spawn_empty().id();
1100
let child_b = world.spawn_empty().id();
1101
1102
world
1103
.entity_mut(parent)
1104
.replace_children_with_difference(&[], &[child_a], &[child_a]);
1105
1106
// This should panic
1107
world.entity_mut(parent).replace_children_with_difference(
1108
&[child_b],
1109
&[child_a, child_b],
1110
&[child_b],
1111
);
1112
}
1113
1114
#[test]
1115
#[should_panic]
1116
#[cfg_attr(
1117
not(debug_assertions),
1118
ignore = "we don't check invariants if debug assertions are off"
1119
)]
1120
fn replace_diff_invariant_newly_not_subset() {
1121
let mut world = World::new();
1122
1123
let parent = world.spawn_empty().id();
1124
let child_a = world.spawn_empty().id();
1125
let child_b = world.spawn_empty().id();
1126
1127
// This should panic
1128
world.entity_mut(parent).replace_children_with_difference(
1129
&[],
1130
&[child_a, child_b],
1131
&[child_a],
1132
);
1133
}
1134
1135
#[test]
1136
fn child_replace_hook_skip() {
1137
let mut world = World::new();
1138
let parent = world.spawn_empty().id();
1139
let other = world.spawn_empty().id();
1140
let child = world.spawn(ChildOf(parent)).id();
1141
world
1142
.entity_mut(child)
1143
.insert_with_relationship_hook_mode(ChildOf(other), RelationshipHookMode::Skip);
1144
assert_eq!(
1145
&**world.entity(parent).get::<Children>().unwrap(),
1146
&[child],
1147
"Children should still have the old value, as on_insert/on_replace didn't run"
1148
);
1149
}
1150
}
1151
1152