Skip to content

Commit 23993dc

Browse files
committed
align
1 parent 79b9231 commit 23993dc

File tree

2 files changed

+237
-64
lines changed

2 files changed

+237
-64
lines changed

crates/bevy_hierarchy/src/child_builder.rs

Lines changed: 236 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ fn update_parent(world: &mut World, child: Entity, new_parent: Entity) -> Option
3737
}
3838
}
3939

40+
/// Remove child from the parent's [`Children`] component.
41+
///
42+
/// Removes the [`Children`] component from the parent if it's empty.
4043
fn remove_from_children(world: &mut World, parent: Entity, child: Entity) {
4144
let mut parent = world.entity_mut(parent);
4245
if let Some(mut children) = parent.get_mut::<Children>() {
@@ -47,24 +50,61 @@ fn remove_from_children(world: &mut World, parent: Entity, child: Entity) {
4750
}
4851
}
4952

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.
5088
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) {
5492
// Do nothing if the entity already has the correct parent.
5593
if parent == previous {
5694
continue;
5795
}
5896

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,
62100
previous_parent: previous,
63101
new_parent: parent,
64102
});
103+
} else {
104+
events.push(HierarchyEvent::ChildAdded { child, parent });
65105
}
66106
}
67-
push_events(world, moved);
107+
push_events(world, events);
68108
}
69109

70110
fn remove_children(parent: Entity, children: &[Entity], world: &mut World) {
@@ -108,33 +148,7 @@ pub struct AddChild {
108148

109149
impl Command for AddChild {
110150
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);
138152
}
139153
}
140154

@@ -148,14 +162,9 @@ pub struct InsertChildren {
148162

149163
impl Command for InsertChildren {
150164
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);
159168
}
160169
}
161170

@@ -167,15 +176,8 @@ pub struct PushChildren {
167176
}
168177

169178
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);
179181
}
180182
}
181183

@@ -198,17 +200,7 @@ pub struct RemoveParent {
198200

199201
impl Command for RemoveParent {
200202
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();
212204
}
213205
}
214206

@@ -425,12 +417,28 @@ impl<'w> WorldChildBuilder<'w> {
425417
pub trait BuildWorldChildren {
426418
/// Creates a [`WorldChildBuilder`] with the given children built in the given closure
427419
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+
428428
/// Pushes children to the back of the builder's children
429429
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
430430
/// Inserts children at the given index
431431
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
432432
/// Removes the given children
433433
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;
434442
}
435443

436444
impl<'w> BuildWorldChildren for EntityMut<'w> {
@@ -442,6 +450,20 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
442450
self
443451
}
444452

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+
445467
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
446468
let parent = self.id();
447469
self.world_scope(|world| {
@@ -481,21 +503,172 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
481503
});
482504
self
483505
}
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+
}
484525
}
485526

486527
#[cfg(test)]
487528
mod tests {
488529
use super::{BuildChildren, BuildWorldChildren};
489-
use crate::prelude::{Children, Parent};
530+
use crate::{
531+
components::{Children, Parent},
532+
HierarchyEvent::{self, ChildAdded, ChildMoved, ChildRemoved},
533+
};
490534
use smallvec::{smallvec, SmallVec};
491535

492536
use bevy_ecs::{
493537
component::Component,
494538
entity::Entity,
539+
event::Events,
495540
system::{CommandQueue, Commands},
496541
world::World,
497542
};
498543

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+
499672
#[derive(Component)]
500673
struct C(u32);
501674

0 commit comments

Comments
 (0)