Skip to content

Commit aa20565

Browse files
authored
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.
1 parent 94c67af commit aa20565

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

crates/bevy_transform/src/systems.rs

+56-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub fn sync_simple_transforms(
2121
Without<Children>,
2222
),
2323
>,
24-
Query<(Ref<Transform>, &mut GlobalTransform), Without<Children>>,
24+
Query<(Ref<Transform>, &mut GlobalTransform), (Without<Parent>, Without<Children>)>,
2525
)>,
2626
mut orphaned: RemovedComponents<Parent>,
2727
) {
@@ -183,7 +183,7 @@ mod test {
183183
use bevy_app::prelude::*;
184184
use bevy_ecs::prelude::*;
185185
use bevy_ecs::system::CommandQueue;
186-
use bevy_math::vec3;
186+
use bevy_math::{vec3, Vec3};
187187
use bevy_tasks::{ComputeTaskPool, TaskPool};
188188

189189
use crate::components::{GlobalTransform, Transform};
@@ -481,4 +481,58 @@ mod test {
481481

482482
app.update();
483483
}
484+
485+
#[test]
486+
fn global_transform_should_not_be_overwritten_after_reparenting() {
487+
let translation = Vec3::ONE;
488+
let mut world = World::new();
489+
490+
// Create transform propagation schedule
491+
let mut schedule = Schedule::default();
492+
schedule.add_systems((sync_simple_transforms, propagate_transforms));
493+
494+
// Spawn a `TransformBundle` entity with a local translation of `Vec3::ONE`
495+
let mut spawn_transform_bundle = || {
496+
world
497+
.spawn(TransformBundle::from_transform(
498+
Transform::from_translation(translation),
499+
))
500+
.id()
501+
};
502+
503+
// Spawn parent and child with identical transform bundles
504+
let parent = spawn_transform_bundle();
505+
let child = spawn_transform_bundle();
506+
world.entity_mut(parent).add_child(child);
507+
508+
// Run schedule to propagate transforms
509+
schedule.run(&mut world);
510+
511+
// Child should be positioned relative to its parent
512+
let parent_global_transform = *world.entity(parent).get::<GlobalTransform>().unwrap();
513+
let child_global_transform = *world.entity(child).get::<GlobalTransform>().unwrap();
514+
assert!(parent_global_transform
515+
.translation()
516+
.abs_diff_eq(translation, 0.1));
517+
assert!(child_global_transform
518+
.translation()
519+
.abs_diff_eq(2. * translation, 0.1));
520+
521+
// Reparent child
522+
world.entity_mut(child).remove_parent();
523+
world.entity_mut(parent).add_child(child);
524+
525+
// Run schedule to propagate transforms
526+
schedule.run(&mut world);
527+
528+
// Translations should be unchanged after update
529+
assert_eq!(
530+
parent_global_transform,
531+
*world.entity(parent).get::<GlobalTransform>().unwrap()
532+
);
533+
assert_eq!(
534+
child_global_transform,
535+
*world.entity(child).get::<GlobalTransform>().unwrap()
536+
);
537+
}
484538
}

0 commit comments

Comments
 (0)