Skip to main content

gizmo_engine/systems/
transform.rs

1pub struct TransformSyncSystem;
2
3impl gizmo_core::system::System for TransformSyncSystem {
4    fn access_info(&self) -> gizmo_core::system::AccessInfo {
5        let mut info = gizmo_core::system::AccessInfo::new();
6        // Since we borrow components, we can mark it as exclusive to be safe, or specify component access.
7        // For simplicity and safety during hierarchy traversal, we'll make it exclusive.
8        info.is_exclusive = true;
9        info
10    }
11
12    fn run(&mut self, world: &gizmo_core::world::World, _dt: f32) {
13        if let Some(mut transforms) = world.query::<gizmo_core::query::Mut<gizmo_physics_core::Transform>>() {
14            for (_, mut trans) in transforms.iter_mut() {
15                trans.update_local_matrix();
16            }
17        }
18    }
19}
20
21pub struct TransformPropagateSystem;
22
23impl gizmo_core::system::System for TransformPropagateSystem {
24    fn access_info(&self) -> gizmo_core::system::AccessInfo {
25        let mut info = gizmo_core::system::AccessInfo::new();
26        info.is_exclusive = true; // Safe fallback for complex queries
27        info
28    }
29
30    fn run(&mut self, world: &gizmo_core::world::World, _dt: f32) {
31        // Query to get root transforms (no Parent)
32        let root_query = world.query::<(
33            &gizmo_physics_core::Transform,
34            gizmo_core::query::Mut<gizmo_physics_core::components::GlobalTransform>,
35            gizmo_core::query::Without<gizmo_core::component::Parent>,
36        )>();
37
38        let mut queue = Vec::new();
39
40        if let Some(mut roots) = root_query {
41            let mut children_query = world.query::<&gizmo_core::component::Children>();
42            for (id, (local, mut global, _)) in roots.iter_mut() {
43                global.matrix = local.local_matrix;
44                if let Some(children_q) = &mut children_query {
45                    if let Some(children) = children_q.get(id) {
46                        for &child_id in &children.0 {
47                            queue.push((global.matrix, child_id));
48                        }
49                    }
50                }
51            }
52        }
53
54        // Processing children (we need random access, so we do individual queries)
55        let mut local_query = world.query::<&gizmo_physics_core::Transform>();
56        let mut global_query = world.query::<gizmo_core::query::Mut<gizmo_physics_core::components::GlobalTransform>>();
57        let mut children_query = world.query::<&gizmo_core::component::Children>();
58
59        let mut head = 0;
60        while head < queue.len() {
61            let (parent_matrix, current_id) = queue[head];
62            head += 1;
63
64            if let (Some(lq), Some(gq)) = (&mut local_query, &mut global_query) {
65                if let (Some(local), Some(mut global)) = (lq.get(current_id), gq.get(current_id)) {
66                    global.matrix = parent_matrix * local.local_matrix;
67
68                    if let Some(cq) = &mut children_query {
69                        if let Some(children) = cq.get(current_id) {
70                            for &child_id in &children.0 {
71                                queue.push((global.matrix, child_id));
72                            }
73                        }
74                    }
75                }
76            }
77        }
78    }
79}
80
81pub struct BoneAttachmentSystem;
82
83impl gizmo_core::system::System for BoneAttachmentSystem {
84    fn access_info(&self) -> gizmo_core::system::AccessInfo {
85        let mut info = gizmo_core::system::AccessInfo::new();
86        info.is_exclusive = true;
87        info
88    }
89
90    fn run(&mut self, world: &gizmo_core::world::World, _dt: f32) {
91        if let Some(query) = world.query::<&gizmo_renderer::components::BoneAttachment>() {
92            let mut skeletons = world.query::<&gizmo_renderer::components::Skeleton>();
93            let mut transforms = world.query::<gizmo_core::query::Mut<gizmo_physics_core::Transform>>();
94            
95            for (id, attachment) in query.iter() {
96                if let Some(sq) = &mut skeletons {
97                    if let Some(skeleton) = sq.get(attachment.target_entity.id()) {
98                        if let Some(global_matrix) = skeleton.global_poses.get(attachment.bone_index) {
99                            if let Some(tq) = &mut transforms {
100                                if let Some(mut trans) = tq.get(id) {
101                                    let final_mat = *global_matrix * attachment.offset;
102                                    let (t, r, s) = gizmo_renderer::decompose_mat4(final_mat);
103                                    trans.position = t;
104                                    trans.rotation = r;
105                                    trans.scale = s;
106                                    trans.update_local_matrix();
107                                }
108                            }
109                        }
110                    }
111                }
112            }
113        }
114    }
115}