#![allow(unused)]
use alloc::boxed::Box;
use core::any::Any;
use dataport::{PortCollection, PortCollectionAccessors, PortCollectionProvider, PortList, PortVec};
use tinyscript::SharedRuntime;
use crate::{
Arc, Behavior, BehaviorCreationFn, BehaviorResult, behavior_data::BehaviorData, behavior_kind::BehaviorKind,
tree::BehaviorTreeElementList,
};
pub type SimpleBhvrTickFn = Arc<Box<dyn Fn() -> BehaviorResult + Send + Sync>>;
pub type ComplexBhvrTickFn = Arc<Box<dyn Fn(&mut BehaviorData, &mut PortVec) -> BehaviorResult + Send + Sync>>;
pub struct SimpleBehavior {
simple_tick_fn: Option<SimpleBhvrTickFn>,
complex_tick_fn: Option<ComplexBhvrTickFn>,
kind: BehaviorKind,
portlist: PortVec,
}
impl crate::behavior_traits::BehaviorExecution for SimpleBehavior {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn kind(&self) -> BehaviorKind {
self.kind
}
fn portlist(&self) -> &dyn PortList {
&self.portlist
}
fn portlist_mut(&mut self) -> &mut dyn PortList {
&mut self.portlist
}
}
#[async_trait::async_trait]
impl crate::behavior_traits::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(crate::error::Error::Composition {
txt: "SimpleBehavior without tick function".into(),
})
},
|func| (func.as_ref())(),
)
},
|func| (func.as_ref())(behavior, &mut self.portlist),
)
}
}
impl PortCollectionProvider for SimpleBehavior {
fn provided_ports(&self) -> &impl PortCollectionAccessors {
&self.portlist
}
fn provided_ports_mut(&mut self) -> &mut impl PortCollectionAccessors {
&mut self.portlist
}
fn port_collection(&self) -> &impl PortCollection {
&self.portlist
}
}
impl SimpleBehavior {
pub fn create(tick_fn: SimpleBhvrTickFn, kind: BehaviorKind) -> Box<BehaviorCreationFn> {
Box::new(move |_blackboard| {
Box::new(Self {
simple_tick_fn: Some(tick_fn.clone()),
complex_tick_fn: None,
kind,
portlist: PortVec::default(),
})
})
}
pub fn create_with_ports(tick_fn: ComplexBhvrTickFn, kind: BehaviorKind, portlist: PortVec) -> Box<BehaviorCreationFn> {
Box::new(move |_blackboard| {
Box::new(Self {
simple_tick_fn: None,
complex_tick_fn: Some(tick_fn.clone()),
kind,
portlist: portlist.clone(),
})
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Mutex;
use tinyscript::Runtime;
#[tokio::test]
async fn tick_without_any_fn_errors() {
let mut behavior = SimpleBehavior {
simple_tick_fn: None,
complex_tick_fn: None,
kind: BehaviorKind::Action,
portlist: PortVec::default(),
};
let mut data = BehaviorData::default();
let mut children = BehaviorTreeElementList::default();
let runtime: SharedRuntime = Arc::new(Mutex::new(Runtime::default()));
let result = behavior
.tick(&mut data, &mut children, &runtime)
.await;
assert!(result.is_err());
}
}