use alloc::boxed::Box;
use tinyscript::SharedRuntime;
use crate::{
BehaviorResult, behavior_data::BehaviorData, behavior_description::BehaviorDescription, behavior_kind::BehaviorKind,
behavior_state::BehaviorState, behavior_traits::BehaviorRegistry, error::Error, tree::BehaviorTreeElementList,
};
pub struct SubTree;
impl crate::behavior_traits::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 kind(&self) -> BehaviorKind {
BehaviorKind::SubTree
}
fn portlist(&self) -> &dyn dataport::PortList {
dataport::EMPTY_PORT_ARRAY.get()
}
fn portlist_mut(&mut self) -> &mut dyn dataport::PortList {
dataport::EMPTY_PORT_ARRAY.get_mut()
}
}
#[async_trait::async_trait]
impl crate::behavior_traits::Behavior for SubTree {
fn on_start(
&mut self,
behavior: &mut BehaviorData,
children: &mut BehaviorTreeElementList,
_runtime: &SharedRuntime,
) -> Result<(), Error> {
if children.is_empty() || children.len() > 1 {
return Err(Error::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::BehaviorCreationFn> {
alloc::boxed::Box::new(|_blackboard| alloc::boxed::Box::new(Self))
}
pub fn register(registry: &mut impl BehaviorRegistry, name: &str) -> Result<(), Error> {
let bhvr_desc = BehaviorDescription::new(name, name, true);
let bhvr_creation_fn = Self::create_fn();
registry.add_behavior(bhvr_desc, bhvr_creation_fn)
}
}