Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/hierarchy.rs
6598 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
// 12 children should result in a flat tuple
812
let id = world
813
.spawn(children![(), (), (), (), (), (), (), (), (), (), (), ()])
814
.id();
815
816
assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 12,);
817
818
// 13 will start nesting, but should nonetheless produce a flat hierarchy
819
let id = world
820
.spawn(children![
821
(),
822
(),
823
(),
824
(),
825
(),
826
(),
827
(),
828
(),
829
(),
830
(),
831
(),
832
(),
833
(),
834
])
835
.id();
836
837
assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 13,);
838
}
839
840
#[test]
841
fn replace_children() {
842
let mut world = World::new();
843
let parent = world.spawn(Children::spawn((Spawn(()), Spawn(())))).id();
844
let &[child_a, child_b] = &world.entity(parent).get::<Children>().unwrap().0[..] else {
845
panic!("Tried to spawn 2 children on an entity and didn't get 2 children");
846
};
847
848
let child_c = world.spawn_empty().id();
849
850
world
851
.entity_mut(parent)
852
.replace_children(&[child_a, child_c]);
853
854
let children = world.entity(parent).get::<Children>().unwrap();
855
856
assert!(children.contains(&child_a));
857
assert!(children.contains(&child_c));
858
assert!(!children.contains(&child_b));
859
860
assert_eq!(
861
world.entity(child_a).get::<ChildOf>().unwrap(),
862
&ChildOf(parent)
863
);
864
assert_eq!(
865
world.entity(child_c).get::<ChildOf>().unwrap(),
866
&ChildOf(parent)
867
);
868
assert!(world.entity(child_b).get::<ChildOf>().is_none());
869
}
870
871
#[test]
872
fn replace_children_with_nothing() {
873
let mut world = World::new();
874
let parent = world.spawn_empty().id();
875
let child_a = world.spawn_empty().id();
876
let child_b = world.spawn_empty().id();
877
878
world.entity_mut(parent).add_children(&[child_a, child_b]);
879
880
assert_eq!(world.entity(parent).get::<Children>().unwrap().len(), 2);
881
882
world.entity_mut(parent).replace_children(&[]);
883
884
assert!(world.entity(child_a).get::<ChildOf>().is_none());
885
assert!(world.entity(child_b).get::<ChildOf>().is_none());
886
}
887
888
#[test]
889
fn insert_same_child_twice() {
890
let mut world = World::new();
891
892
let parent = world.spawn_empty().id();
893
let child = world.spawn_empty().id();
894
895
world.entity_mut(parent).add_child(child);
896
world.entity_mut(parent).add_child(child);
897
898
let children = world.get::<Children>(parent).unwrap();
899
assert_eq!(children.0, [child]);
900
assert_eq!(
901
world.entity(child).get::<ChildOf>().unwrap(),
902
&ChildOf(parent)
903
);
904
}
905
906
#[test]
907
fn replace_with_difference() {
908
let mut world = World::new();
909
910
let parent = world.spawn_empty().id();
911
let child_a = world.spawn_empty().id();
912
let child_b = world.spawn_empty().id();
913
let child_c = world.spawn_empty().id();
914
let child_d = world.spawn_empty().id();
915
916
// Test inserting new relations
917
world.entity_mut(parent).replace_children_with_difference(
918
&[],
919
&[child_a, child_b],
920
&[child_a, child_b],
921
);
922
923
assert_eq!(
924
world.entity(child_a).get::<ChildOf>().unwrap(),
925
&ChildOf(parent)
926
);
927
assert_eq!(
928
world.entity(child_b).get::<ChildOf>().unwrap(),
929
&ChildOf(parent)
930
);
931
assert_eq!(
932
world.entity(parent).get::<Children>().unwrap().0,
933
[child_a, child_b]
934
);
935
936
// Test replacing relations and changing order
937
world.entity_mut(parent).replace_children_with_difference(
938
&[child_b],
939
&[child_d, child_c, child_a],
940
&[child_c, child_d],
941
);
942
assert_eq!(
943
world.entity(child_a).get::<ChildOf>().unwrap(),
944
&ChildOf(parent)
945
);
946
assert_eq!(
947
world.entity(child_c).get::<ChildOf>().unwrap(),
948
&ChildOf(parent)
949
);
950
assert_eq!(
951
world.entity(child_d).get::<ChildOf>().unwrap(),
952
&ChildOf(parent)
953
);
954
assert_eq!(
955
world.entity(parent).get::<Children>().unwrap().0,
956
[child_d, child_c, child_a]
957
);
958
assert!(!world.entity(child_b).contains::<ChildOf>());
959
960
// Test removing relationships
961
world.entity_mut(parent).replace_children_with_difference(
962
&[child_a, child_d, child_c],
963
&[],
964
&[],
965
);
966
assert!(!world.entity(parent).contains::<Children>());
967
assert!(!world.entity(child_a).contains::<ChildOf>());
968
assert!(!world.entity(child_b).contains::<ChildOf>());
969
assert!(!world.entity(child_c).contains::<ChildOf>());
970
assert!(!world.entity(child_d).contains::<ChildOf>());
971
}
972
973
#[test]
974
fn replace_with_difference_on_empty() {
975
let mut world = World::new();
976
977
let parent = world.spawn_empty().id();
978
let child_a = world.spawn_empty().id();
979
980
world
981
.entity_mut(parent)
982
.replace_children_with_difference(&[child_a], &[], &[]);
983
984
assert!(!world.entity(parent).contains::<Children>());
985
assert!(!world.entity(child_a).contains::<ChildOf>());
986
}
987
988
#[test]
989
fn replace_with_difference_totally_new_children() {
990
let mut world = World::new();
991
992
let parent = world.spawn_empty().id();
993
let child_a = world.spawn_empty().id();
994
let child_b = world.spawn_empty().id();
995
let child_c = world.spawn_empty().id();
996
let child_d = world.spawn_empty().id();
997
998
// Test inserting new relations
999
world.entity_mut(parent).replace_children_with_difference(
1000
&[],
1001
&[child_a, child_b],
1002
&[child_a, child_b],
1003
);
1004
1005
assert_eq!(
1006
world.entity(child_a).get::<ChildOf>().unwrap(),
1007
&ChildOf(parent)
1008
);
1009
assert_eq!(
1010
world.entity(child_b).get::<ChildOf>().unwrap(),
1011
&ChildOf(parent)
1012
);
1013
assert_eq!(
1014
world.entity(parent).get::<Children>().unwrap().0,
1015
[child_a, child_b]
1016
);
1017
1018
// Test replacing relations and changing order
1019
world.entity_mut(parent).replace_children_with_difference(
1020
&[child_b, child_a],
1021
&[child_d, child_c],
1022
&[child_c, child_d],
1023
);
1024
assert_eq!(
1025
world.entity(child_c).get::<ChildOf>().unwrap(),
1026
&ChildOf(parent)
1027
);
1028
assert_eq!(
1029
world.entity(child_d).get::<ChildOf>().unwrap(),
1030
&ChildOf(parent)
1031
);
1032
assert_eq!(
1033
world.entity(parent).get::<Children>().unwrap().0,
1034
[child_d, child_c]
1035
);
1036
assert!(!world.entity(child_a).contains::<ChildOf>());
1037
assert!(!world.entity(child_b).contains::<ChildOf>());
1038
}
1039
1040
#[test]
1041
fn replace_children_order() {
1042
let mut world = World::new();
1043
1044
let parent = world.spawn_empty().id();
1045
let child_a = world.spawn_empty().id();
1046
let child_b = world.spawn_empty().id();
1047
let child_c = world.spawn_empty().id();
1048
let child_d = world.spawn_empty().id();
1049
1050
let initial_order = [child_a, child_b, child_c, child_d];
1051
world.entity_mut(parent).add_children(&initial_order);
1052
1053
assert_eq!(
1054
world.entity_mut(parent).get::<Children>().unwrap().0,
1055
initial_order
1056
);
1057
1058
let new_order = [child_d, child_b, child_a, child_c];
1059
world.entity_mut(parent).replace_children(&new_order);
1060
1061
assert_eq!(world.entity(parent).get::<Children>().unwrap().0, new_order);
1062
}
1063
1064
#[test]
1065
#[should_panic]
1066
#[cfg_attr(
1067
not(debug_assertions),
1068
ignore = "we don't check invariants if debug assertions are off"
1069
)]
1070
fn replace_diff_invariant_overlapping_unrelate_with_relate() {
1071
let mut world = World::new();
1072
1073
let parent = world.spawn_empty().id();
1074
let child_a = world.spawn_empty().id();
1075
1076
world
1077
.entity_mut(parent)
1078
.replace_children_with_difference(&[], &[child_a], &[child_a]);
1079
1080
// This should panic
1081
world
1082
.entity_mut(parent)
1083
.replace_children_with_difference(&[child_a], &[child_a], &[]);
1084
}
1085
1086
#[test]
1087
#[should_panic]
1088
#[cfg_attr(
1089
not(debug_assertions),
1090
ignore = "we don't check invariants if debug assertions are off"
1091
)]
1092
fn replace_diff_invariant_overlapping_unrelate_with_newly() {
1093
let mut world = World::new();
1094
1095
let parent = world.spawn_empty().id();
1096
let child_a = world.spawn_empty().id();
1097
let child_b = world.spawn_empty().id();
1098
1099
world
1100
.entity_mut(parent)
1101
.replace_children_with_difference(&[], &[child_a], &[child_a]);
1102
1103
// This should panic
1104
world.entity_mut(parent).replace_children_with_difference(
1105
&[child_b],
1106
&[child_a, child_b],
1107
&[child_b],
1108
);
1109
}
1110
1111
#[test]
1112
#[should_panic]
1113
#[cfg_attr(
1114
not(debug_assertions),
1115
ignore = "we don't check invariants if debug assertions are off"
1116
)]
1117
fn replace_diff_invariant_newly_not_subset() {
1118
let mut world = World::new();
1119
1120
let parent = world.spawn_empty().id();
1121
let child_a = world.spawn_empty().id();
1122
let child_b = world.spawn_empty().id();
1123
1124
// This should panic
1125
world.entity_mut(parent).replace_children_with_difference(
1126
&[],
1127
&[child_a, child_b],
1128
&[child_a],
1129
);
1130
}
1131
1132
#[test]
1133
fn child_replace_hook_skip() {
1134
let mut world = World::new();
1135
let parent = world.spawn_empty().id();
1136
let other = world.spawn_empty().id();
1137
let child = world.spawn(ChildOf(parent)).id();
1138
world
1139
.entity_mut(child)
1140
.insert_with_relationship_hook_mode(ChildOf(other), RelationshipHookMode::Skip);
1141
assert_eq!(
1142
&**world.entity(parent).get::<Children>().unwrap(),
1143
&[child],
1144
"Children should still have the old value, as on_insert/on_replace didn't run"
1145
);
1146
}
1147
}
1148
1149