behavior_tree_lite/
container.rs1use std::{cell::Cell, collections::HashMap};
2
3use crate::{
4 error::{AddChildError, AddChildResult},
5 parser::PortMapOwned,
6 BehaviorCallback, BehaviorNode, BehaviorResult, BlackboardValue, Context, NumChildren, Symbol,
7};
8
9pub struct BehaviorNodeContainer {
10 pub(crate) name: String,
12 pub(crate) node: Box<dyn BehaviorNode>,
13 pub(crate) blackboard_map: HashMap<Symbol, BlackboardValue>,
14 pub(crate) child_nodes: Vec<BehaviorNodeContainer>,
15 pub(crate) last_result: Option<BehaviorResult>,
16 pub(crate) is_subtree: bool,
17 pub(crate) subtree_expanded: Cell<bool>,
18}
19
20impl BehaviorNodeContainer {
21 pub fn new(
22 node: Box<dyn BehaviorNode>,
23 blackboard_map: HashMap<Symbol, BlackboardValue>,
24 ) -> Self {
25 Self {
26 name: "".to_owned(),
27 node,
28 blackboard_map,
29 child_nodes: vec![],
30 last_result: None,
31 is_subtree: false,
32 subtree_expanded: Cell::new(false),
33 }
34 }
35
36 pub fn new_raw(node: Box<dyn BehaviorNode>) -> Self {
37 Self {
38 name: "".to_owned(),
39 node,
40 blackboard_map: HashMap::new(),
41 child_nodes: vec![],
42 last_result: None,
43 is_subtree: false,
44 subtree_expanded: Cell::new(false),
45 }
46 }
47
48 pub fn new_node(node: impl BehaviorNode + 'static) -> Self {
49 Self {
50 name: "".to_owned(),
51 node: Box::new(node),
52 blackboard_map: HashMap::new(),
53 child_nodes: vec![],
54 last_result: None,
55 is_subtree: false,
56 subtree_expanded: Cell::new(false),
57 }
58 }
59
60 pub(crate) fn new_raw_with_name(node: Box<dyn BehaviorNode>, name: String) -> Self {
61 Self {
62 name,
63 node,
64 blackboard_map: HashMap::new(),
65 child_nodes: vec![],
66 last_result: None,
67 is_subtree: false,
68 subtree_expanded: Cell::new(false),
69 }
70 }
71
72 pub fn tick(&mut self, arg: BehaviorCallback, ctx: &mut Context) -> BehaviorResult {
73 std::mem::swap(&mut self.child_nodes, &mut ctx.child_nodes.0);
74 std::mem::swap(&mut self.blackboard_map, &mut ctx.blackboard_map);
75 let res = self.node.tick(arg, ctx);
76 std::mem::swap(&mut self.blackboard_map, &mut ctx.blackboard_map);
77 std::mem::swap(&mut self.child_nodes, &mut ctx.child_nodes.0);
78 res
79 }
80
81 pub fn add_child(&mut self, child: BehaviorNodeContainer) -> AddChildResult {
82 if NumChildren::Finite(self.child_nodes.len()) < self.node.max_children() {
83 self.child_nodes.push(child);
84 Ok(())
85 } else {
86 Err(AddChildError::TooManyNodes)
87 }
88 }
89
90 pub fn children(&self) -> &[BehaviorNodeContainer] {
91 &self.child_nodes
92 }
93
94 pub fn last_result(&self) -> Option<BehaviorResult> {
95 self.last_result
96 }
97
98 pub fn name(&self) -> &str {
99 &self.name
100 }
101
102 pub(crate) fn with_name(mut self, name: String) -> Self {
103 self.name = name;
104 self
105 }
106
107 pub fn blackboard_map(&self) -> &HashMap<Symbol, BlackboardValue> {
108 &self.blackboard_map
109 }
110
111 pub fn port_map(&self) -> impl Iterator<Item = PortMapOwned> {
112 let items = self
113 .node
114 .provided_ports()
115 .into_iter()
116 .filter_map(|port| {
117 self.blackboard_map.get(&port.key).map(|mapped| {
118 PortMapOwned::new(
119 port.ty,
120 port.key.to_string(),
121 BlackboardValue::to_owned2(mapped),
122 )
123 })
124 })
125 .collect::<Vec<_>>();
126 items.into_iter()
127 }
128
129 pub fn is_subtree(&self) -> bool {
130 self.is_subtree
131 }
132
133 pub fn is_subtree_expanded(&self) -> bool {
134 self.subtree_expanded.get()
135 }
136
137 pub fn expand_subtree(&self, b: bool) {
138 self.subtree_expanded.set(b);
139 }
140}