1#[derive(Clone, Copy, Debug, Default, PartialEq)]
4pub struct Vec2 {
5 pub x: f64,
6 pub y: f64,
7}
8
9pub fn global_position(tree: &crate::NodeTree, id: &crate::NodeId) -> (f64, f64) {
16 let mut x = 0.0;
17 let mut y = 0.0;
18 let mut cursor = tree.get(id);
19 while let Some(node) = cursor {
20 if let Some(crate::PropValue::Vec2(px, py)) = node.props.get("position") {
21 x += px;
22 y += py;
23 }
24 cursor = node.parent.as_ref().and_then(|p| tree.get(p));
25 }
26 (x, y)
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32 use crate::{NodeDesc, NodeId, NodeTree, PropValue, Props};
33
34 fn placed(id: &str, parent: Option<&str>, pos: Option<(f64, f64)>) -> NodeDesc {
35 let mut d = NodeDesc::new(NodeId::from(id.to_string()), "Node2D");
36 d.name = id.to_string();
37 d.parent = parent.map(|p| NodeId::from(p.to_string()));
38 let mut props = Props::default();
39 if let Some((x, y)) = pos {
40 props.insert("position", PropValue::Vec2(x, y));
41 }
42 d.props = props;
43 d
44 }
45
46 #[test]
47 fn child_follows_moving_parent() {
48 let mut tree = NodeTree::new();
49 tree.insert(placed("root", None, Some((10.0, 0.0))))
50 .unwrap();
51 tree.insert(placed("child", Some("root"), Some((5.0, 0.0))))
52 .unwrap();
53 tree.insert(placed("grand", Some("child"), None)).unwrap();
54 assert_eq!(
55 global_position(&tree, &NodeId::from("grand".to_string())),
56 (15.0, 0.0)
57 );
58 let root_id = NodeId::from("root".to_string());
59 tree.get_mut(&root_id)
60 .unwrap()
61 .props
62 .insert("position", PropValue::Vec2(100.0, 0.0));
63 assert_eq!(
64 global_position(&tree, &NodeId::from("grand".to_string())),
65 (105.0, 0.0)
66 );
67 }
68}