behavior_tree_lite/
registry.rs

1use super::{
2    nodes::{
3        FallbackNode, ForceFailureNode, ForceSuccessNode, IfNode, InverterNode, IsTrueNode,
4        ReactiveFallbackNode, ReactiveSequenceNode, RepeatNode, RetryNode, SequenceNode,
5        SetBoolNode,
6    },
7    BehaviorNode, Symbol,
8};
9use std::collections::HashMap;
10
11pub trait Constructor: Fn() -> Box<dyn BehaviorNode> {}
12
13pub fn boxify<T>(cons: impl (Fn() -> T) + 'static) -> Box<dyn Fn() -> Box<dyn BehaviorNode>>
14where
15    for<'a> T: BehaviorNode + 'static,
16{
17    Box::new(move || Box::new(cons()))
18}
19
20pub struct Registry {
21    node_types: HashMap<String, Box<dyn Fn() -> Box<dyn BehaviorNode>>>,
22    pub(crate) key_names: HashMap<String, Symbol>,
23}
24
25impl Default for Registry {
26    fn default() -> Self {
27        let mut ret = Self {
28            node_types: HashMap::new(),
29            key_names: HashMap::new(),
30        };
31        ret.register("Sequence", boxify(SequenceNode::default));
32        ret.register("ReactiveSequence", boxify(ReactiveSequenceNode::default));
33        ret.register("Fallback", boxify(FallbackNode::default));
34        ret.register("ReactiveFallback", boxify(ReactiveFallbackNode::default));
35        ret.register("ForceSuccess", boxify(ForceSuccessNode::default));
36        ret.register("ForceFailure", boxify(ForceFailureNode::default));
37        ret.register("Inverter", boxify(InverterNode::default));
38        ret.register("Repeat", boxify(RepeatNode::default));
39        ret.register("Retry", boxify(RetryNode::default));
40        ret.register("IsTrue", boxify(|| IsTrueNode));
41        ret.register("if", boxify(IfNode::default));
42        ret.register("SetBool", boxify(|| SetBoolNode));
43        ret
44    }
45}
46
47impl Registry {
48    pub fn register(
49        &mut self,
50        type_name: impl ToString,
51        constructor: Box<dyn Fn() -> Box<dyn BehaviorNode>>,
52    ) {
53        self.node_types.insert(type_name.to_string(), constructor);
54    }
55
56    pub fn build(&self, type_name: &str) -> Option<Box<dyn BehaviorNode>> {
57        self.node_types
58            .get(type_name)
59            .map(|constructor| constructor())
60    }
61}