bevior_tree 0.11.0

Behavior tree plugin for Bevy.
Documentation
use super::ConverterStrategy;
use super::ResultConverter;
use crate as bevior_tree;
use crate::node::prelude::*;

pub mod prelude {
    pub use super::{ForceResult, Invert};
}

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug)]
struct InvertStrategy;
#[cfg_attr(feature = "serde", typetag::serde)]
impl ConverterStrategy for InvertStrategy {
    fn convert(&self, result: NodeResult) -> NodeResult {
        !result
    }
}

/// Invert the result of the child.
#[delegate_node(delegate)]
pub struct Invert {
    delegate: ResultConverter,
}
impl Invert {
    pub fn new(child: impl Node) -> Self {
        Self {
            delegate: ResultConverter::new(child, InvertStrategy),
        }
    }
}

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug)]
struct ForceResultStrategy {
    result: NodeResult,
}
#[cfg_attr(feature = "serde", typetag::serde)]
impl ConverterStrategy for ForceResultStrategy {
    fn convert(&self, _result: NodeResult) -> NodeResult {
        self.result
    }
}

/// Returns the specified result whatever the child returns.
#[delegate_node(delegate)]
pub struct ForceResult {
    delegate: ResultConverter,
}
impl ForceResult {
    pub fn new(child: impl Node, result: NodeResult) -> Self {
        Self {
            delegate: ResultConverter::new(child, ForceResultStrategy { result }),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::tester_util::prelude::*;

    #[test]
    fn test_invert() {
        let mut app = App::new();
        app.add_plugins((TesterPlugin, BehaviorTreePlugin::default()));
        let task = TesterTask0::new(1, NodeResult::Success);
        let converter = Invert::new(task);
        let tree = BehaviorTree::from_node(
            converter,
            &mut app.world_mut().resource_mut::<Assets<BehaviorTreeRoot>>(),
        );
        let entity = app.world_mut().spawn(tree).id();
        app.update();
        app.update();
        let status = app.world().get::<TreeStatus>(entity);
        assert!(
            if let Some(TreeStatus(NodeStatus::Complete(result))) = status {
                result == &NodeResult::Failure
            } else {
                false
            },
            "Invert should match the result."
        );
    }

    #[test]
    fn test_force_result() {
        let mut app = App::new();
        app.add_plugins((TesterPlugin, BehaviorTreePlugin::default()));
        let task = TesterTask0::new(1, NodeResult::Success);
        let converter = ForceResult::new(task, NodeResult::Failure);
        let tree = BehaviorTree::from_node(
            converter,
            &mut app.world_mut().resource_mut::<Assets<BehaviorTreeRoot>>(),
        );
        let entity = app.world_mut().spawn(tree).id();
        app.update();
        app.update();
        let status = app.world().get::<TreeStatus>(entity);
        assert!(
            if let Some(TreeStatus(NodeStatus::Complete(result))) = status {
                result == &NodeResult::Failure
            } else {
                false
            },
            "ForceResult should match the result."
        );
    }
}