1use crate::status::Status::*;
2use crate::tracer::{first_child_id, next_sibling_id, NodeMeta, Tracer};
3use crate::Float;
4use crate::{event::UpdateEvent, state::State, ActionArgs, Status, RUNNING};
5
6pub struct WhenAllArgs<'a, A, E, F, B, T> {
7 pub any: bool,
8 pub upd: Option<Float>,
9 pub cursors: &'a mut [Option<State<A>>],
10 pub e: &'a E,
11 pub blackboard: &'a mut B,
12 pub f: &'a mut F,
13 pub parent_id: usize,
14 pub metas: &'a [NodeMeta],
15 pub tracer: &'a mut T,
16}
17
18pub fn when_all<A, E, F, B, T>(args: WhenAllArgs<A, E, F, B, T>) -> (Status, Float)
23where
24 A: Clone,
25 E: UpdateEvent,
26 F: FnMut(ActionArgs<E, A>, &mut B) -> (Status, Float),
27 T: Tracer,
28{
29 let WhenAllArgs {
30 any,
31 upd,
32 cursors,
33 e,
34 blackboard,
35 f,
36 parent_id,
37 metas,
38 tracer,
39 } = args;
40 let (status, inv_status) = if any {
41 (Status::Failure, Status::Success)
43 } else {
44 (Status::Success, Status::Failure)
46 };
47 let mut min_dt = Float::MAX;
49 let mut terminated = 0;
51 let mut child_id = first_child_id::<T>(parent_id);
52 for cur in cursors.iter_mut() {
53 let this_id = child_id;
54 child_id = next_sibling_id::<T>(metas, this_id);
55 match *cur {
56 None => {}
57 Some(ref mut cur) => {
58 match cur.tick(this_id, metas, e, blackboard, f, tracer) {
59 (Running, _) => {
60 continue;
61 }
62 (s, new_dt) if s == inv_status => {
63 return (inv_status, new_dt);
66 }
67 (s, new_dt) if s == status => {
68 min_dt = min_dt.min(new_dt);
69 }
70 _ => unreachable!(),
71 }
72 }
73 }
74
75 terminated += 1;
76 *cur = None;
77 }
78 #[allow(clippy::manual_unwrap_or)]
79 match terminated {
80 0 if cursors.is_empty() => (
82 status,
83 match upd {
84 Some(dt) => dt,
85 _ => 0.0,
87 },
88 ),
89 n if cursors.len() == n => (status, min_dt),
91 _ => RUNNING,
92 }
93}