1use crate::{components::*, writer::TaskWriter, TaskData};
2
3use specs::{prelude::*, storage::GenericReadStorage, world::LazyBuilder};
4
5pub type TaskUser<'a> = TaskData<'a,
7 ReadStorage<'a, TaskProgress>,
8 ReadStorage<'a, SingleEdge>,
9 ReadStorage<'a, MultiEdge>,
10 (),
11>;
12
13impl<'a, P, S, M, F> TaskData<'a, P, S, M, F>
14where
15 P: GenericReadStorage<Component=TaskProgress>,
16 S: GenericReadStorage<Component=SingleEdge>,
17 M: GenericReadStorage<Component=MultiEdge>,
18 &'a P: 'a + Join,
19{
20 pub fn make_task_with_entity_lazy<'b, T: TaskComponent<'b> + Send + Sync>(
24 &self, entity: Entity, task: T
25 ) {
26 self.lazy.exec(move |world| {
27 world.exec(move |(mut builder, mut task_storage): (TaskWriter, WriteStorage<T>)| {
28 builder.make_task_with_entity(entity, task, &mut task_storage);
29 })
30 })
31 }
32
33 pub fn make_task_lazy<'b, T: TaskComponent<'b> + Send + Sync>(&self, task: T) -> Entity {
36 let entity = self.entities.create();
37 self.make_task_with_entity_lazy(entity, task);
38
39 entity
40 }
41
42 pub fn make_final_task_lazy<'b, T: TaskComponent<'b> + Send + Sync>(
43 &self, task: T, on_completion: OnCompletion,
44 ) -> Entity {
45 let entity = self.make_task_lazy(task);
46 self.finalize_lazy(entity, on_completion);
47
48 entity
49 }
50
51 pub fn make_fork_lazy(&self) -> Entity {
53 let entity = self
54 .lazy
55 .create_entity(&self.entities)
56 .with(MultiEdge::default())
57 .build();
58 log::debug!("Created fork {:?}", entity);
59
60 entity
61 }
62
63 pub fn add_prong_lazy(&self, fork_entity: Entity, prong: Entity) {
65 self.lazy.exec(move |world| {
66 world.exec(move |mut builder: TaskWriter| {
67 builder.add_prong(fork_entity, prong);
68 })
69 });
70 }
71
72 pub fn join_lazy(&self, parent: Entity, child: Entity) {
74 self.lazy.exec(move |world| {
75 world.exec(move |mut builder: TaskWriter| {
76 builder.join(parent, child);
77 })
78 });
79 }
80
81 pub fn finalize_lazy(&self, entity: Entity, on_completion: OnCompletion) {
87 LazyBuilder {
88 entity,
89 lazy: &self.lazy,
90 }
91 .with(FinalTag { on_completion })
92 .build();
93 }
94
95 pub fn task_is_complete(&self, task: Entity) -> bool {
97 if let Some(progress) = self.progress.get(task) {
98 progress.is_complete()
99 } else {
100 false
102 }
103 }
104
105 fn fork_is_complete(&self, multi_children: &[Entity]) -> bool {
107 for child in multi_children.iter() {
110 if !self.entity_is_complete(*child) {
111 return false;
112 }
113 }
114
115 true
116 }
117
118 pub fn entity_is_complete(&self, entity: Entity) -> bool {
120 if let Some(MultiEdge { children }) = self.multi_edges.get(entity) {
123 self.fork_is_complete(&children)
124 } else {
125 self.task_is_complete(entity)
126 }
127 }
128
129 pub fn count_tasks_in_progress(&'a self) -> usize {
131 (&self.progress).join().count()
132 }
133
134 fn delete_descendents(&self, entity: Entity) {
136 if let Some(MultiEdge { children }) = self.multi_edges.get(entity) {
137 for child in children.iter() {
138 self.delete_entity_and_descendents(*child);
139 }
140 }
141 if let Some(SingleEdge { child }) = self.single_edges.get(entity) {
142 self.delete_entity_and_descendents(*child);
143 }
144 }
145
146 pub fn delete_entity_and_descendents(&self, entity: Entity) {
148 if !self.entities.is_alive(entity) {
151 return;
152 }
153
154 self.delete_descendents(entity);
155 log::debug!("Deleting {:?}", entity);
156 self.entities.delete(entity).unwrap();
157 }
158
159 pub fn delete_if_complete(&self, entity: Entity) -> bool {
162 if self.entity_is_complete(entity) {
163 self.delete_entity_and_descendents(entity);
164
165 true
166 } else {
167 false
168 }
169 }
170
171 fn maintain_task_and_descendents(&self, entity: Entity) -> bool {
173 let (is_unblocked, is_complete) = if let Some(progress) = self.progress.get(entity) {
174 (progress.is_unblocked(), progress.is_complete())
175 } else {
176 return true;
178 };
179
180 if is_complete {
181 log::debug!(
182 "Noticed task {:?} is complete, removing TaskProgress",
183 entity
184 );
185 return true;
186 }
187
188 if is_unblocked {
191 return false;
192 }
193
194 let mut child_complete = true;
196 if let Some(SingleEdge { child }) = self.single_edges.get(entity).cloned() {
197 child_complete = self.maintain_entity_and_descendents(child);
198 }
199 if child_complete {
200 log::debug!("Unblocking task {:?}", entity);
201 let progress = self
202 .progress
203 .get(entity)
204 .expect("Blocked task must have progress");
205 progress.unblock();
206 }
207
208 false
209 }
210
211 fn maintain_fork_and_descendents(
213 &self,
214 entity: Entity,
215 multi_edge_children: &[Entity],
216 ) -> bool {
217 let mut single_child_complete = true;
220 if let Some(SingleEdge { child }) = self.single_edges.get(entity).cloned() {
221 single_child_complete = self.maintain_entity_and_descendents(child);
222 }
223 let mut multi_children_complete = true;
224 if single_child_complete {
225 for child in multi_edge_children.iter() {
226 multi_children_complete &= self.maintain_entity_and_descendents(*child);
227 }
228 }
229
230 single_child_complete && multi_children_complete
231 }
232
233 pub(crate) fn maintain_entity_and_descendents(&self, entity: Entity) -> bool {
235 if let Some(MultiEdge { children }) = self.multi_edges.get(entity).cloned() {
237 self.maintain_fork_and_descendents(entity, &children)
238 } else {
239 self.maintain_task_and_descendents(entity)
240 }
241 }
242}