Skip to content

Commit 0936f4c

Browse files
author
James Higgins
committed
RemoveChildren command (#1925)
1 parent 0813509 commit 0936f4c

File tree

1 file changed

+130
-7
lines changed

1 file changed

+130
-7
lines changed

crates/bevy_transform/src/hierarchy/child_builder.rs

Lines changed: 130 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ pub struct PushChildren {
4040
children: SmallVec<[Entity; 8]>,
4141
}
4242

43-
pub struct ChildBuilder<'w, 's, 'a> {
44-
commands: &'a mut Commands<'w, 's>,
45-
push_children: PushChildren,
46-
}
47-
4843
impl Command for PushChildren {
4944
fn write(self, world: &mut World) {
5045
for child in self.children.iter() {
@@ -71,6 +66,46 @@ impl Command for PushChildren {
7166
}
7267
}
7368

69+
pub struct RemoveChildren {
70+
parent: Entity,
71+
children: SmallVec<[Entity; 8]>,
72+
}
73+
74+
fn remove_children(parent: Entity, children: &[Entity], world: &mut World) {
75+
for child in children.iter() {
76+
let mut child = world.entity_mut(*child);
77+
let mut remove_parent = false;
78+
if let Some(child_parent) = child.get_mut::<Parent>() {
79+
if child_parent.0 == parent {
80+
remove_parent = true;
81+
}
82+
}
83+
if remove_parent {
84+
if let Some(parent) = child.remove::<Parent>() {
85+
child.insert(PreviousParent(parent.0));
86+
}
87+
}
88+
}
89+
// Remove the children from the parents.
90+
if let Some(mut parent_children) = world.get_mut::<Children>(parent) {
91+
parent_children
92+
.0
93+
.retain(|parent_child| !children.contains(parent_child));
94+
}
95+
}
96+
97+
impl Command for RemoveChildren {
98+
fn write(self, world: &mut World) {
99+
// Remove any matching Parent components from the children
100+
remove_children(self.parent, &self.children, world);
101+
}
102+
}
103+
104+
pub struct ChildBuilder<'w, 's, 'a> {
105+
commands: &'a mut Commands<'w, 's>,
106+
push_children: PushChildren,
107+
}
108+
74109
impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
75110
pub fn spawn_bundle(&mut self, bundle: impl Bundle) -> EntityCommands<'w, 's, '_> {
76111
let e = self.commands.spawn_bundle(bundle);
@@ -98,6 +133,7 @@ pub trait BuildChildren {
98133
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
99134
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
100135
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
136+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
101137
}
102138

103139
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
@@ -137,6 +173,15 @@ impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
137173
});
138174
self
139175
}
176+
177+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
178+
let parent = self.id();
179+
self.commands().add(RemoveChildren {
180+
children: SmallVec::from(children),
181+
parent,
182+
});
183+
self
184+
}
140185
}
141186

142187
#[derive(Debug)]
@@ -196,6 +241,7 @@ pub trait BuildWorldChildren {
196241
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
197242
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
198243
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
244+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
199245
}
200246

201247
impl<'w> BuildWorldChildren for EntityMut<'w> {
@@ -260,6 +306,33 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
260306
}
261307
self
262308
}
309+
310+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
311+
let parent = self.id();
312+
// SAFE: This doesn't change the parent's location
313+
let world = unsafe { self.world_mut() };
314+
for child in children.iter() {
315+
let mut child = world.entity_mut(*child);
316+
let mut remove_parent = false;
317+
if let Some(child_parent) = child.get_mut::<Parent>() {
318+
if child_parent.0 == parent {
319+
remove_parent = true;
320+
}
321+
}
322+
if remove_parent {
323+
if let Some(parent) = child.remove::<Parent>() {
324+
child.insert(PreviousParent(parent.0));
325+
}
326+
}
327+
}
328+
// Remove the children from the parents.
329+
if let Some(mut parent_children) = world.get_mut::<Children>(parent) {
330+
parent_children
331+
.0
332+
.retain(|parent_child| !children.contains(parent_child));
333+
}
334+
self
335+
}
263336
}
264337

265338
impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
@@ -319,6 +392,15 @@ impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
319392
}
320393
self
321394
}
395+
396+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
397+
let parent = self
398+
.current_entity
399+
.expect("Cannot remove children without a parent. Try creating an entity first.");
400+
401+
remove_children(parent, children, self.world);
402+
self
403+
}
322404
}
323405

324406
#[cfg(test)]
@@ -369,7 +451,7 @@ mod tests {
369451
}
370452

371453
#[test]
372-
fn push_and_insert_children_commands() {
454+
fn push_and_insert_and_remove_children_commands() {
373455
let mut world = World::default();
374456

375457
let entities = world
@@ -427,10 +509,33 @@ mod tests {
427509
*world.get::<PreviousParent>(child4).unwrap(),
428510
PreviousParent(parent)
429511
);
512+
513+
let remove_children = [child1, child4];
514+
{
515+
let mut commands = Commands::new(&mut queue, &world);
516+
commands.entity(parent).remove_children(&remove_children);
517+
}
518+
queue.apply(&mut world);
519+
520+
let expected_children: SmallVec<[Entity; 8]> = smallvec![child3, child2];
521+
assert_eq!(
522+
world.get::<Children>(parent).unwrap().0.clone(),
523+
expected_children
524+
);
525+
assert!(world.get::<Parent>(child1).is_none());
526+
assert!(world.get::<Parent>(child4).is_none());
527+
assert_eq!(
528+
*world.get::<PreviousParent>(child1).unwrap(),
529+
PreviousParent(parent)
530+
);
531+
assert_eq!(
532+
*world.get::<PreviousParent>(child4).unwrap(),
533+
PreviousParent(parent)
534+
);
430535
}
431536

432537
#[test]
433-
fn push_and_insert_children_world() {
538+
fn push_and_insert_and_remove_children_world() {
434539
let mut world = World::default();
435540

436541
let entities = world
@@ -478,6 +583,24 @@ mod tests {
478583
*world.get::<PreviousParent>(child4).unwrap(),
479584
PreviousParent(parent)
480585
);
586+
587+
let remove_children = [child1, child4];
588+
world.entity_mut(parent).remove_children(&remove_children);
589+
let expected_children: SmallVec<[Entity; 8]> = smallvec![child3, child2];
590+
assert_eq!(
591+
world.get::<Children>(parent).unwrap().0.clone(),
592+
expected_children
593+
);
594+
assert!(world.get::<Parent>(child1).is_none());
595+
assert!(world.get::<Parent>(child4).is_none());
596+
assert_eq!(
597+
*world.get::<PreviousParent>(child1).unwrap(),
598+
PreviousParent(parent)
599+
);
600+
assert_eq!(
601+
*world.get::<PreviousParent>(child4).unwrap(),
602+
PreviousParent(parent)
603+
);
481604
}
482605

483606
#[test]

0 commit comments

Comments
 (0)