Skip to main content

behaviortree_rs/nodes/control/
while_do_else.rs

1use behaviortree_rs_derive::bt_node;
2
3use crate::{
4    basic_types::NodeStatus,
5    nodes::{NodeError, NodeResult},
6};
7
8/// WhileDoElse must have exactly 2 or 3 children.
9/// It is a REACTIVE node of IfThenElseNode.
10///
11/// The first child is the "statement" that is executed at each tick
12///
13/// If result is SUCCESS, the second child is executed.
14///
15/// If result is FAILURE, the third child is executed.
16///
17/// If the 2nd or 3d child is RUNNING and the statement changes,
18/// the RUNNING child will be stopped before starting the sibling.
19#[bt_node(ControlNode)]
20pub struct WhileDoElseNode {}
21
22#[bt_node(ControlNode)]
23impl WhileDoElseNode {
24    async fn tick(&mut self) -> NodeResult {
25        let children_count = node_.children.len();
26        // Node should only have 2 or 3 children
27        if !(2..=3).contains(&children_count) {
28            return Err(NodeError::NodeStructureError(
29                "IfThenElseNode must have either 2 or 3 children.".to_string(),
30            ));
31        }
32
33        node_.status = NodeStatus::Running;
34
35        let condition_status = node_.children[0].execute_tick().await?;
36
37        if matches!(condition_status, NodeStatus::Running) {
38            return Ok(NodeStatus::Running);
39        }
40
41        let mut status = NodeStatus::Idle;
42
43        match condition_status {
44            NodeStatus::Success => {
45                if children_count == 3 {
46                    node_.halt_child_idx(2).await?;
47                }
48
49                status = node_.children[1].execute_tick().await?;
50            }
51            NodeStatus::Failure => match children_count {
52                3 => {
53                    node_.halt_child_idx(1).await?;
54                    status = node_.children[2].execute_tick().await?;
55                }
56                2 => {
57                    status = NodeStatus::Failure;
58                }
59                _ => {}
60            },
61            _ => {}
62        }
63
64        match status {
65            NodeStatus::Running => Ok(NodeStatus::Running),
66            status => {
67                node_.reset_children().await;
68                Ok(status)
69            }
70        }
71    }
72
73    async fn halt(&mut self) {
74        node_.reset_children().await;
75    }
76}