@@ -37,6 +37,9 @@ fn update_parent(world: &mut World, child: Entity, new_parent: Entity) -> Option
37
37
}
38
38
}
39
39
40
+ /// Remove child from the parent's [`Children`] component.
41
+ ///
42
+ /// Removes the [`Children`] component from the parent if it's empty.
40
43
fn remove_from_children ( world : & mut World , parent : Entity , child : Entity ) {
41
44
let mut parent = world. entity_mut ( parent) ;
42
45
if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
@@ -47,24 +50,61 @@ fn remove_from_children(world: &mut World, parent: Entity, child: Entity) {
47
50
}
48
51
}
49
52
53
+ /// Update the [`Parent`] component of the `child`.
54
+ /// Removes the `child` from the previous parent's [`Children`].
55
+ ///
56
+ /// Does not update the new parents [`Children`] component.
57
+ ///
58
+ /// Does nothing if `child` was already a child of `parent`.
59
+ ///
60
+ /// Sends [`HierarchyEvent`]'s.
61
+ fn update_old_parent ( world : & mut World , child : Entity , parent : Entity ) {
62
+ let previous = update_parent ( world, child, parent) ;
63
+ if let Some ( previous_parent) = previous {
64
+ // Do nothing if the child was already parented to this entity.
65
+ if previous_parent == parent {
66
+ return ;
67
+ }
68
+ remove_from_children ( world, previous_parent, child) ;
69
+
70
+ world. send_event ( HierarchyEvent :: ChildMoved {
71
+ child,
72
+ previous_parent,
73
+ new_parent : parent,
74
+ } ) ;
75
+ } else {
76
+ world. send_event ( HierarchyEvent :: ChildAdded { child, parent } ) ;
77
+ }
78
+ }
79
+
80
+ /// Update the [`Parent`] components of the `children`.
81
+ /// Removes the `children` from their previous parent's [`Children`].
82
+ ///
83
+ /// Does not update the new parents [`Children`] component.
84
+ ///
85
+ /// Does nothing for a child if it was already a child of `parent`.
86
+ ///
87
+ /// Sends [`HierarchyEvent`]'s.
50
88
fn update_old_parents ( world : & mut World , parent : Entity , children : & [ Entity ] ) {
51
- let mut moved : SmallVec < [ HierarchyEvent ; 8 ] > = SmallVec :: with_capacity ( children. len ( ) ) ;
52
- for child in children {
53
- if let Some ( previous) = update_parent ( world, * child, parent) {
89
+ let mut events : SmallVec < [ HierarchyEvent ; 8 ] > = SmallVec :: with_capacity ( children. len ( ) ) ;
90
+ for & child in children {
91
+ if let Some ( previous) = update_parent ( world, child, parent) {
54
92
// Do nothing if the entity already has the correct parent.
55
93
if parent == previous {
56
94
continue ;
57
95
}
58
96
59
- remove_from_children ( world, previous, * child) ;
60
- moved . push ( HierarchyEvent :: ChildMoved {
61
- child : * child ,
97
+ remove_from_children ( world, previous, child) ;
98
+ events . push ( HierarchyEvent :: ChildMoved {
99
+ child,
62
100
previous_parent : previous,
63
101
new_parent : parent,
64
102
} ) ;
103
+ } else {
104
+ events. push ( HierarchyEvent :: ChildAdded { child, parent } ) ;
65
105
}
66
106
}
67
- push_events ( world, moved ) ;
107
+ push_events ( world, events ) ;
68
108
}
69
109
70
110
fn remove_children ( parent : Entity , children : & [ Entity ] , world : & mut World ) {
@@ -108,33 +148,7 @@ pub struct AddChild {
108
148
109
149
impl Command for AddChild {
110
150
fn write ( self , world : & mut World ) {
111
- let previous = update_parent ( world, self . child , self . parent ) ;
112
- if let Some ( previous) = previous {
113
- if previous == self . parent {
114
- return ;
115
- }
116
- remove_from_children ( world, previous, self . child ) ;
117
- if let Some ( mut events) = world. get_resource_mut :: < Events < HierarchyEvent > > ( ) {
118
- events. send ( HierarchyEvent :: ChildMoved {
119
- child : self . child ,
120
- previous_parent : previous,
121
- new_parent : self . parent ,
122
- } ) ;
123
- }
124
- } else if let Some ( mut events) = world. get_resource_mut :: < Events < HierarchyEvent > > ( ) {
125
- events. send ( HierarchyEvent :: ChildAdded {
126
- child : self . child ,
127
- parent : self . parent ,
128
- } ) ;
129
- }
130
- let mut parent = world. entity_mut ( self . parent ) ;
131
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
132
- if !children. contains ( & self . child ) {
133
- children. 0 . push ( self . child ) ;
134
- }
135
- } else {
136
- parent. insert ( Children ( smallvec:: smallvec![ self . child] ) ) ;
137
- }
151
+ world. entity_mut ( self . parent ) . add_child ( self . child ) ;
138
152
}
139
153
}
140
154
@@ -148,14 +162,9 @@ pub struct InsertChildren {
148
162
149
163
impl Command for InsertChildren {
150
164
fn write ( self , world : & mut World ) {
151
- update_old_parents ( world, self . parent , & self . children ) ;
152
- let mut parent = world. entity_mut ( self . parent ) ;
153
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
154
- children. 0 . retain ( |value| !self . children . contains ( value) ) ;
155
- children. 0 . insert_from_slice ( self . index , & self . children ) ;
156
- } else {
157
- parent. insert ( Children ( self . children ) ) ;
158
- }
165
+ world
166
+ . entity_mut ( self . parent )
167
+ . insert_children ( self . index , & self . children ) ;
159
168
}
160
169
}
161
170
@@ -167,15 +176,8 @@ pub struct PushChildren {
167
176
}
168
177
169
178
impl Command for PushChildren {
170
- fn write ( mut self , world : & mut World ) {
171
- update_old_parents ( world, self . parent , & self . children ) ;
172
- let mut parent = world. entity_mut ( self . parent ) ;
173
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
174
- children. 0 . retain ( |child| !self . children . contains ( child) ) ;
175
- children. 0 . append ( & mut self . children ) ;
176
- } else {
177
- parent. insert ( Children ( self . children ) ) ;
178
- }
179
+ fn write ( self , world : & mut World ) {
180
+ world. entity_mut ( self . parent ) . push_children ( & self . children ) ;
179
181
}
180
182
}
181
183
@@ -198,17 +200,7 @@ pub struct RemoveParent {
198
200
199
201
impl Command for RemoveParent {
200
202
fn write ( self , world : & mut World ) {
201
- if let Some ( parent) = world. get :: < Parent > ( self . child ) {
202
- let parent_entity = parent. get ( ) ;
203
- remove_from_children ( world, parent_entity, self . child ) ;
204
- world. entity_mut ( self . child ) . remove :: < Parent > ( ) ;
205
- if let Some ( mut events) = world. get_resource_mut :: < Events < _ > > ( ) {
206
- events. send ( HierarchyEvent :: ChildRemoved {
207
- child : self . child ,
208
- parent : parent_entity,
209
- } ) ;
210
- }
211
- }
203
+ world. entity_mut ( self . child ) . remove_parent ( ) ;
212
204
}
213
205
}
214
206
@@ -425,12 +417,28 @@ impl<'w> WorldChildBuilder<'w> {
425
417
pub trait BuildWorldChildren {
426
418
/// Creates a [`WorldChildBuilder`] with the given children built in the given closure
427
419
fn with_children ( & mut self , spawn_children : impl FnOnce ( & mut WorldChildBuilder ) ) -> & mut Self ;
420
+
421
+ /// Adds a single child
422
+ ///
423
+ /// If the children were previously children of another parent, that parent's [`Children`] component
424
+ /// will have those children removed from its list. Removing all children from a parent causes its
425
+ /// [`Children`] component to be removed from the entity.
426
+ fn add_child ( & mut self , child : Entity ) -> & mut Self ;
427
+
428
428
/// Pushes children to the back of the builder's children
429
429
fn push_children ( & mut self , children : & [ Entity ] ) -> & mut Self ;
430
430
/// Inserts children at the given index
431
431
fn insert_children ( & mut self , index : usize , children : & [ Entity ] ) -> & mut Self ;
432
432
/// Removes the given children
433
433
fn remove_children ( & mut self , children : & [ Entity ] ) -> & mut Self ;
434
+
435
+ /// Set the `parent` of this entity. This entity will be added to the end of the `parent`'s list of children.
436
+ ///
437
+ /// If this entity already had a parent it will be removed from it.
438
+ fn set_parent ( & mut self , parent : Entity ) -> & mut Self ;
439
+
440
+ /// Remove the parent from this entity.
441
+ fn remove_parent ( & mut self ) -> & mut Self ;
434
442
}
435
443
436
444
impl < ' w > BuildWorldChildren for EntityMut < ' w > {
@@ -442,6 +450,20 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
442
450
self
443
451
}
444
452
453
+ fn add_child ( & mut self , child : Entity ) -> & mut Self {
454
+ let parent = self . id ( ) ;
455
+ self . world_scope ( |world| {
456
+ update_old_parent ( world, child, parent) ;
457
+ } ) ;
458
+ if let Some ( mut children_component) = self . get_mut :: < Children > ( ) {
459
+ children_component. 0 . retain ( |value| child != * value) ;
460
+ children_component. 0 . push ( child) ;
461
+ } else {
462
+ self . insert ( Children :: from_entities ( & [ child] ) ) ;
463
+ }
464
+ self
465
+ }
466
+
445
467
fn push_children ( & mut self , children : & [ Entity ] ) -> & mut Self {
446
468
let parent = self . id ( ) ;
447
469
self . world_scope ( |world| {
@@ -481,21 +503,172 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
481
503
} ) ;
482
504
self
483
505
}
506
+
507
+ fn set_parent ( & mut self , parent : Entity ) -> & mut Self {
508
+ let child = self . id ( ) ;
509
+ self . world_scope ( |world| {
510
+ world. entity_mut ( parent) . add_child ( child) ;
511
+ } ) ;
512
+ self
513
+ }
514
+
515
+ fn remove_parent ( & mut self ) -> & mut Self {
516
+ let child = self . id ( ) ;
517
+ if let Some ( parent) = self . remove :: < Parent > ( ) . map ( |p| p. get ( ) ) {
518
+ self . world_scope ( |world| {
519
+ remove_from_children ( world, parent, child) ;
520
+ world. send_event ( HierarchyEvent :: ChildRemoved { child, parent } ) ;
521
+ } ) ;
522
+ }
523
+ self
524
+ }
484
525
}
485
526
486
527
#[ cfg( test) ]
487
528
mod tests {
488
529
use super :: { BuildChildren , BuildWorldChildren } ;
489
- use crate :: prelude:: { Children , Parent } ;
530
+ use crate :: {
531
+ components:: { Children , Parent } ,
532
+ HierarchyEvent :: { self , ChildAdded , ChildMoved , ChildRemoved } ,
533
+ } ;
490
534
use smallvec:: { smallvec, SmallVec } ;
491
535
492
536
use bevy_ecs:: {
493
537
component:: Component ,
494
538
entity:: Entity ,
539
+ event:: Events ,
495
540
system:: { CommandQueue , Commands } ,
496
541
world:: World ,
497
542
} ;
498
543
544
+ /// Assert the (non)existence and state of the child's [`Parent`] component.
545
+ fn assert_parent ( world : & mut World , child : Entity , parent : Option < Entity > ) {
546
+ assert_eq ! ( world. get:: <Parent >( child) . map( |p| p. get( ) ) , parent) ;
547
+ }
548
+
549
+ /// Assert the (non)existence and state of the parent's [`Children`] component.
550
+ fn assert_children ( world : & mut World , parent : Entity , children : Option < & [ Entity ] > ) {
551
+ assert_eq ! ( world. get:: <Children >( parent) . map( |c| & * * c) , children) ;
552
+ }
553
+
554
+ /// Used to omit a number of events that are not relevant to a particular test.
555
+ fn omit_events ( world : & mut World , number : usize ) {
556
+ let mut events_resource = world. resource_mut :: < Events < HierarchyEvent > > ( ) ;
557
+ let mut events: Vec < _ > = events_resource. drain ( ) . collect ( ) ;
558
+ events_resource. extend ( events. drain ( number..) ) ;
559
+ }
560
+
561
+ fn assert_events ( world : & mut World , expected_events : & [ HierarchyEvent ] ) {
562
+ let events: Vec < _ > = world
563
+ . resource_mut :: < Events < HierarchyEvent > > ( )
564
+ . drain ( )
565
+ . collect ( ) ;
566
+ assert_eq ! ( events, expected_events) ;
567
+ }
568
+
569
+ #[ test]
570
+ fn add_child ( ) {
571
+ let world = & mut World :: new ( ) ;
572
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
573
+
574
+ let [ a, b, c, d] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
575
+
576
+ world. entity_mut ( a) . add_child ( b) ;
577
+
578
+ assert_parent ( world, b, Some ( a) ) ;
579
+ assert_children ( world, a, Some ( & [ b] ) ) ;
580
+ assert_events (
581
+ world,
582
+ & [ ChildAdded {
583
+ child : b,
584
+ parent : a,
585
+ } ] ,
586
+ ) ;
587
+
588
+ world. entity_mut ( a) . add_child ( c) ;
589
+
590
+ assert_children ( world, a, Some ( & [ b, c] ) ) ;
591
+ assert_parent ( world, c, Some ( a) ) ;
592
+ assert_events (
593
+ world,
594
+ & [ ChildAdded {
595
+ child : c,
596
+ parent : a,
597
+ } ] ,
598
+ ) ;
599
+ // Children component should be removed when it's empty.
600
+ world. entity_mut ( d) . add_child ( b) . add_child ( c) ;
601
+ assert_children ( world, a, None ) ;
602
+ }
603
+
604
+ #[ test]
605
+ fn set_parent ( ) {
606
+ let world = & mut World :: new ( ) ;
607
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
608
+
609
+ let [ a, b, c] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
610
+
611
+ world. entity_mut ( a) . set_parent ( b) ;
612
+
613
+ assert_parent ( world, a, Some ( b) ) ;
614
+ assert_children ( world, b, Some ( & [ a] ) ) ;
615
+ assert_events (
616
+ world,
617
+ & [ ChildAdded {
618
+ child : a,
619
+ parent : b,
620
+ } ] ,
621
+ ) ;
622
+
623
+ world. entity_mut ( a) . set_parent ( c) ;
624
+
625
+ assert_parent ( world, a, Some ( c) ) ;
626
+ assert_children ( world, b, None ) ;
627
+ assert_children ( world, c, Some ( & [ a] ) ) ;
628
+ assert_events (
629
+ world,
630
+ & [ ChildMoved {
631
+ child : a,
632
+ previous_parent : b,
633
+ new_parent : c,
634
+ } ] ,
635
+ ) ;
636
+ }
637
+
638
+ #[ test]
639
+ fn remove_parent ( ) {
640
+ let world = & mut World :: new ( ) ;
641
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
642
+
643
+ let [ a, b, c] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
644
+
645
+ world. entity_mut ( a) . push_children ( & [ b, c] ) ;
646
+ world. entity_mut ( b) . remove_parent ( ) ;
647
+
648
+ assert_parent ( world, b, None ) ;
649
+ assert_parent ( world, c, Some ( a) ) ;
650
+ assert_children ( world, a, Some ( & [ c] ) ) ;
651
+ omit_events ( world, 2 ) ; // Omit ChildAdded events.
652
+ assert_events (
653
+ world,
654
+ & [ ChildRemoved {
655
+ child : b,
656
+ parent : a,
657
+ } ] ,
658
+ ) ;
659
+
660
+ world. entity_mut ( c) . remove_parent ( ) ;
661
+ assert_parent ( world, c, None ) ;
662
+ assert_children ( world, a, None ) ;
663
+ assert_events (
664
+ world,
665
+ & [ ChildRemoved {
666
+ child : c,
667
+ parent : a,
668
+ } ] ,
669
+ ) ;
670
+ }
671
+
499
672
#[ derive( Component ) ]
500
673
struct C ( u32 ) ;
501
674
0 commit comments