legion_task/
runner.rs

1use crate::components::{TaskComponent, TaskProgress};
2
3use legion::{
4    filter::{And, ComponentFilter, EntityFilterTuple, Passthrough},
5    prelude::*,
6    query::Query,
7};
8
9/// The type of `SystemQuery` created by `task_runner_query` and used by `run_tasks`.
10pub type TaskSystemQuery<T> = Query<(Read<TaskProgress>, Write<T>), TaskEntityFilter<T>>;
11
12/// The type of `Query` created by `task_runner_query` and used by `run_tasks`.
13pub type TaskQuery<T> = Query<(Read<TaskProgress>, Write<T>), TaskEntityFilter<T>>;
14
15/// The `EntityFilterTuple` for `task_runner_query`.
16pub type TaskEntityFilter<T> = EntityFilterTuple<
17    And<(ComponentFilter<TaskProgress>, ComponentFilter<T>)>,
18    And<(Passthrough, Passthrough)>,
19    And<(Passthrough, Passthrough)>,
20>;
21
22/// Run the tasks that match `task_query`. Should be run in a `System` created with
23/// `task_runner_query`.
24pub fn run_tasks<'a, T: 'static + TaskComponent<'a>>(
25    world: &mut SubWorld,
26    task_component_data: &mut T::Data,
27    task_query: &mut TaskSystemQuery<T>,
28) {
29    for (task_progress, mut task) in task_query.iter_mut(world) {
30        if !task_progress.is_unblocked || task_progress.is_complete() {
31            continue;
32        }
33        let is_complete = task.run(task_component_data);
34        if is_complete {
35            task_progress.complete();
36        }
37    }
38}
39
40/// The legion system query required to run all tasks with `T: TaskComponent`.
41pub fn task_runner_query<'a, T: 'static + TaskComponent<'a>>() -> TaskQuery<T> {
42    <(Read<TaskProgress>, Write<T>)>::query()
43}