behavior_tree_lite/
container.rs

1use 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    /// Name of the type of the node
11    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}