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