mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 14:10:19 +00:00
Update EntityMut's location in push_children() and insert_children() (#2604)
## Objective This code would result in a crash: ```rust use bevy::prelude::*; fn main() { let mut world = World::new(); let child = world.spawn().id(); world.spawn().push_children(&[child]); } ``` ## Solution Update the `EntityMut`'s location after inserting a component on the children entities, as it may have changed.
This commit is contained in:
parent
90586a4c46
commit
336583a86b
1 changed files with 13 additions and 2 deletions
|
@ -219,7 +219,7 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
|
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||||
let parent = self.id();
|
let parent = self.id();
|
||||||
{
|
{
|
||||||
// SAFE: parent entity is not modified
|
// SAFE: parent entity is not modified and its location is updated manually
|
||||||
let world = unsafe { self.world_mut() };
|
let world = unsafe { self.world_mut() };
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
world
|
world
|
||||||
|
@ -227,6 +227,8 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||||
// FIXME: don't erase the previous parent (see #1545)
|
// FIXME: don't erase the previous parent (see #1545)
|
||||||
.insert_bundle((Parent(parent), PreviousParent(parent)));
|
.insert_bundle((Parent(parent), PreviousParent(parent)));
|
||||||
}
|
}
|
||||||
|
// Inserting a bundle in the children entities may change the parent entity's location if they were of the same archetype
|
||||||
|
self.update_location();
|
||||||
}
|
}
|
||||||
if let Some(mut children_component) = self.get_mut::<Children>() {
|
if let Some(mut children_component) = self.get_mut::<Children>() {
|
||||||
children_component.0.extend(children.iter().cloned());
|
children_component.0.extend(children.iter().cloned());
|
||||||
|
@ -239,7 +241,7 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
|
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
|
||||||
let parent = self.id();
|
let parent = self.id();
|
||||||
{
|
{
|
||||||
// SAFE: parent entity is not modified
|
// SAFE: parent entity is not modified and its location is updated manually
|
||||||
let world = unsafe { self.world_mut() };
|
let world = unsafe { self.world_mut() };
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
world
|
world
|
||||||
|
@ -247,6 +249,8 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
|
||||||
// FIXME: don't erase the previous parent (see #1545)
|
// FIXME: don't erase the previous parent (see #1545)
|
||||||
.insert_bundle((Parent(parent), PreviousParent(parent)));
|
.insert_bundle((Parent(parent), PreviousParent(parent)));
|
||||||
}
|
}
|
||||||
|
// Inserting a bundle in the children entities may change the parent entity's location if they were of the same archetype
|
||||||
|
self.update_location();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut children_component) = self.get_mut::<Children>() {
|
if let Some(mut children_component) = self.get_mut::<Children>() {
|
||||||
|
@ -471,4 +475,11 @@ mod tests {
|
||||||
PreviousParent(parent)
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_push_children_same_archetype() {
|
||||||
|
let mut world = World::new();
|
||||||
|
let child = world.spawn().id();
|
||||||
|
world.spawn().push_children(&[child]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue