specs_hierarchy/
lib.rs

1/// # `specs-hierarchy`
2///
3/// Scene graph type hierarchy for use with Specs.
4///
5/// ## `Parent`
6///
7/// This crate uses a generic parameter `P` for the parent component. Its bound by the `Parent`
8/// trait that only requires a getter for the `Entity` that's the parent.
9///
10/// ## Usage
11///
12/// ```rust
13/// # extern crate specs;
14/// # extern crate specs_hierarchy;
15///
16/// use specs::prelude::{Component, DenseVecStorage, Entity, FlaggedStorage};
17/// use specs_hierarchy::{Hierarchy, Parent as HParent};
18///
19/// pub use specs_hierarchy::HierarchyEvent;
20/// pub type ParentHierarchy = Hierarchy<Parent>;
21///
22/// /// Component for defining a parent entity.
23/// ///
24/// /// The entity with this component *has* a parent, rather than *is* a parent.
25/// #[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
26/// pub struct Parent {
27///     /// The parent entity
28///     pub entity: Entity,
29/// }
30///
31/// impl Component for Parent {
32///     type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
33/// }
34///
35/// impl HParent for Parent {
36///     fn parent_entity(&self) -> Entity {
37///         self.entity
38///     }
39/// }
40///
41/// # fn main() {}
42/// ```
43///
44extern crate hibitset;
45extern crate shrev;
46extern crate specs;
47
48use std::collections::{HashMap, HashSet};
49use std::marker::PhantomData;
50
51use hibitset::BitSetLike;
52use shrev::EventChannel;
53use specs::prelude::{
54    BitSet, Component, ComponentEvent, Entities, Entity, Join, ReadStorage, ReaderId, ResourceId,
55    System, SystemData, Tracked, World, WriteExpect, WriteStorage,
56};
57use specs::world::Index;
58
59/// Hierarchy events.
60///
61/// These are the events that are sent through the internal `EventChannel` in the `Hierarchy`
62/// resource.
63#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
64pub enum HierarchyEvent {
65    /// `Entity` was either inserted or modified in the `Hierarchy`
66    Modified(Entity),
67    /// `Entity` was removed from the `Hierarchy`. Note that this does not mean the `Parent`
68    /// component was removed from the component storage, just that the `Entity` will no longer be
69    /// considered to be a part of the `Hierarchy`.
70    Removed(Entity),
71}
72
73/// Scene graph type hierarchy.
74///
75/// Will use the given generic type `P` as the component type that provides parenting links. The
76/// internal structure is kept in sync with the `Tracked` events for that component type.
77///
78/// Will send modification events on the internal `EventChannel`. Note that `Removed` events
79/// do not indicate that the `Parent` component was removed from the component storage, just that
80/// the `Entity` will no longer be considered to be a part of the `Hierarchy`. This is because the
81/// user may wish to either remove only the component, or the complete Entity, or something
82/// completely different. When an `Entity` that is a parent gets removed from the hierarchy, the
83/// full tree of children below it will also be removed from the hierarchy.
84///
85/// Any cycles in the hierarchy will cause Undefined Behavior.
86pub struct Hierarchy<P> {
87    sorted: Vec<Entity>,
88    entities: HashMap<Index, usize>,
89    children: HashMap<Entity, Vec<Entity>>,
90    current_parent: HashMap<Entity, Entity>,
91    external_parents: HashSet<Entity>,
92    changed: EventChannel<HierarchyEvent>,
93
94    reader_id: ReaderId<ComponentEvent>,
95    modified: BitSet,
96    inserted: BitSet,
97    removed: BitSet,
98
99    scratch_set: HashSet<Entity>,
100
101    _phantom: PhantomData<P>,
102}
103
104impl<P> Hierarchy<P> {
105    /// Create a new hierarchy object.
106    pub fn new(reader_id: ReaderId<ComponentEvent>) -> Self
107    where
108        P: Component,
109        P::Storage: Tracked,
110    {
111        Hierarchy {
112            sorted: Vec::new(),
113            entities: HashMap::new(),
114            current_parent: HashMap::new(),
115            external_parents: HashSet::new(),
116            children: HashMap::new(),
117            changed: EventChannel::new(),
118
119            reader_id,
120            modified: BitSet::new(),
121            inserted: BitSet::new(),
122            removed: BitSet::new(),
123
124            scratch_set: HashSet::default(),
125
126            _phantom: PhantomData,
127        }
128    }
129
130    /// Get all entities that contain parents, in sorted order, where parents are guaranteed to
131    /// be before their children.
132    ///
133    /// Note: This does not include entities that **are** parents.
134    pub fn all(&self) -> &[Entity] {
135        self.sorted.as_slice()
136    }
137
138    /// Get the immediate children of a specific entity.
139    pub fn children(&self, entity: Entity) -> &[Entity] {
140        self.children
141            .get(&entity)
142            .map(|vec| vec.as_slice())
143            .unwrap_or(&[])
144    }
145
146    /// Get all children of this entity recursively as a `BitSet`
147    ///
148    /// This does not include the parent entity you pass in.
149    pub fn all_children(&self, entity: Entity) -> BitSet {
150        let mut entities = BitSet::new();
151        self.add_children_to_set(entity, &mut entities);
152        entities
153    }
154
155    fn add_children_to_set(&self, entity: Entity, set: &mut BitSet) {
156        if let Some(children) = self.children.get(&entity) {
157            for child in children {
158                set.add(child.id());
159                self.add_children_to_set(*child, set);
160            }
161        }
162    }
163
164    /// Returns an iterator over all of the recursive children of this entity.
165    ///
166    /// This does not include the parent entity you pass in. Parents are guaranteed to be
167    /// prior to their children.
168    pub fn all_children_iter(&self, entity: Entity) -> SubHierarchyIterator<'_, P> {
169        SubHierarchyIterator::new(self, entity)
170    }
171
172    /// Get the parent of a specific entity
173    pub fn parent(&self, entity: Entity) -> Option<Entity> {
174        self.current_parent.get(&entity).cloned()
175    }
176
177    /// Get a token for tracking the modification events from the hierarchy
178    pub fn track(&mut self) -> ReaderId<HierarchyEvent> {
179        self.changed.register_reader()
180    }
181
182    /// Get the `EventChannel` for the modification events for reading
183    pub fn changed(&self) -> &EventChannel<HierarchyEvent> {
184        &self.changed
185    }
186
187    /// Maintain the hierarchy, usually only called by `HierarchySystem`.
188    pub fn maintain(&mut self, data: ParentData<P>)
189    where
190        P: Component + Parent,
191        P::Storage: Tracked,
192    {
193        let ParentData {
194            entities, parents, ..
195        } = data;
196
197        // Maintain tracking
198        self.modified.clear();
199        self.inserted.clear();
200        self.removed.clear();
201
202        let events = parents.channel().read(&mut self.reader_id);
203        for event in events {
204            match event {
205                ComponentEvent::Modified(id) => {
206                    self.modified.add(*id);
207                }
208                ComponentEvent::Inserted(id) => {
209                    self.inserted.add(*id);
210                }
211                ComponentEvent::Removed(id) => {
212                    self.removed.add(*id);
213                }
214            }
215        }
216
217        // process removed parent components
218        self.scratch_set.clear();
219        for id in (&self.removed).iter() {
220            if let Some(index) = self.entities.get(&id) {
221                self.scratch_set.insert(self.sorted[*index]);
222            }
223        }
224        // handle parents that have been removed which do not have a Parent themselves
225        for entity in &self.external_parents {
226            if !entities.is_alive(*entity) {
227                self.scratch_set.insert(*entity);
228            }
229        }
230
231        // do removal
232        if !self.scratch_set.is_empty() {
233            let mut i = 0;
234            let mut min_index = std::usize::MAX;
235            while i < self.sorted.len() {
236                let entity = self.sorted[i];
237                let remove = self.scratch_set.contains(&entity)
238                    || self
239                        .current_parent
240                        .get(&entity)
241                        .map(|parent_entity| self.scratch_set.contains(&parent_entity))
242                        .unwrap_or(false);
243                if remove {
244                    if i < min_index {
245                        min_index = i;
246                    }
247                    self.scratch_set.insert(entity);
248                    self.sorted.remove(i);
249                    if let Some(children) = self
250                        .current_parent
251                        .get(&entity)
252                        .cloned()
253                        .and_then(|parent_entity| self.children.get_mut(&parent_entity))
254                    {
255                        if let Some(pos) = children.iter().position(|e| *e == entity) {
256                            children.swap_remove(pos);
257                        }
258                    }
259                    self.current_parent.remove(&entity);
260                    self.children.remove(&entity);
261                    self.entities.remove(&entity.id());
262                } else {
263                    i += 1;
264                }
265            }
266            for i in min_index..self.sorted.len() {
267                self.entities.insert(self.sorted[i].id(), i);
268            }
269            for entity in &self.scratch_set {
270                self.changed.single_write(HierarchyEvent::Removed(*entity));
271                self.external_parents.remove(entity);
272            }
273        }
274
275        // insert new components in hierarchy
276        self.scratch_set.clear();
277        for (entity, _, parent) in (&*entities, &self.inserted, &parents).join() {
278            let parent_entity = parent.parent_entity();
279
280            // if we insert a parent component on an entity that have children, we need to make
281            // sure the parent is inserted before the children in the sorted list
282            let insert_index = self
283                .children
284                .get(&entity)
285                .and_then(|children| {
286                    children
287                        .iter()
288                        .map(|child_entity| self.entities.get(&child_entity.id()).unwrap())
289                        .min()
290                        .cloned()
291                })
292                .unwrap_or_else(|| self.sorted.len());
293            self.entities.insert(entity.id(), insert_index);
294            if insert_index >= self.sorted.len() {
295                self.sorted.push(entity);
296            } else {
297                self.sorted.insert(insert_index, entity);
298                for i in insert_index..self.sorted.len() {
299                    self.entities.insert(self.sorted[i].id(), i);
300                }
301            }
302
303            {
304                let children = self
305                    .children
306                    .entry(parent_entity)
307                    .or_insert_with(Vec::default);
308                children.push(entity);
309            }
310
311            self.current_parent.insert(entity, parent_entity);
312            self.scratch_set.insert(entity);
313            if !self.current_parent.contains_key(&parent_entity) {
314                self.external_parents.insert(parent_entity);
315            }
316            self.external_parents.remove(&entity);
317        }
318
319        for (entity, _, parent) in (&*entities, &self.modified.clone(), &parents).join() {
320            let parent_entity = parent.parent_entity();
321            // if theres an old parent
322            if let Some(old_parent) = self.current_parent.get(&entity).cloned() {
323                // if the parent entity was not changed, ignore event
324                if old_parent == parent_entity {
325                    continue;
326                }
327                // remove entity from old parents children
328                if let Some(children) = self.children.get_mut(&old_parent) {
329                    if let Some(pos) = children.iter().position(|e| *e == entity) {
330                        children.remove(pos);
331                    }
332                }
333            }
334
335            // insert in new parents children
336            self.children
337                .entry(parent_entity)
338                .or_insert_with(Vec::default)
339                .push(entity);
340
341            // move entity in sorted if needed
342            let entity_index = self.entities.get(&entity.id()).cloned().unwrap();
343            if let Some(parent_index) = self.entities.get(&parent_entity.id()).cloned() {
344                let mut offset = 0;
345                let mut process_index = parent_index;
346                while process_index > entity_index {
347                    let move_entity = self.sorted.remove(process_index);
348                    self.sorted.insert(entity_index, move_entity);
349                    offset += 1;
350                    process_index = self
351                        .current_parent
352                        .get(&move_entity)
353                        .and_then(|p_entity| self.entities.get(&p_entity.id()))
354                        .map(|p_index| p_index + offset)
355                        .unwrap_or(0);
356                }
357
358                // fix indexes
359                if parent_index > entity_index {
360                    for i in entity_index..parent_index {
361                        self.entities.insert(self.sorted[i].id(), i);
362                    }
363                }
364            }
365
366            self.current_parent.insert(entity, parent_entity);
367            self.scratch_set.insert(entity);
368
369            if !self.current_parent.contains_key(&parent_entity) {
370                self.external_parents.insert(parent_entity);
371            }
372        }
373
374        if !self.scratch_set.is_empty() {
375            for i in 0..self.sorted.len() {
376                let entity = self.sorted[i];
377                let notify = self.scratch_set.contains(&entity)
378                    || self
379                        .current_parent
380                        .get(&entity)
381                        .map(|parent_entity| self.scratch_set.contains(&parent_entity))
382                        .unwrap_or(false);
383                if notify {
384                    self.scratch_set.insert(entity);
385                    self.changed.single_write(HierarchyEvent::Modified(entity));
386                }
387            }
388        }
389
390        self.scratch_set.clear();
391        for entity in &self.external_parents {
392            if !self.children.contains_key(entity) {
393                self.scratch_set.insert(*entity);
394            }
395        }
396        for entity in &self.scratch_set {
397            self.external_parents.remove(entity);
398        }
399    }
400}
401
402pub struct SubHierarchyIterator<'a, P>
403where
404    P: 'a,
405{
406    current_index: usize,
407    end_index: usize,
408    hierarchy: &'a Hierarchy<P>,
409    entities: BitSet,
410}
411
412impl<'a, P> SubHierarchyIterator<'a, P>
413where
414    P: 'a,
415{
416    fn new(hierarchy: &'a Hierarchy<P>, root: Entity) -> Self {
417        let max = hierarchy.sorted.len();
418        let root_index = hierarchy
419            .children
420            .get(&root)
421            .map(|children| {
422                children
423                    .iter()
424                    .map(|c| hierarchy.entities.get(&c.id()).cloned().unwrap_or(max))
425                    .min()
426                    .unwrap_or(max)
427            })
428            .unwrap_or(max);
429        let mut iter = SubHierarchyIterator {
430            hierarchy,
431            current_index: root_index,
432            end_index: 0,
433            entities: BitSet::new(),
434        };
435        iter.process_entity(root);
436        if root_index != max {
437            iter.process_entity(hierarchy.sorted[root_index]);
438        }
439        iter
440    }
441
442    fn process_entity(&mut self, child: Entity) {
443        if let Some(children) = self.hierarchy.children.get(&child) {
444            for child in children {
445                self.entities.add(child.id());
446                if let Some(index) = self.hierarchy.entities.get(&child.id()) {
447                    if *index > self.end_index {
448                        self.end_index = *index;
449                    }
450                }
451            }
452        }
453    }
454}
455
456impl<'a, P> Iterator for SubHierarchyIterator<'a, P>
457where
458    P: 'a,
459{
460    type Item = Entity;
461
462    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
463        if self.current_index >= self.hierarchy.sorted.len() || self.current_index > self.end_index
464        {
465            None
466        } else {
467            let entity = self.hierarchy.sorted[self.current_index];
468            let mut found_next = false;
469            while !found_next {
470                self.current_index += 1;
471                if self.current_index > self.end_index
472                    || self.current_index >= self.hierarchy.sorted.len()
473                {
474                    found_next = true;
475                } else if self
476                    .entities
477                    .contains(self.hierarchy.sorted[self.current_index].id())
478                {
479                    found_next = true;
480                    let current_index = self.current_index; // compiler fails to realise a usize is Copy, so we break it out
481                    self.process_entity(self.hierarchy.sorted[current_index]);
482                }
483            }
484            Some(entity)
485        }
486    }
487}
488
489/// Bound for the parent component of your crate. Your `Parent` component usually just contains the
490/// `Entity` that's the parent you're linking to.
491///
492/// Note that the component should indicate that the `Entity` its added *has* a parent (the entity
493/// stored in your component).
494pub trait Parent {
495    /// Retrieves the parent `Entity`.
496    fn parent_entity(&self) -> Entity;
497}
498
499/// Utility struct for the data needed by the `Hierarchy` maintain.
500#[derive(SystemData)]
501pub struct ParentData<'a, P>
502where
503    P: Component + Parent,
504    P::Storage: Tracked,
505{
506    entities: Entities<'a>,
507    parents: ReadStorage<'a, P>,
508}
509
510/// System for maintaining a `Hierarchy` resource.
511///
512/// ## Type parameters:
513///
514/// - `P`: Component type that provides `Parent` links for the maintained `Hierarchy`
515pub struct HierarchySystem<P> {
516    m: PhantomData<P>,
517}
518
519impl<P> HierarchySystem<P>
520where
521    P: Component + Parent + Send + Sync + 'static,
522    P::Storage: Tracked,
523{
524    pub fn new(mut world: &mut World) -> Self {
525        <Self as System<'_>>::SystemData::setup(&mut world);
526        if !world.has_value::<Hierarchy<P>>() {
527            let hierarchy = {
528                let mut storage: WriteStorage<P> = SystemData::fetch(&world);
529                Hierarchy::<P>::new(storage.register_reader())
530            };
531            world.insert(hierarchy);
532        }
533        HierarchySystem { m: PhantomData }
534    }
535}
536
537impl<'a, P> System<'a> for HierarchySystem<P>
538where
539    P: Component + Parent + Send + Sync + 'static,
540    P::Storage: Tracked,
541{
542    type SystemData = (ParentData<'a, P>, WriteExpect<'a, Hierarchy<P>>);
543
544    fn run(&mut self, (data, mut hierarchy): Self::SystemData) {
545        hierarchy.maintain(data);
546    }
547}
548
549#[cfg(test)]
550mod tests {
551
552    use super::{Hierarchy, HierarchyEvent, HierarchySystem, Parent as PParent};
553    use specs::prelude::{
554        Builder, Component, DenseVecStorage, Entity, FlaggedStorage, ReaderId, RunNow, World,
555    };
556    use specs::WorldExt;
557
558    struct Parent {
559        entity: Entity,
560    }
561
562    impl Component for Parent {
563        type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
564    }
565
566    impl PParent for Parent {
567        fn parent_entity(&self) -> Entity {
568            self.entity
569        }
570    }
571
572    fn delete_removals(world: &mut World, reader_id: &mut ReaderId<HierarchyEvent>) {
573        let mut remove = vec![];
574        for event in world.fetch::<Hierarchy<Parent>>().changed().read(reader_id) {
575            if let HierarchyEvent::Removed(entity) = *event {
576                remove.push(entity);
577            }
578        }
579        for entity in remove {
580            if let Err(_) = world.delete_entity(entity) {
581                println!("Failed removed entity");
582            }
583        }
584    }
585
586    #[test]
587    fn parent_removed() {
588        let mut world = World::new();
589        world.register::<Parent>();
590        let mut system = HierarchySystem::<Parent>::new(&mut world);
591        let mut reader_id = world.write_resource::<Hierarchy<Parent>>().track();
592
593        let e1 = world.create_entity().build();
594
595        let e2 = world.create_entity().with(Parent { entity: e1 }).build();
596
597        let e3 = world.create_entity().build();
598
599        let e4 = world.create_entity().with(Parent { entity: e3 }).build();
600
601        let e5 = world.create_entity().with(Parent { entity: e4 }).build();
602
603        system.run_now(&mut world);
604        delete_removals(&mut world, &mut reader_id);
605        world.maintain();
606
607        let _ = world.delete_entity(e1);
608        system.run_now(&mut world);
609        delete_removals(&mut world, &mut reader_id);
610        world.maintain();
611
612        assert_eq!(world.is_alive(e1), false);
613        assert_eq!(world.is_alive(e2), false);
614
615        let _ = world.delete_entity(e3);
616        system.run_now(&mut world);
617        delete_removals(&mut world, &mut reader_id);
618        world.maintain();
619
620        assert_eq!(world.is_alive(e3), false);
621        assert_eq!(world.is_alive(e4), false);
622        assert_eq!(world.is_alive(e5), false);
623
624        assert_eq!(0, world.read_resource::<Hierarchy<Parent>>().all().len());
625    }
626
627    #[test]
628    fn test_all_children_iter() {
629        let mut world = World::new();
630        world.register::<Parent>();
631        let mut system = HierarchySystem::<Parent>::new(&mut world);
632        let e0 = world.create_entity().build();
633
634        let e1 = world.create_entity().with(Parent { entity: e0 }).build();
635
636        let e2 = world.create_entity().build();
637
638        let e3 = world.create_entity().with(Parent { entity: e2 }).build();
639
640        let e4 = world.create_entity().with(Parent { entity: e2 }).build();
641
642        let e5 = world.create_entity().with(Parent { entity: e3 }).build();
643
644        system.run_now(&mut world);
645        world.maintain();
646        let hierarchy = world.read_resource::<Hierarchy<Parent>>();
647        assert!(hierarchy.all_children_iter(e0).eq([e1].iter().cloned()));
648        assert_eq!(hierarchy.all_children_iter(e1).next(), None);
649        assert!(hierarchy
650            .all_children_iter(e2)
651            .eq([e3, e4, e5].iter().cloned()));
652        assert!(hierarchy.all_children_iter(e3).eq([e5].iter().cloned()));
653        assert_eq!(hierarchy.all_children_iter(e4).next(), None);
654        assert_eq!(hierarchy.all_children_iter(e5).next(), None);
655    }
656
657    #[test]
658    fn test_all_children() {
659        let mut world = World::new();
660        world.register::<Parent>();
661        let mut system = HierarchySystem::<Parent>::new(&mut world);
662        let e0 = world.create_entity().build();
663
664        let e1 = world.create_entity().with(Parent { entity: e0 }).build();
665
666        let e2 = world.create_entity().build();
667
668        let e3 = world.create_entity().with(Parent { entity: e2 }).build();
669
670        let e4 = world.create_entity().with(Parent { entity: e2 }).build();
671
672        let e5 = world.create_entity().with(Parent { entity: e3 }).build();
673
674        system.run_now(&mut world);
675        world.maintain();
676        let hierarchy = world.read_resource::<Hierarchy<Parent>>();
677        use hibitset::BitSetLike;
678
679        assert!(hierarchy
680            .all_children(e0)
681            .iter()
682            .eq([e1].iter().map(|e| e.id())));
683        assert_eq!(hierarchy.all_children(e1).iter().next(), None);
684        assert!(hierarchy
685            .all_children(e2)
686            .iter()
687            .eq([e3, e4, e5].iter().map(|e| e.id())));
688        assert!(hierarchy
689            .all_children(e3)
690            .iter()
691            .eq([e5].iter().map(|e| e.id())));
692        assert_eq!(hierarchy.all_children(e4).iter().next(), None);
693        assert_eq!(hierarchy.all_children(e5).iter().next(), None);
694    }
695}