specs_task/
writer.rs

1use crate::{components::*, TaskData};
2
3use specs::prelude::*;
4
5/// Creates and modifies task graph entities. Effects are immediate, not lazy like `TaskUser`, so
6/// this requires using `WriteStorage` for task graph components.
7pub type TaskWriter<'a> = TaskData<'a,
8    WriteStorage<'a, TaskProgress>,
9    WriteStorage<'a, SingleEdge>,
10    WriteStorage<'a, MultiEdge>,
11    WriteStorage<'a, FinalTag>,
12>;
13
14impl<'a> TaskWriter<'a> {
15    /// Like `make_task`, but use `entity` for tracking the task components.
16    pub fn make_task_with_entity<'b, T: TaskComponent<'b> + Send + Sync>(
17        &mut self, entity: Entity, task: T, task_storage: &mut WriteStorage<T>,
18    ) {
19        task_storage.insert(entity, task).unwrap();
20        self.progress.insert(entity, TaskProgress::default()).unwrap();
21        log::debug!("Created task {:?}", entity);
22    }
23
24    /// Create a new task entity with the given `TaskComponent`. The task will not make progress
25    /// until it is either finalized or the descendent of a finalized entity.
26    pub fn make_task<'b, T: TaskComponent<'b> + Send + Sync>(
27        &mut self, task: T, task_storage: &mut WriteStorage<T>
28    ) -> Entity {
29        let entity = self.entities.create();
30        self.make_task_with_entity(entity, task, task_storage);
31        log::debug!("Created task {:?}", entity);
32
33        entity
34    }
35
36    /// Same as `make_task_with_entity`, but also finalizes the task.
37    pub fn make_final_task_with_entity<'b, T: TaskComponent<'b> + Send + Sync>(
38        &mut self,
39        entity: Entity,
40        task: T,
41        on_completion: OnCompletion,
42        task_storage: &mut WriteStorage<T>,
43    ) -> Entity {
44        self.make_task_with_entity(entity, task, task_storage);
45        self.finalize(entity, on_completion);
46
47        entity
48    }
49
50    /// Same as `make_task`, but also finalizes the task.
51    pub fn make_final_task<'b, T: TaskComponent<'b> + Send + Sync>(
52        &mut self,
53        task: T,
54        on_completion: OnCompletion,
55        task_storage: &mut WriteStorage<T>,
56    ) -> Entity {
57        let task_entity = self.make_task(task, task_storage);
58        self.finalize(task_entity, on_completion);
59
60        task_entity
61    }
62
63    /// Create a new fork entity with no children.
64    pub fn make_fork(&mut self) -> Entity {
65        let entity = self.entities.create();
66        self.multi_edges.insert(entity, MultiEdge::default()).unwrap();
67        log::debug!("Created fork {:?}", entity);
68
69        entity
70    }
71
72    /// Add `prong` as a child on the `MultiEdge` of `fork_entity`.
73    pub fn add_prong(&mut self, fork_entity: Entity, prong: Entity) {
74        let multi_edge = self.multi_edges.get_mut(fork_entity).unwrap_or_else(|| {
75            panic!(
76                "Tried to add prong {:?} to non-fork entity {:?}",
77                prong, fork_entity
78            )
79        });
80        multi_edge.add_child(prong);
81    }
82
83    /// Creates a `SingleEdge` from `parent` to `child`. Creates a fork-join if `parent` is a fork.
84    pub fn join(&mut self, parent: Entity, child: Entity) {
85        if let Some(edge) = self.single_edges.get_mut(parent) {
86            panic!(
87                "Attempted to make task {:?} child of {:?}, but task {:?} already has child {:?}",
88                child, parent, parent, edge.child
89            );
90        } else {
91            self.single_edges.insert(parent, SingleEdge { child }).unwrap();
92        }
93    }
94
95    /// Mark `entity` as final. This will make all of `entity`'s descendents visible to the
96    /// `TaskManagerSystem`, allowing them to make progress. If `OnCompletion::Delete`, then
97    /// `entity` and all of its descendents will be deleted when `entity` is complete (and hence the
98    /// entire graph is complete). Otherwise, you need to clean up the entities your self by calling
99    /// `delete_entity_and_descendents`. God help you if you leak an orphaned entity.
100    pub fn finalize(&mut self, entity: Entity, on_completion: OnCompletion) {
101        self.final_tags.insert(entity, FinalTag { on_completion }).unwrap();
102    }
103}