hassium_core/
hierarchy.rs1use crate::state::StateToken;
2use specs::{Component, Entity, FlaggedStorage, VecStorage, World};
3use specs_hierarchy::Hierarchy;
4use std::{borrow::Cow, collections::HashSet};
5
6pub fn hierarchy_find(mut root: Entity, path: &str, world: &World) -> Option<Entity> {
7 let hierarchy = world.read_resource::<HierarchyRes>();
8 let names = world.read_storage::<Name>();
9 for part in path.split('/') {
10 match part {
11 "" | "." => {}
12 ".." => {
13 if let Some(parent) = hierarchy.parent(root) {
14 root = parent;
15 } else {
16 return None;
17 }
18 }
19 part => {
20 let found = hierarchy.children(root).iter().find_map(|child| {
21 if let Some(name) = names.get(*child) {
22 if name.0 == part {
23 Some(child)
24 } else {
25 None
26 }
27 } else {
28 None
29 }
30 });
31 if let Some(child) = found {
32 root = *child;
33 } else {
34 return None;
35 }
36 }
37 }
38 }
39 Some(root)
40}
41
42pub type HierarchyRes = Hierarchy<Parent>;
43
44#[derive(Default)]
45pub struct HierarchyChangeRes {
46 pub(crate) entities: HashSet<Entity>,
47 pub(crate) added: Vec<Entity>,
48 pub(crate) removed: Vec<Entity>,
49}
50
51impl HierarchyChangeRes {
52 #[inline]
53 pub fn added(&self) -> &[Entity] {
54 &self.added
55 }
56
57 #[inline]
58 pub fn removed(&self) -> &[Entity] {
59 &self.removed
60 }
61}
62
63#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
64pub struct Parent(pub Entity);
65
66impl Component for Parent {
67 type Storage = FlaggedStorage<Self, VecStorage<Self>>;
68}
69
70impl specs_hierarchy::Parent for Parent {
71 fn parent_entity(&self) -> Entity {
72 self.0
73 }
74}
75
76#[derive(Debug, Clone)]
77pub struct Tag(pub Cow<'static, str>);
78
79impl Component for Tag {
80 type Storage = VecStorage<Self>;
81}
82
83#[derive(Debug, Clone)]
84pub struct Name(pub Cow<'static, str>);
85
86impl Component for Name {
87 type Storage = VecStorage<Self>;
88}
89
90#[derive(Debug, Clone)]
91pub struct NonPersistent(pub StateToken);
92
93impl Component for NonPersistent {
94 type Storage = VecStorage<Self>;
95}