use super::{Behavior, BehaviorCreationFn, BehaviorExecution, BehaviorResult};
use crate::{BehaviorKind, behavior::BehaviorData, port::PortList, tree::BehaviorTreeElementList};
use alloc::{boxed::Box, sync::Arc};
use core::any::Any;
use tinyscript::SharedRuntime;
pub type SimpleBhvrTickFn = Arc<dyn Fn() -> BehaviorResult + Send + Sync>;
pub type ComplexBhvrTickFn = Arc<dyn Fn(&mut BehaviorData) -> BehaviorResult + Send + Sync>;
#[derive(Default)]
pub struct SimpleBehavior {
simple_tick_fn: Option<SimpleBhvrTickFn>,
complex_tick_fn: Option<ComplexBhvrTickFn>,
provided_ports: PortList,
}
impl BehaviorExecution for SimpleBehavior {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn creation_fn() -> Box<BehaviorCreationFn> {
alloc::boxed::Box::new(|| alloc::boxed::Box::new(Self::default()))
}
fn kind() -> BehaviorKind {
BehaviorKind::Action
}
fn static_provided_ports(&self) -> PortList {
self.provided_ports.clone()
}
}
#[async_trait::async_trait]
impl Behavior for SimpleBehavior {
async fn tick(
&mut self,
behavior: &mut BehaviorData,
_children: &mut BehaviorTreeElementList,
_runtime: &SharedRuntime,
) -> BehaviorResult {
self.complex_tick_fn.as_ref().map_or_else(
|| {
self.simple_tick_fn.as_ref().map_or_else(
|| {
Err(super::BehaviorError::Composition {
txt: "SimpleBehavior without tick function".into(),
})
},
|func| func(),
)
},
|func| func(behavior),
)
}
}
impl SimpleBehavior {
pub fn create(tick_fn: SimpleBhvrTickFn) -> Box<BehaviorCreationFn> {
Box::new(move || {
Box::new(Self {
simple_tick_fn: Some(tick_fn.clone()),
complex_tick_fn: None,
provided_ports: PortList::default(),
})
})
}
pub fn new_create_with_ports(tick_fn: ComplexBhvrTickFn, port_list: PortList) -> Box<BehaviorCreationFn> {
Box::new(move || {
Box::new(Self {
simple_tick_fn: None,
complex_tick_fn: Some(tick_fn.clone()),
provided_ports: port_list.clone(),
})
})
}
}