use bevy_ecs::prelude::*;
use bevy_entity_ptr::{EntityHandle, EntityPtr, WorldExt};
#[derive(Component)]
struct Name(&'static str);
#[derive(Component)]
struct Value(i32);
#[derive(Component)]
struct Parent(EntityHandle);
#[derive(Component)]
struct Children(Vec<EntityHandle>);
fn sum_tree(node: EntityPtr) -> i32 {
let my_value = node.get::<Value>().map(|v| v.0).unwrap_or(0);
let children_sum: i32 = node
.get::<Children>()
.map(|c| c.0.iter().map(|h| sum_tree(node.follow_handle(*h))).sum())
.unwrap_or(0);
my_value + children_sum
}
fn find_root(node: EntityPtr) -> EntityPtr {
match node.follow::<Parent, _>(|p| p.0) {
Some(parent) => find_root(parent),
None => node,
}
}
fn tree_depth(node: EntityPtr) -> usize {
node.get::<Children>()
.map(|c| {
c.0.iter()
.map(|h| tree_depth(node.follow_handle(*h)))
.max()
.unwrap_or(0)
+ 1
})
.unwrap_or(0)
}
fn collect_names(node: EntityPtr, names: &mut Vec<&'static str>) {
if let Some(name) = node.get::<Name>() {
names.push(name.0);
}
if let Some(children) = node.get::<Children>() {
for child_handle in &children.0 {
collect_names(node.follow_handle(*child_handle), names);
}
}
}
fn main() {
let mut world = World::new();
println!("Building tree structure...\n");
let d = world.spawn((Name("d"), Value(7))).id();
let c = world
.spawn((Name("c"), Value(2), Children(vec![EntityHandle::new(d)])))
.id();
world.entity_mut(d).insert(Parent(EntityHandle::new(c)));
let a = world
.spawn((Name("a"), Value(5), Children(vec![EntityHandle::new(c)])))
.id();
world.entity_mut(c).insert(Parent(EntityHandle::new(a)));
let b = world.spawn((Name("b"), Value(3))).id();
let root = world
.spawn((
Name("root"),
Value(10),
Children(vec![EntityHandle::new(a), EntityHandle::new(b)]),
))
.id();
world.entity_mut(a).insert(Parent(EntityHandle::new(root)));
world.entity_mut(b).insert(Parent(EntityHandle::new(root)));
let root_ptr = world.entity_ptr(root);
let total = sum_tree(root_ptr);
println!("Sum of all values in tree: {}", total);
println!(" Expected: 10 + 5 + 2 + 7 + 3 = 27");
assert_eq!(total, 27);
let d_ptr = world.entity_ptr(d);
let found_root = find_root(d_ptr);
let root_name = found_root.get::<Name>().unwrap().0;
println!("\nFinding root from node 'd': {}", root_name);
assert_eq!(root_name, "root");
let b_ptr = world.entity_ptr(b);
let found_root = find_root(b_ptr);
let root_name = found_root.get::<Name>().unwrap().0;
println!("Finding root from node 'b': {}", root_name);
assert_eq!(root_name, "root");
let depth = tree_depth(root_ptr);
println!("\nTree depth from root: {}", depth);
println!(" Expected: 3 (root->a, a->c, c->d = 3 edges)");
assert_eq!(depth, 3);
let a_ptr = world.entity_ptr(a);
let a_depth = tree_depth(a_ptr);
println!("Subtree depth from 'a': {}", a_depth);
assert_eq!(a_depth, 2);
let mut names = Vec::new();
collect_names(root_ptr, &mut names);
println!("\nPre-order traversal: {:?}", names);
assert_eq!(names, vec!["root", "a", "c", "d", "b"]);
println!("\nAll assertions passed!");
}