use hecs::*;
struct Parent {
entity: Entity,
from_child: Transform,
}
fn main() {
let mut world = World::new();
let root = world.spawn((Transform(3, 4),));
let _other_root = world.spawn((Transform(1, 2),));
let child = world.spawn((
Parent {
entity: root,
from_child: Transform(1, 1),
},
Transform::default(),
));
let _other_child = world.spawn((
Parent {
entity: root,
from_child: Transform(0, 0),
},
Transform::default(),
));
let grandchild = world.spawn((
Parent {
entity: child,
from_child: Transform(-1, 0),
},
Transform::default(),
));
evaluate_relative_transforms(&mut world);
assert_eq!(*world.get::<&Transform>(child).unwrap(), Transform(4, 5));
assert_eq!(
*world.get::<&Transform>(grandchild).unwrap(),
Transform(3, 5)
);
*world.get::<&mut Transform>(root).unwrap() = Transform(2, 2);
evaluate_relative_transforms(&mut world);
assert_eq!(*world.get::<&Transform>(child).unwrap(), Transform(3, 3));
assert_eq!(
*world.get::<&Transform>(grandchild).unwrap(),
Transform(2, 3)
);
}
fn evaluate_relative_transforms(world: &mut World) {
let mut parents = world.query::<&Parent>();
let parents = parents.view();
let mut roots = world.query::<&Transform>().without::<&Parent>();
let roots = roots.view();
for (parent, absolute) in world.query::<(&Parent, &mut Transform)>().iter() {
let mut relative = parent.from_child;
let mut ancestor = parent.entity;
while let Some(next) = parents.get(ancestor) {
relative = next.from_child * relative;
ancestor = next.entity;
}
*absolute = *roots.get(ancestor).unwrap() * relative;
}
}
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
struct Transform(i32, i32);
impl std::ops::Mul for Transform {
type Output = Transform;
fn mul(self, rhs: Self) -> Transform {
Transform(self.0 + rhs.0, self.1 + rhs.1)
}
}