use crate::{
BehaviorDescription, BehaviorTreeFactory,
behavior::{
Behavior, BehaviorData, BehaviorExecution, BehaviorKind, BehaviorResult, BehaviorState,
error::Error as BehaviorError,
},
port::PortList,
tree::BehaviorTreeElementList,
};
use alloc::boxed::Box;
use tinyscript::SharedRuntime;
pub struct SubTree;
impl BehaviorExecution for SubTree {
fn as_any(&self) -> &dyn core::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
self
}
fn creation_fn() -> Box<crate::behavior::BehaviorCreationFn> {
alloc::boxed::Box::new(|| alloc::boxed::Box::new(Self))
}
fn kind() -> crate::prelude::BehaviorKind {
BehaviorKind::SubTree
}
fn static_provided_ports(&self) -> PortList {
Self::provided_ports()
}
}
#[async_trait::async_trait]
impl Behavior for SubTree {
#[inline]
fn on_start(
&mut self,
behavior: &mut BehaviorData,
children: &mut BehaviorTreeElementList,
_runtime: &SharedRuntime,
) -> Result<(), BehaviorError> {
if children.is_empty() || children.len() > 1 {
return Err(BehaviorError::Composition {
txt: "a subtree must have exactly 1 child".into(),
});
}
behavior.set_state(BehaviorState::Running);
Ok(())
}
async fn tick(
&mut self,
_behavior: &mut BehaviorData,
children: &mut BehaviorTreeElementList,
runtime: &SharedRuntime,
) -> BehaviorResult {
children[0].tick(runtime).await
}
}
impl SubTree {
fn create_fn() -> Box<crate::behavior::BehaviorCreationFn> {
alloc::boxed::Box::new(|| alloc::boxed::Box::new(Self))
}
pub fn register(factory: &mut BehaviorTreeFactory, name: &str) -> Result<(), crate::factory::error::Error> {
let bhvr_desc = BehaviorDescription::new(name, name, BehaviorKind::SubTree, true, Self::provided_ports());
let bhvr_creation_fn = Self::create_fn();
factory
.registry_mut()
.add_behavior(bhvr_desc, bhvr_creation_fn)
}
}