Skip to content

Commit f7f3e17

Browse files
committed
Also fix for entities without children
1 parent f19db01 commit f7f3e17

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

crates/bevy_transform/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub enum TransformSystem {
8686
pub fn transform_propagate_system_set() -> SystemSet {
8787
SystemSet::new()
8888
.with_system(systems::sync_simple_transforms)
89+
.with_system(systems::sync_simple_transforms_orphaned)
8990
.with_system(systems::propagate_transforms)
9091
}
9192

@@ -103,6 +104,10 @@ impl Plugin for TransformPlugin {
103104
StartupStage::PostStartup,
104105
systems::sync_simple_transforms.label(TransformSystem::TransformPropagate),
105106
)
107+
.add_startup_system_to_stage(
108+
StartupStage::PostStartup,
109+
systems::sync_simple_transforms_orphaned.label(TransformSystem::TransformPropagate),
110+
)
106111
.add_startup_system_to_stage(
107112
StartupStage::PostStartup,
108113
systems::propagate_transforms.label(TransformSystem::TransformPropagate),
@@ -111,6 +116,10 @@ impl Plugin for TransformPlugin {
111116
CoreStage::PostUpdate,
112117
systems::sync_simple_transforms.label(TransformSystem::TransformPropagate),
113118
)
119+
.add_system_to_stage(
120+
CoreStage::PostUpdate,
121+
systems::sync_simple_transforms_orphaned.label(TransformSystem::TransformPropagate),
122+
)
114123
.add_system_to_stage(
115124
CoreStage::PostUpdate,
116125
systems::propagate_transforms.label(TransformSystem::TransformPropagate),

crates/bevy_transform/src/systems.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ pub fn sync_simple_transforms(
2020
*global_transform = GlobalTransform::from(*transform);
2121
});
2222
}
23+
/// Update [`GlobalTransform`] component of entities that aren't in the hierarchy
24+
/// and lost their parent last frame.
25+
///
26+
/// Third party plugins should use [`transform_propagate_system_set`](crate::transform_propagate_system_set)
27+
/// to propagate transforms correctly.
28+
pub fn sync_simple_transforms_orphaned(
29+
mut query: Query<(&Transform, &mut GlobalTransform), Without<Children>>,
30+
changed: Query<(), Changed<Transform>>,
31+
orphaned: RemovedComponents<Parent>,
32+
) {
33+
let mut iter = query.iter_many_mut(orphaned.iter().filter(|e| !changed.contains(*e)));
34+
while let Some((transform, mut global_transform)) = iter.fetch_next() {
35+
*global_transform = GlobalTransform::from(*transform);
36+
}
37+
}
2338

2439
/// Update [`GlobalTransform`] component of entities based on entity hierarchy and
2540
/// [`Transform`] component.
@@ -181,6 +196,10 @@ mod test {
181196
fn correct_parent_removed() {
182197
ComputeTaskPool::init(TaskPool::default);
183198
let mut world = World::default();
199+
let offset_global_transform =
200+
|offset| GlobalTransform::from(Transform::from_xyz(offset, offset, offset));
201+
let offset_transform =
202+
|offset| TransformBundle::from_transform(Transform::from_xyz(offset, offset, offset));
184203

185204
let mut update_stage = SystemStage::parallel();
186205
update_stage.add_system_set(transform_propagate_system_set());
@@ -190,13 +209,9 @@ mod test {
190209

191210
let mut command_queue = CommandQueue::default();
192211
let mut commands = Commands::new(&mut command_queue, &world);
193-
let root = commands
194-
.spawn(TransformBundle::from_transform(Transform::from_xyz(
195-
9.9, 9.9, 9.9,
196-
)))
197-
.id();
198-
let parent = commands.spawn(TransformBundle::IDENTITY).id();
199-
let child = commands.spawn(TransformBundle::IDENTITY).id();
212+
let root = commands.spawn(offset_transform(3.3)).id();
213+
let parent = commands.spawn(offset_transform(4.4)).id();
214+
let child = commands.spawn(offset_transform(5.5)).id();
200215
commands.entity(parent).set_parent(root);
201216
commands.entity(child).set_parent(parent);
202217
command_queue.apply(&mut world);
@@ -216,7 +231,19 @@ mod test {
216231

217232
assert_eq!(
218233
world.get::<GlobalTransform>(parent).unwrap(),
219-
&GlobalTransform::from(Transform::IDENTITY)
234+
&offset_global_transform(4.4)
235+
);
236+
237+
// Remove parent of `child`
238+
let mut command_queue = CommandQueue::default();
239+
let mut commands = Commands::new(&mut command_queue, &world);
240+
commands.entity(child).remove_parent();
241+
command_queue.apply(&mut world);
242+
schedule.run(&mut world);
243+
244+
assert_eq!(
245+
world.get::<GlobalTransform>(child).unwrap(),
246+
&offset_global_transform(5.5)
220247
);
221248
}
222249

0 commit comments

Comments
 (0)