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
156
157
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,
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(),
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();
let self_hidden_events_id = &mut self.hidden_events_id;
let self_marked_as_modified = &mut self.marked_as_modified;
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_dirty = self_marked_as_modified.contains(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());
if parent_dirty {
if hidden.contains(parent_entity) {
for child in hierarchy.all_children_iter(parent_entity) {
if let Err(e) = hidden.insert(child, HiddenPropagate::default()) {
error!("Failed to automatically add `HiddenPropagate`: {:?}", e);
};
}
} else {
for child in hierarchy.all_children_iter(parent_entity) {
hidden.remove(child);
}
}
} else if self_dirty {
if hidden.contains(*entity) {
for child in hierarchy.all_children_iter(*entity) {
if let Err(e) = hidden.insert(child, HiddenPropagate::default()) {
error!("Failed to automatically add `HiddenPropagate`: {:?}", e);
};
}
} else {
for child in hierarchy.all_children_iter(*entity) {
hidden.remove(child);
}
}
}
}
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) => {}
});
}
}
}