1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::{
ecs::prelude::{
BitSet, ComponentEvent, ReadExpect, ReadStorage, ReaderId, System, SystemData, World,
WriteStorage,
},
transform::components::{HierarchyEvent, Parent, ParentHierarchy},
SystemDesc,
};
#[cfg(feature = "profiler")]
use thread_profiler::profile_scope;
use log::error;
use crate::HiddenPropagate;
#[derive(Default, Debug)]
pub struct HideHierarchySystemDesc;
impl<'a, 'b> SystemDesc<'a, 'b, HideHierarchySystem> for HideHierarchySystemDesc {
fn build(self, world: &mut World) -> HideHierarchySystem {
<HideHierarchySystem as System<'_>>::SystemData::setup(world);
let parent_events_id = world.fetch_mut::<ParentHierarchy>().track();
let mut hidden = WriteStorage::<HiddenPropagate>::fetch(&world);
let hidden_events_id = hidden.register_reader();
HideHierarchySystem::new(hidden_events_id, parent_events_id)
}
}
#[derive(Debug)]
pub struct HideHierarchySystem {
marked_as_modified: BitSet,
manually_hidden: BitSet,
hidden_events_id: ReaderId<ComponentEvent>,
parent_events_id: ReaderId<HierarchyEvent>,
}
impl HideHierarchySystem {
pub fn new(
hidden_events_id: ReaderId<ComponentEvent>,
parent_events_id: ReaderId<HierarchyEvent>,
) -> Self {
Self {
marked_as_modified: BitSet::default(),
manually_hidden: BitSet::default(),
hidden_events_id,
parent_events_id,
}
}
}
impl<'a> System<'a> for HideHierarchySystem {
type SystemData = (
WriteStorage<'a, HiddenPropagate>,
ReadStorage<'a, Parent>,
ReadExpect<'a, ParentHierarchy>,
);
fn run(&mut self, (mut hidden, parents, hierarchy): Self::SystemData) {
#[cfg(feature = "profiler")]
profile_scope!("hide_hierarchy_system");
self.marked_as_modified.clear();
self.manually_hidden.clear();
let self_hidden_events_id = &mut self.hidden_events_id;
let self_marked_as_modified = &mut self.marked_as_modified;
let self_manually_hidden = &mut self.manually_hidden;
hidden
.channel()
.read(self_hidden_events_id)
.for_each(|event| match event {
ComponentEvent::Inserted(id) | ComponentEvent::Removed(id) => {
self_marked_as_modified.add(*id);
}
ComponentEvent::Modified(_id) => {}
});
for event in hierarchy.changed().read(&mut self.parent_events_id) {
match *event {
HierarchyEvent::Removed(entity) => {
self_marked_as_modified.add(entity.id());
}
HierarchyEvent::Modified(entity) => {
self_marked_as_modified.add(entity.id());
}
}
}
for entity in hierarchy.all() {
{
let self_hidden = hidden.get(*entity);
let self_is_manually_hidden =
self_hidden.as_ref().map_or(false, |p| !p.is_propagated);
if self_is_manually_hidden {
self_manually_hidden.add(entity.id());
}
let parent_entity = parents
.get(*entity)
.expect(
"Unreachable: All entities in `ParentHierarchy` should also be in \
`Parents`",
)
.entity;
let parent_dirty = self_marked_as_modified.contains(parent_entity.id());
let parent_hidden = hidden.get(parent_entity);
let parent_is_manually_hidden =
parent_hidden.as_ref().map_or(false, |p| !p.is_propagated);
if parent_is_manually_hidden {
self_manually_hidden.add(parent_entity.id());
self_manually_hidden.add(entity.id());
}
if parent_dirty && !self_is_manually_hidden {
if parent_hidden.is_some() {
if let Err(e) = hidden.insert(*entity, HiddenPropagate::new_propagated()) {
error!("Failed to automatically add `HiddenPropagate`: {:?}", e);
}
} else {
hidden.remove(*entity);
}
}
}
hidden
.channel()
.read(self_hidden_events_id)
.for_each(|event| match event {
ComponentEvent::Inserted(id) | ComponentEvent::Removed(id) => {
self_marked_as_modified.add(*id);
}
ComponentEvent::Modified(_id) => {}
});
}
}
}