1use crate::maybe_profile_function;
2use crate::prelude::*;
3use std::{cell::RefCell, rc::Rc};
4
5pub struct Node<T> {
6 pub name: Option<String>,
7 pub behavior: Behavior<T>,
8 pub status: Status,
9 pub collapse_as: Option<String>,
10}
11
12impl<T> Node<T> {
13 fn new(behavior: Behavior<T>) -> Node<T> {
14 Node {
15 name: None,
16 behavior,
17 status: Status::Initialized,
18 collapse_as: None,
19 }
20 }
21
22 pub fn new_named(name: String, behavior: Behavior<T>) -> Node<T> {
23 Node {
24 name: Some(name),
25 behavior,
26 status: Status::Initialized,
27 collapse_as: None,
28 }
29 }
30
31 pub fn action(name: &str, func: fn(&mut T) -> Status) -> Node<T> {
32 Self::new_named(name.to_owned(), Behavior::Action(name.to_owned(), func))
33 }
34
35 pub fn action_success(name: &str, func: fn(&mut T) -> ()) -> Node<T> {
36 Self::new_named(
37 name.to_owned(),
38 Behavior::ActionSuccess(name.to_owned(), func),
39 )
40 }
41
42 pub fn stateful_action(name: &str, func: Box<dyn StatefulAction<T>>) -> Node<T> {
43 Self::new_named(
44 name.to_owned(),
45 Behavior::StatefulAction(name.to_owned(), func),
46 )
47 }
48
49 pub fn sequence(nodes: Vec<Node<T>>) -> Node<T> {
50 Self::new(Behavior::Sequence(
51 0,
52 nodes
53 .into_iter()
54 .map(|node| Rc::new(RefCell::new(node)))
55 .collect(),
56 ))
57 }
58
59 pub fn named_sequence(name: &str, nodes: Vec<Node<T>>) -> Node<T> {
60 Self::new_named(
61 name.to_owned(),
62 Behavior::Sequence(
63 0,
64 nodes
65 .into_iter()
66 .map(|node| Rc::new(RefCell::new(node)))
67 .collect(),
68 ),
69 )
70 }
71
72 pub fn select(nodes: Vec<Node<T>>) -> Node<T> {
73 Self::new(Behavior::Select(
74 0,
75 nodes
76 .into_iter()
77 .map(|node| Rc::new(RefCell::new(node)))
78 .collect(),
79 ))
80 }
81
82 pub fn named_select(name: &str, nodes: Vec<Node<T>>) -> Node<T> {
85 Self::new_named(
86 name.to_owned(),
87 Behavior::Select(
88 0,
89 nodes
90 .into_iter()
91 .map(|node| Rc::new(RefCell::new(node)))
92 .collect(),
93 ),
94 )
95 }
96
97 pub fn cond(name: &str, cond: fn(&T) -> bool, success: Node<T>, failure: Node<T>) -> Node<T> {
98 Self::new_named(
99 name.to_owned(),
100 Behavior::Cond(
101 name.to_owned(),
102 cond,
103 Rc::new(RefCell::new(success)),
104 Rc::new(RefCell::new(failure)),
105 ),
106 )
107 }
108
109 pub fn wait(time: f64) -> Node<T> {
110 Self::new(Behavior::Wait {
111 curr: time,
112 max: time,
113 })
114 }
115
116 pub fn random_wait(time: f64) -> Node<T> {
117 let curr_max = rand::random::<f64>() * time;
118
119 Self::new(Behavior::RandomWait {
120 curr: curr_max,
121 curr_max,
122 max: time,
123 })
124 }
125
126 pub fn named_while_single(
127 name: &str,
128 cond: Box<dyn Fn(&T) -> bool>,
129 child: Node<T>,
130 ) -> Node<T> {
131 Self::new_named(
132 name.to_owned(),
133 Behavior::While(cond, Rc::new(RefCell::new(child))),
134 )
135 }
136
137 pub fn named_while_single_child(
138 name: &str,
139 cond: Box<dyn Fn(&T) -> bool>,
140 child: Rc<RefCell<Node<T>>>,
141 ) -> Node<T> {
142 Self::new_named(name.to_owned(), Behavior::While(cond, child))
143 }
144
145 pub fn collapse(self, desc: &str) -> Node<T> {
150 Self {
151 collapse_as: Some(desc.to_owned()),
152 ..self
153 }
154 }
155
156 pub fn reset(&mut self) {
157 self.status = Status::Initialized;
158 self.behavior.reset();
159 }
160
161 pub fn tick(&mut self, delta: f64, context: &mut T) -> Status {
162 maybe_profile_function!();
163
164 if self.status == Status::Success || self.status == Status::Failure {
165 self.reset();
166 }
167
168 self.status = self.behavior.tick(delta, context);
169 self.status
170 }
171
172 pub fn children(&self) -> Vec<Rc<RefCell<Node<T>>>> {
173 match &self.behavior {
174 Behavior::Wait { .. } => vec![],
175 Behavior::RandomWait { .. } => vec![],
176 Behavior::Cond(_, _, positive, negative) => vec![positive.clone(), negative.clone()],
177 Behavior::Sequence(_, ref seq) => seq.clone(),
178 Behavior::Select(_, ref seq) => seq.clone(),
179 Behavior::Action(_, _) => vec![],
180 Behavior::ActionSuccess(_, _) => vec![],
181 Behavior::StatefulAction(_, _) => vec![],
182 Behavior::While(_, item) => vec![item.clone()],
183 }
184 }
185
186 pub fn name(&self) -> String {
187 maybe_profile_function!();
188
189 match &self.collapse_as {
190 Some(collapse_text) => collapse_text.clone(),
191 None => {
192 match &self.behavior {
193 Behavior::Wait { curr, max } => format!("Wait {:.2}/{:.2}", curr, max),
194 Behavior::RandomWait {
195 curr,
196 curr_max,
197 max,
198 } => format!("RandomWait {:.2}/{:.2} ({:.2})", curr, curr_max, max),
199 Behavior::Cond(name, _cond, _a, _b) => format!("Cond {}", name),
200 Behavior::Sequence(_, _seq) => "Sequence".to_string(),
203 Behavior::Select(_, _seq) => "Select".to_string(),
210 Behavior::Action(name, _) => format!("Action {}", name),
211 Behavior::ActionSuccess(name, _) => format!("ActionSuccess {}", name),
212 Behavior::StatefulAction(name, _) => format!("StatefulAction {}", name),
213 Behavior::While(_, _x) => {
216 format!(
217 "While {}",
218 self.name.as_ref().expect("While must have a name")
219 )
220 }
221 }
222 }
223 }
224 }
225
226 pub fn recheck_condition(&mut self, context: &T, is_sequence: bool) -> bool {
227 maybe_profile_function!();
228
229 match &self.behavior {
230 Behavior::While(cond, _) => cond(context) != is_sequence,
231 _ => false,
232 }
240 }
241}