RemoveChildren command (#1925)
This commit is contained in:
parent
081350916c
commit
0936f4ca9d
@ -40,11 +40,6 @@ pub struct PushChildren {
|
||||
children: SmallVec<[Entity; 8]>,
|
||||
}
|
||||
|
||||
pub struct ChildBuilder<'w, 's, 'a> {
|
||||
commands: &'a mut Commands<'w, 's>,
|
||||
push_children: PushChildren,
|
||||
}
|
||||
|
||||
impl Command for PushChildren {
|
||||
fn write(self, world: &mut World) {
|
||||
for child in self.children.iter() {
|
||||
@ -71,6 +66,46 @@ impl Command for PushChildren {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RemoveChildren {
|
||||
parent: Entity,
|
||||
children: SmallVec<[Entity; 8]>,
|
||||
}
|
||||
|
||||
fn remove_children(parent: Entity, children: &[Entity], world: &mut World) {
|
||||
for child in children.iter() {
|
||||
let mut child = world.entity_mut(*child);
|
||||
let mut remove_parent = false;
|
||||
if let Some(child_parent) = child.get_mut::<Parent>() {
|
||||
if child_parent.0 == parent {
|
||||
remove_parent = true;
|
||||
}
|
||||
}
|
||||
if remove_parent {
|
||||
if let Some(parent) = child.remove::<Parent>() {
|
||||
child.insert(PreviousParent(parent.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the children from the parents.
|
||||
if let Some(mut parent_children) = world.get_mut::<Children>(parent) {
|
||||
parent_children
|
||||
.0
|
||||
.retain(|parent_child| !children.contains(parent_child));
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for RemoveChildren {
|
||||
fn write(self, world: &mut World) {
|
||||
// Remove any matching Parent components from the children
|
||||
remove_children(self.parent, &self.children, world);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChildBuilder<'w, 's, 'a> {
|
||||
commands: &'a mut Commands<'w, 's>,
|
||||
push_children: PushChildren,
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
|
||||
pub fn spawn_bundle(&mut self, bundle: impl Bundle) -> EntityCommands<'w, 's, '_> {
|
||||
let e = self.commands.spawn_bundle(bundle);
|
||||
@ -98,6 +133,7 @@ pub trait BuildChildren {
|
||||
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
|
||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
||||
@ -137,6 +173,15 @@ impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||
let parent = self.id();
|
||||
self.commands().add(RemoveChildren {
|
||||
children: SmallVec::from(children),
|
||||
parent,
|
||||
});
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -196,6 +241,7 @@ pub trait BuildWorldChildren {
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
|
||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||
@ -260,6 +306,33 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||
let parent = self.id();
|
||||
// SAFE: This doesn't change the parent's location
|
||||
let world = unsafe { self.world_mut() };
|
||||
for child in children.iter() {
|
||||
let mut child = world.entity_mut(*child);
|
||||
let mut remove_parent = false;
|
||||
if let Some(child_parent) = child.get_mut::<Parent>() {
|
||||
if child_parent.0 == parent {
|
||||
remove_parent = true;
|
||||
}
|
||||
}
|
||||
if remove_parent {
|
||||
if let Some(parent) = child.remove::<Parent>() {
|
||||
child.insert(PreviousParent(parent.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the children from the parents.
|
||||
if let Some(mut parent_children) = world.get_mut::<Children>(parent) {
|
||||
parent_children
|
||||
.0
|
||||
.retain(|parent_child| !children.contains(parent_child));
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
|
||||
@ -319,6 +392,15 @@ impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||
let parent = self
|
||||
.current_entity
|
||||
.expect("Cannot remove children without a parent. Try creating an entity first.");
|
||||
|
||||
remove_children(parent, children, self.world);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -369,7 +451,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_and_insert_children_commands() {
|
||||
fn push_and_insert_and_remove_children_commands() {
|
||||
let mut world = World::default();
|
||||
|
||||
let entities = world
|
||||
@ -427,10 +509,33 @@ mod tests {
|
||||
*world.get::<PreviousParent>(child4).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
|
||||
let remove_children = [child1, child4];
|
||||
{
|
||||
let mut commands = Commands::new(&mut queue, &world);
|
||||
commands.entity(parent).remove_children(&remove_children);
|
||||
}
|
||||
queue.apply(&mut world);
|
||||
|
||||
let expected_children: SmallVec<[Entity; 8]> = smallvec![child3, child2];
|
||||
assert_eq!(
|
||||
world.get::<Children>(parent).unwrap().0.clone(),
|
||||
expected_children
|
||||
);
|
||||
assert!(world.get::<Parent>(child1).is_none());
|
||||
assert!(world.get::<Parent>(child4).is_none());
|
||||
assert_eq!(
|
||||
*world.get::<PreviousParent>(child1).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
assert_eq!(
|
||||
*world.get::<PreviousParent>(child4).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_and_insert_children_world() {
|
||||
fn push_and_insert_and_remove_children_world() {
|
||||
let mut world = World::default();
|
||||
|
||||
let entities = world
|
||||
@ -478,6 +583,24 @@ mod tests {
|
||||
*world.get::<PreviousParent>(child4).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
|
||||
let remove_children = [child1, child4];
|
||||
world.entity_mut(parent).remove_children(&remove_children);
|
||||
let expected_children: SmallVec<[Entity; 8]> = smallvec![child3, child2];
|
||||
assert_eq!(
|
||||
world.get::<Children>(parent).unwrap().0.clone(),
|
||||
expected_children
|
||||
);
|
||||
assert!(world.get::<Parent>(child1).is_none());
|
||||
assert!(world.get::<Parent>(child4).is_none());
|
||||
assert_eq!(
|
||||
*world.get::<PreviousParent>(child1).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
assert_eq!(
|
||||
*world.get::<PreviousParent>(child4).unwrap(),
|
||||
PreviousParent(parent)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user