Skip to content

Commit 75690aa

Browse files
author
James Higgins
committed
RemoveChildren command
1 parent 97d8e4e commit 75690aa

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
@@ -46,11 +46,6 @@ pub struct PushChildren {
4646
children: SmallVec<[Entity; 8]>,
4747
}
4848

49-
pub struct ChildBuilder<'a, 'b> {
50-
commands: &'b mut Commands<'a>,
51-
push_children: PushChildren,
52-
}
53-
5449
impl Command for PushChildren {
5550
fn write(self: Box<Self>, world: &mut World) {
5651
for child in self.children.iter() {
@@ -77,6 +72,46 @@ impl Command for PushChildren {
7772
}
7873
}
7974

75+
pub struct RemoveChildren {
76+
parent: Entity,
77+
children: SmallVec<[Entity; 8]>,
78+
}
79+
80+
fn remove_children(parent: Entity, children: &[Entity], world: &mut World) {
81+
for child in children.iter() {
82+
let mut child = world.entity_mut(*child);
83+
let mut remove_parent = false;
84+
if let Some(child_parent) = child.get_mut::<Parent>() {
85+
if child_parent.0 == parent {
86+
remove_parent = true;
87+
}
88+
}
89+
if remove_parent {
90+
if let Some(parent) = child.remove::<Parent>() {
91+
child.insert(PreviousParent(parent.0));
92+
}
93+
}
94+
}
95+
// Remove the children from the parents.
96+
if let Some(mut parent_children) = world.get_mut::<Children>(parent) {
97+
parent_children
98+
.0
99+
.retain(|parent_child| !children.contains(parent_child));
100+
}
101+
}
102+
103+
impl Command for RemoveChildren {
104+
fn write(self: Box<Self>, world: &mut World) {
105+
// Remove any matching Parent components from the children
106+
remove_children(self.parent, &self.children, world);
107+
}
108+
}
109+
110+
pub struct ChildBuilder<'a, 'b> {
111+
commands: &'b mut Commands<'a>,
112+
push_children: PushChildren,
113+
}
114+
80115
impl<'a, 'b> ChildBuilder<'a, 'b> {
81116
pub fn spawn_bundle(&mut self, bundle: impl Bundle) -> EntityCommands<'a, '_> {
82117
let e = self.commands.spawn_bundle(bundle);
@@ -104,6 +139,7 @@ pub trait BuildChildren {
104139
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
105140
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
106141
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
142+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
107143
}
108144

109145
impl<'a, 'b> BuildChildren for EntityCommands<'a, 'b> {
@@ -143,6 +179,15 @@ impl<'a, 'b> BuildChildren for EntityCommands<'a, 'b> {
143179
});
144180
self
145181
}
182+
183+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
184+
let parent = self.id();
185+
self.commands().add(RemoveChildren {
186+
children: SmallVec::from(children),
187+
parent,
188+
});
189+
self
190+
}
146191
}
147192

148193
#[derive(Debug)]
@@ -202,6 +247,7 @@ pub trait BuildWorldChildren {
202247
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
203248
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
204249
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
250+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
205251
}
206252

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

267340
impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
@@ -321,6 +394,15 @@ impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
321394
}
322395
self
323396
}
397+
398+
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
399+
let parent = self
400+
.current_entity
401+
.expect("Cannot remove children without a parent. Try creating an entity first.");
402+
403+
remove_children(parent, children, self.world);
404+
self
405+
}
324406
}
325407

326408
#[cfg(test)]
@@ -367,7 +449,7 @@ mod tests {
367449
}
368450

369451
#[test]
370-
fn push_and_insert_children_commands() {
452+
fn push_and_insert_and_remove_children_commands() {
371453
let mut world = World::default();
372454

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

430535
#[test]
431-
fn push_and_insert_children_world() {
536+
fn push_and_insert_and_remove_children_world() {
432537
let mut world = World::default();
433538

434539
let entities = world
@@ -476,5 +581,23 @@ mod tests {
476581
*world.get::<PreviousParent>(child4).unwrap(),
477582
PreviousParent(parent)
478583
);
584+
585+
let remove_children = [child1, child4];
586+
world.entity_mut(parent).remove_children(&remove_children);
587+
let expected_children: SmallVec<[Entity; 8]> = smallvec![child3, child2];
588+
assert_eq!(
589+
world.get::<Children>(parent).unwrap().0.clone(),
590+
expected_children
591+
);
592+
assert!(world.get::<Parent>(child1).is_none());
593+
assert!(world.get::<Parent>(child4).is_none());
594+
assert_eq!(
595+
*world.get::<PreviousParent>(child1).unwrap(),
596+
PreviousParent(parent)
597+
);
598+
assert_eq!(
599+
*world.get::<PreviousParent>(child4).unwrap(),
600+
PreviousParent(parent)
601+
);
479602
}
480603
}

0 commit comments

Comments
 (0)