Skip to content

Commit

Permalink
Add Without<Parent> filter to sync_simple_transforms' orphaned en…
Browse files Browse the repository at this point in the history
…tities 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.
  • Loading branch information
ickshonpe committed Aug 28, 2023
1 parent 94c67af commit aa20565
Showing 1 changed file with 56 additions and 2 deletions.
58 changes: 56 additions & 2 deletions crates/bevy_transform/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
) {
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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()
);
}
}

0 comments on commit aa20565

Please sign in to comment.