1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use shiv::{
hierarchy::{Children, Parent},
query::{Changed, Query, With, Without},
schedule::SystemLabel,
world::Entity,
};
use crate::{GlobalTransform, Transform};
pub fn transform_system(
mut root_query: Query<
(
Entity,
Option<(&Children, Changed<Children>)>,
&Transform,
Changed<Transform>,
&mut GlobalTransform,
),
Without<Parent>,
>,
mut transform_query: Query<(
&Transform,
Changed<Transform>,
&mut GlobalTransform,
&Parent,
)>,
children_query: Query<(&Children, Changed<Children>), (With<Parent>, With<GlobalTransform>)>,
) {
for (entity, children, transform, transform_changed, mut global_transform) in &mut root_query {
let mut changed = transform_changed;
if transform_changed {
*global_transform = transform.into();
}
if let Some((children, children_changed)) = children {
changed |= children_changed;
for &child in children.iter() {
propagate_recursive(
child,
entity,
changed,
*global_transform,
&mut transform_query,
&children_query,
);
}
}
}
}
#[inline]
fn propagate_recursive(
entity: Entity,
expected_parent: Entity,
mut changed: bool,
parent: GlobalTransform,
transform_query: &mut Query<(
&Transform,
Changed<Transform>,
&mut GlobalTransform,
&Parent,
)>,
children_query: &Query<(&Children, Changed<Children>), (With<Parent>, With<GlobalTransform>)>,
) -> Option<()> {
let (&transform, transform_changed, mut global_transform, child_parent) =
transform_query.get_mut(entity)?;
assert_eq!(
child_parent.entity(),
expected_parent,
"Malformed hierarchy"
);
changed |= transform_changed;
if changed {
*global_transform = parent * transform;
}
let global_transform = global_transform.clone();
let (children, children_changed) = children_query.get(entity)?;
changed |= children_changed;
for &child in children.iter() {
propagate_recursive(
child,
entity,
changed,
global_transform,
transform_query,
children_query,
);
}
Some(())
}
#[derive(SystemLabel)]
pub struct TransformSystem;