specs_task/
components.rs

1use specs::prelude::*;
2use std::sync::atomic::{AtomicBool, Ordering};
3
4/// An ephemeral component that needs access to `SystemData` to run some task. Will be run by the
5/// `TaskRunnerSystem<T>` until `run` returns `true`.
6///
7/// Note: `TaskComponent::Data` isn't allowed to contain `Storage<TaskComponent>`, since the
8/// `TaskRunnerSystem` already uses that resource and borrows it mutably while calling
9/// `TaskComponent::run`. If you really need access to `Storage<TaskComponent>`, you can
10/// safely use the `LazyUpdate` resource for that.
11pub trait TaskComponent<'a>: Component {
12    type Data: SystemData<'a>;
13
14    /// Returns `true` iff the task is complete.
15    fn run(&mut self, data: &mut Self::Data) -> bool;
16}
17
18// As long as an entity has this component, it will be considered by the `TaskRunnerSystem`.
19#[doc(hidden)]
20#[derive(Default)]
21pub struct TaskProgress {
22    is_complete: AtomicBool,
23    is_unblocked: AtomicBool,
24}
25
26impl Component for TaskProgress {
27    type Storage = VecStorage<Self>;
28}
29
30impl TaskProgress {
31    pub(crate) fn is_complete(&self) -> bool {
32        self.is_complete.load(Ordering::Relaxed)
33    }
34
35    pub(crate) fn complete(&self) {
36        self.is_complete.store(true, Ordering::Relaxed);
37    }
38
39    pub(crate) fn is_unblocked(&self) -> bool {
40        self.is_unblocked.load(Ordering::Relaxed)
41    }
42
43    pub(crate) fn unblock(&self) {
44        self.is_unblocked.store(true, Ordering::Relaxed);
45    }
46}
47
48#[doc(hidden)]
49#[derive(Clone)]
50pub struct SingleEdge {
51    pub(crate) child: Entity,
52}
53
54impl Component for SingleEdge {
55    type Storage = VecStorage<Self>;
56}
57
58#[doc(hidden)]
59#[derive(Clone, Default)]
60pub struct MultiEdge {
61    pub(crate) children: Vec<Entity>,
62}
63
64impl MultiEdge {
65    pub(crate) fn add_child(&mut self, entity: Entity) {
66        self.children.push(entity);
67    }
68}
69
70impl Component for MultiEdge {
71    type Storage = VecStorage<Self>;
72}
73
74/// What to do to a final task and its descendents when it they complete.
75/// WARNING: If you specify `Delete`, then you will not be able to poll for completion, since a
76/// non-existent entity is assumed to be "incomplete."
77#[derive(Copy, Clone, Debug, Eq, PartialEq)]
78pub enum OnCompletion {
79    None,
80    Delete,
81}
82
83impl Default for OnCompletion {
84    fn default() -> Self {
85        OnCompletion::None
86    }
87}
88
89#[doc(hidden)]
90#[derive(Clone, Copy, Default)]
91pub struct FinalTag {
92    pub(crate) on_completion: OnCompletion,
93}
94
95impl Component for FinalTag {
96    type Storage = VecStorage<Self>;
97}