@@ -28,6 +28,9 @@ fn update_parent(world: &mut World, child: Entity, new_parent: Entity) -> Option
28
28
}
29
29
}
30
30
31
+ /// Remove child from the parent's [`Children`] component.
32
+ ///
33
+ /// Removes the [`Children`] component from the parent if it's empty.
31
34
fn remove_from_children ( world : & mut World , parent : Entity , child : Entity ) {
32
35
let mut parent = world. entity_mut ( parent) ;
33
36
if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
@@ -38,24 +41,61 @@ fn remove_from_children(world: &mut World, parent: Entity, child: Entity) {
38
41
}
39
42
}
40
43
44
+ /// Update the [`Parent`] component of the `child`.
45
+ /// Removes the `child` from the previous parent's [`Children`].
46
+ ///
47
+ /// Does not update the new parents [`Children`] component.
48
+ ///
49
+ /// Does nothing if `child` was already a child of `parent`.
50
+ ///
51
+ /// Sends [`HierarchyEvent`]'s.
52
+ fn update_old_parent ( world : & mut World , child : Entity , parent : Entity ) {
53
+ let previous = update_parent ( world, child, parent) ;
54
+ if let Some ( previous_parent) = previous {
55
+ // Do nothing if the child was already parented to this entity.
56
+ if previous_parent == parent {
57
+ return ;
58
+ }
59
+ remove_from_children ( world, previous_parent, child) ;
60
+
61
+ world. send_event ( HierarchyEvent :: ChildMoved {
62
+ child,
63
+ previous_parent,
64
+ new_parent : parent,
65
+ } ) ;
66
+ } else {
67
+ world. send_event ( HierarchyEvent :: ChildAdded { child, parent } ) ;
68
+ }
69
+ }
70
+
71
+ /// Update the [`Parent`] components of the `children`.
72
+ /// Removes the `children` from their previous parent's [`Children`].
73
+ ///
74
+ /// Does not update the new parents [`Children`] component.
75
+ ///
76
+ /// Does nothing for a child if it was already a child of `parent`.
77
+ ///
78
+ /// Sends [`HierarchyEvent`]'s.
41
79
fn update_old_parents ( world : & mut World , parent : Entity , children : & [ Entity ] ) {
42
- let mut moved : SmallVec < [ HierarchyEvent ; 8 ] > = SmallVec :: with_capacity ( children. len ( ) ) ;
43
- for child in children {
44
- if let Some ( previous) = update_parent ( world, * child, parent) {
80
+ let mut events : SmallVec < [ HierarchyEvent ; 8 ] > = SmallVec :: with_capacity ( children. len ( ) ) ;
81
+ for & child in children {
82
+ if let Some ( previous) = update_parent ( world, child, parent) {
45
83
// Do nothing if the entity already has the correct parent.
46
84
if parent == previous {
47
85
continue ;
48
86
}
49
87
50
- remove_from_children ( world, previous, * child) ;
51
- moved . push ( HierarchyEvent :: ChildMoved {
52
- child : * child ,
88
+ remove_from_children ( world, previous, child) ;
89
+ events . push ( HierarchyEvent :: ChildMoved {
90
+ child,
53
91
previous_parent : previous,
54
92
new_parent : parent,
55
93
} ) ;
94
+ } else {
95
+ events. push ( HierarchyEvent :: ChildAdded { child, parent } ) ;
56
96
}
57
97
}
58
- world. send_event_batch ( moved ) ;
98
+ world. send_event_batch ( events ) ;
59
99
}
60
100
61
101
fn remove_children ( parent : Entity , children : & [ Entity ] , world : & mut World ) {
@@ -99,30 +139,7 @@ pub struct AddChild {
99
139
100
140
impl Command for AddChild {
101
141
fn write ( self , world : & mut World ) {
102
- let previous = update_parent ( world, self . child , self . parent ) ;
103
- if let Some ( previous) = previous {
104
- if previous == self . parent {
105
- return ;
106
- }
107
- remove_from_children ( world, previous, self . child ) ;
108
- world. send_event ( HierarchyEvent :: ChildMoved {
109
- child : self . child ,
110
- previous_parent : previous,
111
- new_parent : self . parent ,
112
- } ) ;
113
- }
114
- world. send_event ( HierarchyEvent :: ChildAdded {
115
- child : self . child ,
116
- parent : self . parent ,
117
- } ) ;
118
- let mut parent = world. entity_mut ( self . parent ) ;
119
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
120
- if !children. contains ( & self . child ) {
121
- children. 0 . push ( self . child ) ;
122
- }
123
- } else {
124
- parent. insert ( Children ( smallvec:: smallvec![ self . child] ) ) ;
125
- }
142
+ world. entity_mut ( self . parent ) . add_child ( self . child ) ;
126
143
}
127
144
}
128
145
@@ -136,14 +153,9 @@ pub struct InsertChildren {
136
153
137
154
impl Command for InsertChildren {
138
155
fn write ( self , world : & mut World ) {
139
- update_old_parents ( world, self . parent , & self . children ) ;
140
- let mut parent = world. entity_mut ( self . parent ) ;
141
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
142
- children. 0 . retain ( |value| !self . children . contains ( value) ) ;
143
- children. 0 . insert_from_slice ( self . index , & self . children ) ;
144
- } else {
145
- parent. insert ( Children ( self . children ) ) ;
146
- }
156
+ world
157
+ . entity_mut ( self . parent )
158
+ . insert_children ( self . index , & self . children ) ;
147
159
}
148
160
}
149
161
@@ -155,15 +167,8 @@ pub struct PushChildren {
155
167
}
156
168
157
169
impl Command for PushChildren {
158
- fn write ( mut self , world : & mut World ) {
159
- update_old_parents ( world, self . parent , & self . children ) ;
160
- let mut parent = world. entity_mut ( self . parent ) ;
161
- if let Some ( mut children) = parent. get_mut :: < Children > ( ) {
162
- children. 0 . retain ( |child| !self . children . contains ( child) ) ;
163
- children. 0 . append ( & mut self . children ) ;
164
- } else {
165
- parent. insert ( Children ( self . children ) ) ;
166
- }
170
+ fn write ( self , world : & mut World ) {
171
+ world. entity_mut ( self . parent ) . push_children ( & self . children ) ;
167
172
}
168
173
}
169
174
@@ -186,15 +191,7 @@ pub struct RemoveParent {
186
191
187
192
impl Command for RemoveParent {
188
193
fn write ( self , world : & mut World ) {
189
- if let Some ( parent) = world. get :: < Parent > ( self . child ) {
190
- let parent_entity = parent. get ( ) ;
191
- remove_from_children ( world, parent_entity, self . child ) ;
192
- world. entity_mut ( self . child ) . remove :: < Parent > ( ) ;
193
- world. send_event ( HierarchyEvent :: ChildRemoved {
194
- child : self . child ,
195
- parent : parent_entity,
196
- } ) ;
197
- }
194
+ world. entity_mut ( self . child ) . remove_parent ( ) ;
198
195
}
199
196
}
200
197
@@ -368,12 +365,28 @@ impl<'w> WorldChildBuilder<'w> {
368
365
pub trait BuildWorldChildren {
369
366
/// Creates a [`WorldChildBuilder`] with the given children built in the given closure
370
367
fn with_children ( & mut self , spawn_children : impl FnOnce ( & mut WorldChildBuilder ) ) -> & mut Self ;
368
+
369
+ /// Adds a single child
370
+ ///
371
+ /// If the children were previously children of another parent, that parent's [`Children`] component
372
+ /// will have those children removed from its list. Removing all children from a parent causes its
373
+ /// [`Children`] component to be removed from the entity.
374
+ fn add_child ( & mut self , child : Entity ) -> & mut Self ;
375
+
371
376
/// Pushes children to the back of the builder's children
372
377
fn push_children ( & mut self , children : & [ Entity ] ) -> & mut Self ;
373
378
/// Inserts children at the given index
374
379
fn insert_children ( & mut self , index : usize , children : & [ Entity ] ) -> & mut Self ;
375
380
/// Removes the given children
376
381
fn remove_children ( & mut self , children : & [ Entity ] ) -> & mut Self ;
382
+
383
+ /// Set the `parent` of this entity. This entity will be added to the end of the `parent`'s list of children.
384
+ ///
385
+ /// If this entity already had a parent it will be removed from it.
386
+ fn set_parent ( & mut self , parent : Entity ) -> & mut Self ;
387
+
388
+ /// Remove the parent from this entity.
389
+ fn remove_parent ( & mut self ) -> & mut Self ;
377
390
}
378
391
379
392
impl < ' w > BuildWorldChildren for EntityMut < ' w > {
@@ -385,6 +398,20 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
385
398
self
386
399
}
387
400
401
+ fn add_child ( & mut self , child : Entity ) -> & mut Self {
402
+ let parent = self . id ( ) ;
403
+ self . world_scope ( |world| {
404
+ update_old_parent ( world, child, parent) ;
405
+ } ) ;
406
+ if let Some ( mut children_component) = self . get_mut :: < Children > ( ) {
407
+ children_component. 0 . retain ( |value| child != * value) ;
408
+ children_component. 0 . push ( child) ;
409
+ } else {
410
+ self . insert ( Children :: from_entities ( & [ child] ) ) ;
411
+ }
412
+ self
413
+ }
414
+
388
415
fn push_children ( & mut self , children : & [ Entity ] ) -> & mut Self {
389
416
let parent = self . id ( ) ;
390
417
self . world_scope ( |world| {
@@ -424,21 +451,172 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
424
451
} ) ;
425
452
self
426
453
}
454
+
455
+ fn set_parent ( & mut self , parent : Entity ) -> & mut Self {
456
+ let child = self . id ( ) ;
457
+ self . world_scope ( |world| {
458
+ world. entity_mut ( parent) . add_child ( child) ;
459
+ } ) ;
460
+ self
461
+ }
462
+
463
+ fn remove_parent ( & mut self ) -> & mut Self {
464
+ let child = self . id ( ) ;
465
+ if let Some ( parent) = self . remove :: < Parent > ( ) . map ( |p| p. get ( ) ) {
466
+ self . world_scope ( |world| {
467
+ remove_from_children ( world, parent, child) ;
468
+ world. send_event ( HierarchyEvent :: ChildRemoved { child, parent } ) ;
469
+ } ) ;
470
+ }
471
+ self
472
+ }
427
473
}
428
474
429
475
#[ cfg( test) ]
430
476
mod tests {
431
477
use super :: { BuildChildren , BuildWorldChildren } ;
432
- use crate :: prelude:: { Children , Parent } ;
478
+ use crate :: {
479
+ components:: { Children , Parent } ,
480
+ HierarchyEvent :: { self , ChildAdded , ChildMoved , ChildRemoved } ,
481
+ } ;
433
482
use smallvec:: { smallvec, SmallVec } ;
434
483
435
484
use bevy_ecs:: {
436
485
component:: Component ,
437
486
entity:: Entity ,
487
+ event:: Events ,
438
488
system:: { CommandQueue , Commands } ,
439
489
world:: World ,
440
490
} ;
441
491
492
+ /// Assert the (non)existence and state of the child's [`Parent`] component.
493
+ fn assert_parent ( world : & mut World , child : Entity , parent : Option < Entity > ) {
494
+ assert_eq ! ( world. get:: <Parent >( child) . map( |p| p. get( ) ) , parent) ;
495
+ }
496
+
497
+ /// Assert the (non)existence and state of the parent's [`Children`] component.
498
+ fn assert_children ( world : & mut World , parent : Entity , children : Option < & [ Entity ] > ) {
499
+ assert_eq ! ( world. get:: <Children >( parent) . map( |c| & * * c) , children) ;
500
+ }
501
+
502
+ /// Used to omit a number of events that are not relevant to a particular test.
503
+ fn omit_events ( world : & mut World , number : usize ) {
504
+ let mut events_resource = world. resource_mut :: < Events < HierarchyEvent > > ( ) ;
505
+ let mut events: Vec < _ > = events_resource. drain ( ) . collect ( ) ;
506
+ events_resource. extend ( events. drain ( number..) ) ;
507
+ }
508
+
509
+ fn assert_events ( world : & mut World , expected_events : & [ HierarchyEvent ] ) {
510
+ let events: Vec < _ > = world
511
+ . resource_mut :: < Events < HierarchyEvent > > ( )
512
+ . drain ( )
513
+ . collect ( ) ;
514
+ assert_eq ! ( events, expected_events) ;
515
+ }
516
+
517
+ #[ test]
518
+ fn add_child ( ) {
519
+ let world = & mut World :: new ( ) ;
520
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
521
+
522
+ let [ a, b, c, d] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
523
+
524
+ world. entity_mut ( a) . add_child ( b) ;
525
+
526
+ assert_parent ( world, b, Some ( a) ) ;
527
+ assert_children ( world, a, Some ( & [ b] ) ) ;
528
+ assert_events (
529
+ world,
530
+ & [ ChildAdded {
531
+ child : b,
532
+ parent : a,
533
+ } ] ,
534
+ ) ;
535
+
536
+ world. entity_mut ( a) . add_child ( c) ;
537
+
538
+ assert_children ( world, a, Some ( & [ b, c] ) ) ;
539
+ assert_parent ( world, c, Some ( a) ) ;
540
+ assert_events (
541
+ world,
542
+ & [ ChildAdded {
543
+ child : c,
544
+ parent : a,
545
+ } ] ,
546
+ ) ;
547
+ // Children component should be removed when it's empty.
548
+ world. entity_mut ( d) . add_child ( b) . add_child ( c) ;
549
+ assert_children ( world, a, None ) ;
550
+ }
551
+
552
+ #[ test]
553
+ fn set_parent ( ) {
554
+ let world = & mut World :: new ( ) ;
555
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
556
+
557
+ let [ a, b, c] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
558
+
559
+ world. entity_mut ( a) . set_parent ( b) ;
560
+
561
+ assert_parent ( world, a, Some ( b) ) ;
562
+ assert_children ( world, b, Some ( & [ a] ) ) ;
563
+ assert_events (
564
+ world,
565
+ & [ ChildAdded {
566
+ child : a,
567
+ parent : b,
568
+ } ] ,
569
+ ) ;
570
+
571
+ world. entity_mut ( a) . set_parent ( c) ;
572
+
573
+ assert_parent ( world, a, Some ( c) ) ;
574
+ assert_children ( world, b, None ) ;
575
+ assert_children ( world, c, Some ( & [ a] ) ) ;
576
+ assert_events (
577
+ world,
578
+ & [ ChildMoved {
579
+ child : a,
580
+ previous_parent : b,
581
+ new_parent : c,
582
+ } ] ,
583
+ ) ;
584
+ }
585
+
586
+ #[ test]
587
+ fn remove_parent ( ) {
588
+ let world = & mut World :: new ( ) ;
589
+ world. insert_resource ( Events :: < HierarchyEvent > :: default ( ) ) ;
590
+
591
+ let [ a, b, c] = std:: array:: from_fn ( |_| world. spawn_empty ( ) . id ( ) ) ;
592
+
593
+ world. entity_mut ( a) . push_children ( & [ b, c] ) ;
594
+ world. entity_mut ( b) . remove_parent ( ) ;
595
+
596
+ assert_parent ( world, b, None ) ;
597
+ assert_parent ( world, c, Some ( a) ) ;
598
+ assert_children ( world, a, Some ( & [ c] ) ) ;
599
+ omit_events ( world, 2 ) ; // Omit ChildAdded events.
600
+ assert_events (
601
+ world,
602
+ & [ ChildRemoved {
603
+ child : b,
604
+ parent : a,
605
+ } ] ,
606
+ ) ;
607
+
608
+ world. entity_mut ( c) . remove_parent ( ) ;
609
+ assert_parent ( world, c, None ) ;
610
+ assert_children ( world, a, None ) ;
611
+ assert_events (
612
+ world,
613
+ & [ ChildRemoved {
614
+ child : c,
615
+ parent : a,
616
+ } ] ,
617
+ ) ;
618
+ }
619
+
442
620
#[ derive( Component ) ]
443
621
struct C ( u32 ) ;
444
622
0 commit comments