Skip to content

Commit 0c374df

Browse files
Daviercart
andcommitted
Add insert_children and push_children to EntityMut (#1728)
The only API to add a parent/child relationship between existing entities is through commands, there is no easy way to do it from `World`. Manually inserting the components is not completely possible since `PreviousParent` has no public constructor. This PR adds two methods to set entities as children of an `EntityMut`: `insert_children` and `push_children`. ~~The API is similar to the one on `Commands`, except that the parent is the `EntityMut`.~~ The API is the same as in #1703. However, the `Parent` and `Children` components are defined in `bevy_transform` which depends on `bevy_ecs`, while `EntityMut` is defined in `bevy_ecs`, so the methods are added to the `BuildWorldChildren` trait instead. If #1545 is merged this should be fixed too. I'm aware cart was experimenting with entity hierarchies, but unless it's a coming soon this PR would be useful to have meanwhile. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
1 parent d90d19f commit 0c374df

File tree

1 file changed

+139
-2
lines changed

1 file changed

+139
-2
lines changed

crates/bevy_transform/src/hierarchy/child_builder.rs

+139-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl Command for InsertChildren {
1919
for child in self.children.iter() {
2020
world
2121
.entity_mut(*child)
22+
// FIXME: don't erase the previous parent (see #1545)
2223
.insert_bundle((Parent(self.parent), PreviousParent(self.parent)));
2324
}
2425
{
@@ -55,6 +56,7 @@ impl Command for PushChildren {
5556
for child in self.children.iter() {
5657
world
5758
.entity_mut(*child)
59+
// FIXME: don't erase the previous parent (see #1545)
5860
.insert_bundle((Parent(self.parent), PreviousParent(self.parent)));
5961
}
6062
{
@@ -198,6 +200,8 @@ impl<'w> WorldChildBuilder<'w> {
198200

199201
pub trait BuildWorldChildren {
200202
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
203+
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
204+
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
201205
}
202206

203207
impl<'w> BuildWorldChildren for EntityMut<'w> {
@@ -217,6 +221,47 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
217221
self.update_location();
218222
self
219223
}
224+
225+
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
226+
let parent = self.id();
227+
{
228+
// SAFE: parent entity is not modified
229+
let world = unsafe { self.world_mut() };
230+
for child in children.iter() {
231+
world
232+
.entity_mut(*child)
233+
// FIXME: don't erase the previous parent (see #1545)
234+
.insert_bundle((Parent(parent), PreviousParent(parent)));
235+
}
236+
}
237+
if let Some(mut children_component) = self.get_mut::<Children>() {
238+
children_component.0.extend(children.iter().cloned());
239+
} else {
240+
self.insert(Children::with(children));
241+
}
242+
self
243+
}
244+
245+
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
246+
let parent = self.id();
247+
{
248+
// SAFE: parent entity is not modified
249+
let world = unsafe { self.world_mut() };
250+
for child in children.iter() {
251+
world
252+
.entity_mut(*child)
253+
// FIXME: don't erase the previous parent (see #1545)
254+
.insert_bundle((Parent(parent), PreviousParent(parent)));
255+
}
256+
}
257+
258+
if let Some(mut children_component) = self.get_mut::<Children>() {
259+
children_component.0.insert_from_slice(index, children);
260+
} else {
261+
self.insert(Children::with(children));
262+
}
263+
self
264+
}
220265
}
221266

222267
impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
@@ -235,11 +280,52 @@ impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
235280
self.current_entity = self.parent_entities.pop();
236281
self
237282
}
283+
284+
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
285+
let parent = self
286+
.current_entity
287+
.expect("Cannot add children without a parent. Try creating an entity first.");
288+
for child in children.iter() {
289+
self.world
290+
.entity_mut(*child)
291+
// FIXME: don't erase the previous parent (see #1545)
292+
.insert_bundle((Parent(parent), PreviousParent(parent)));
293+
}
294+
if let Some(mut children_component) = self.world.get_mut::<Children>(parent) {
295+
children_component.0.extend(children.iter().cloned());
296+
} else {
297+
self.world
298+
.entity_mut(parent)
299+
.insert(Children::with(children));
300+
}
301+
self
302+
}
303+
304+
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
305+
let parent = self
306+
.current_entity
307+
.expect("Cannot add children without a parent. Try creating an entity first.");
308+
309+
for child in children.iter() {
310+
self.world
311+
.entity_mut(*child)
312+
// FIXME: don't erase the previous parent (see #1545)
313+
.insert_bundle((Parent(parent), PreviousParent(parent)));
314+
}
315+
if let Some(mut children_component) = self.world.get_mut::<Children>(parent) {
316+
children_component.0.insert_from_slice(index, children);
317+
} else {
318+
self.world
319+
.entity_mut(parent)
320+
.insert(Children::with(children));
321+
}
322+
self
323+
}
238324
}
239325

240326
#[cfg(test)]
241327
mod tests {
242-
use super::BuildChildren;
328+
use super::{BuildChildren, BuildWorldChildren};
243329
use crate::prelude::{Children, Parent, PreviousParent};
244330
use bevy_ecs::{
245331
entity::Entity,
@@ -281,7 +367,7 @@ mod tests {
281367
}
282368

283369
#[test]
284-
fn push_and_insert_children() {
370+
fn push_and_insert_children_commands() {
285371
let mut world = World::default();
286372

287373
let entities = world
@@ -340,4 +426,55 @@ mod tests {
340426
PreviousParent(parent)
341427
);
342428
}
429+
430+
#[test]
431+
fn push_and_insert_children_world() {
432+
let mut world = World::default();
433+
434+
let entities = world
435+
.spawn_batch(vec![(1,), (2,), (3,), (4,), (5,)])
436+
.collect::<Vec<Entity>>();
437+
438+
world.entity_mut(entities[0]).push_children(&entities[1..3]);
439+
440+
let parent = entities[0];
441+
let child1 = entities[1];
442+
let child2 = entities[2];
443+
let child3 = entities[3];
444+
let child4 = entities[4];
445+
446+
let expected_children: SmallVec<[Entity; 8]> = smallvec![child1, child2];
447+
assert_eq!(
448+
world.get::<Children>(parent).unwrap().0.clone(),
449+
expected_children
450+
);
451+
assert_eq!(*world.get::<Parent>(child1).unwrap(), Parent(parent));
452+
assert_eq!(*world.get::<Parent>(child2).unwrap(), Parent(parent));
453+
454+
assert_eq!(
455+
*world.get::<PreviousParent>(child1).unwrap(),
456+
PreviousParent(parent)
457+
);
458+
assert_eq!(
459+
*world.get::<PreviousParent>(child2).unwrap(),
460+
PreviousParent(parent)
461+
);
462+
463+
world.entity_mut(parent).insert_children(1, &entities[3..]);
464+
let expected_children: SmallVec<[Entity; 8]> = smallvec![child1, child3, child4, child2];
465+
assert_eq!(
466+
world.get::<Children>(parent).unwrap().0.clone(),
467+
expected_children
468+
);
469+
assert_eq!(*world.get::<Parent>(child3).unwrap(), Parent(parent));
470+
assert_eq!(*world.get::<Parent>(child4).unwrap(), Parent(parent));
471+
assert_eq!(
472+
*world.get::<PreviousParent>(child3).unwrap(),
473+
PreviousParent(parent)
474+
);
475+
assert_eq!(
476+
*world.get::<PreviousParent>(child4).unwrap(),
477+
PreviousParent(parent)
478+
);
479+
}
343480
}

0 commit comments

Comments
 (0)