Add Without<Parent> filter to sync_simple_transforms' orphaned entities query (#9518)

# Objective

`sync_simple_transforms` only checks for removed parents and doesn't
filter for `Without<Parent>`, so it overwrites the `GlobalTransform` of
non-orphan entities that were orphaned and then reparented since the
last update.

Introduced by #7264

## Solution

Filter for `Without<Parent>`.

Fixes #9517, #9492

## Changelog

`sync_simple_transforms`:
* Added a `Without<Parent>` filter to the orphaned entities query.
This commit is contained in:
ickshonpe 2023-08-28 18:29:46 +01:00 committed by GitHub
parent 94c67afa4b
commit aa20565f75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -21,7 +21,7 @@ pub fn sync_simple_transforms(
Without<Children>,
),
>,
Query<(Ref<Transform>, &mut GlobalTransform), Without<Children>>,
Query<(Ref<Transform>, &mut GlobalTransform), (Without<Parent>, Without<Children>)>,
)>,
mut orphaned: RemovedComponents<Parent>,
) {
@ -183,7 +183,7 @@ mod test {
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_ecs::system::CommandQueue;
use bevy_math::vec3;
use bevy_math::{vec3, Vec3};
use bevy_tasks::{ComputeTaskPool, TaskPool};
use crate::components::{GlobalTransform, Transform};
@ -481,4 +481,58 @@ mod test {
app.update();
}
#[test]
fn global_transform_should_not_be_overwritten_after_reparenting() {
let translation = Vec3::ONE;
let mut world = World::new();
// Create transform propagation schedule
let mut schedule = Schedule::default();
schedule.add_systems((sync_simple_transforms, propagate_transforms));
// Spawn a `TransformBundle` entity with a local translation of `Vec3::ONE`
let mut spawn_transform_bundle = || {
world
.spawn(TransformBundle::from_transform(
Transform::from_translation(translation),
))
.id()
};
// Spawn parent and child with identical transform bundles
let parent = spawn_transform_bundle();
let child = spawn_transform_bundle();
world.entity_mut(parent).add_child(child);
// Run schedule to propagate transforms
schedule.run(&mut world);
// Child should be positioned relative to its parent
let parent_global_transform = *world.entity(parent).get::<GlobalTransform>().unwrap();
let child_global_transform = *world.entity(child).get::<GlobalTransform>().unwrap();
assert!(parent_global_transform
.translation()
.abs_diff_eq(translation, 0.1));
assert!(child_global_transform
.translation()
.abs_diff_eq(2. * translation, 0.1));
// Reparent child
world.entity_mut(child).remove_parent();
world.entity_mut(parent).add_child(child);
// Run schedule to propagate transforms
schedule.run(&mut world);
// Translations should be unchanged after update
assert_eq!(
parent_global_transform,
*world.entity(parent).get::<GlobalTransform>().unwrap()
);
assert_eq!(
child_global_transform,
*world.entity(child).get::<GlobalTransform>().unwrap()
);
}
}