use crate::handle::EntityHandle;
pub trait HasParent {
fn parent_handle(&self) -> Option<EntityHandle>;
}
pub trait HasChildren {
fn children_handles(&self) -> &[EntityHandle];
}
use crate::handle::{BoundEntity, BoundEntityNav};
impl<'w> BoundEntityNav<'w> {
#[inline]
pub fn parent<T: bevy_ecs::component::Component + HasParent>(self) -> Option<BoundEntity<'w>> {
self.0.get::<T>().and_then(|c| {
c.parent_handle()
.map(|h| BoundEntity::new(h.entity(), self.0.world()))
})
}
#[inline]
pub fn children<T: bevy_ecs::component::Component + HasChildren>(
self,
) -> impl Iterator<Item = BoundEntity<'w>> + 'w {
self.0.get::<T>().into_iter().flat_map(move |c| {
c.children_handles()
.iter()
.copied()
.map(move |h| BoundEntity::new(h.entity(), self.0.world()))
})
}
}
use crate::ptr::{EntityPtr, EntityPtrNav, EntityPtrNavMany};
impl EntityPtrNav {
#[inline]
pub fn parent<T: bevy_ecs::component::Component + HasParent>(self) -> Option<EntityPtr> {
self.0.get::<T>().and_then(|c| {
c.parent_handle()
.map(|h| EntityPtr::new(h.entity(), self.0.world()))
})
}
}
impl EntityPtrNavMany {
#[inline]
pub fn children<T: bevy_ecs::component::Component + HasChildren>(
self,
) -> impl Iterator<Item = EntityPtr> {
self.0.get::<T>().into_iter().flat_map(move |c| {
c.children_handles()
.iter()
.copied()
.map(move |h| EntityPtr::new(h.entity(), self.0.world()))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ptr::WorldRef;
use bevy_ecs::component::Component;
use bevy_ecs::world::World;
#[derive(Component)]
struct Name(&'static str);
#[derive(Component)]
struct ParentRef(Option<EntityHandle>);
impl HasParent for ParentRef {
fn parent_handle(&self) -> Option<EntityHandle> {
self.0
}
}
#[derive(Component)]
struct ChildRefs(Vec<EntityHandle>);
impl HasChildren for ChildRefs {
fn children_handles(&self) -> &[EntityHandle] {
&self.0
}
}
#[test]
fn bound_entity_nav_parent() {
let mut world = World::new();
let parent = world.spawn(Name("parent")).id();
let child = world
.spawn((Name("child"), ParentRef(Some(EntityHandle::new(parent)))))
.id();
let bound = EntityHandle::new(child).bind(&world);
let parent_bound = bound.nav().parent::<ParentRef>().unwrap();
assert_eq!(parent_bound.get::<Name>().unwrap().0, "parent");
}
#[test]
fn bound_entity_nav_parent_none() {
let mut world = World::new();
let orphan = world.spawn((Name("orphan"), ParentRef(None))).id();
let bound = EntityHandle::new(orphan).bind(&world);
assert!(bound.nav().parent::<ParentRef>().is_none());
}
#[test]
fn bound_entity_nav_children() {
let mut world = World::new();
let child1 = world.spawn(Name("child1")).id();
let child2 = world.spawn(Name("child2")).id();
let parent = world
.spawn((
Name("parent"),
ChildRefs(vec![EntityHandle::new(child1), EntityHandle::new(child2)]),
))
.id();
let bound = EntityHandle::new(parent).bind(&world);
let children: Vec<_> = bound.nav().children::<ChildRefs>().collect();
assert_eq!(children.len(), 2);
let names: Vec<_> = children
.iter()
.map(|c| c.get::<Name>().unwrap().0)
.collect();
assert!(names.contains(&"child1"));
assert!(names.contains(&"child2"));
}
#[test]
fn entityptr_nav_parent() {
let mut world = World::new();
let parent = world.spawn(Name("parent")).id();
let child = world
.spawn((Name("child"), ParentRef(Some(EntityHandle::new(parent)))))
.id();
let world_ref = unsafe { WorldRef::new(&world) };
let ptr = world_ref.entity(child);
let parent_ptr = ptr.nav().parent::<ParentRef>().unwrap();
assert_eq!(parent_ptr.get::<Name>().unwrap().0, "parent");
}
#[test]
fn entityptr_nav_many_children() {
let mut world = World::new();
let child1 = world.spawn(Name("child1")).id();
let child2 = world.spawn(Name("child2")).id();
let parent = world
.spawn((
Name("parent"),
ChildRefs(vec![EntityHandle::new(child1), EntityHandle::new(child2)]),
))
.id();
let world_ref = unsafe { WorldRef::new(&world) };
let ptr = world_ref.entity(parent);
let children: Vec<_> = ptr.nav_many().children::<ChildRefs>().collect();
assert_eq!(children.len(), 2);
let names: Vec<_> = children
.iter()
.map(|c| c.get::<Name>().unwrap().0)
.collect();
assert!(names.contains(&"child1"));
assert!(names.contains(&"child2"));
}
#[test]
fn children_empty_vec() {
let mut world = World::new();
let parent = world.spawn((Name("parent"), ChildRefs(vec![]))).id();
let bound = EntityHandle::new(parent).bind(&world);
assert_eq!(bound.nav().children::<ChildRefs>().count(), 0);
let world_ref = unsafe { WorldRef::new(&world) };
let ptr = world_ref.entity(parent);
assert_eq!(ptr.nav_many().children::<ChildRefs>().count(), 0);
}
#[test]
fn nav_many_no_children_component() {
let mut world = World::new();
let entity = world.spawn(Name("no_children")).id();
let bound = EntityHandle::new(entity).bind(&world);
assert_eq!(bound.nav().children::<ChildRefs>().count(), 0);
let world_ref = unsafe { WorldRef::new(&world) };
let ptr = world_ref.entity(entity);
assert_eq!(ptr.nav_many().children::<ChildRefs>().count(), 0);
}
}