use crate::{BehaviorArc, BehaviorNode, NodeResult, ReportStatus};
use std::sync::Arc;
pub struct Succeeder<B> {
child: Option<BehaviorArc<B>>,
has_run: bool,
}
impl<B> std::fmt::Debug for Succeeder<B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Succeeder")
.field("child", &self.child)
.finish()
}
}
impl<B> Clone for Succeeder<B> {
fn clone(&self) -> Self {
Self {
child: self.child.clone(),
has_run: self.has_run,
}
}
}
impl<B> Default for Succeeder<B> {
fn default() -> Self {
Self {
child: None,
has_run: false,
}
}
}
impl<B> Succeeder<B> {
pub fn new(child: BehaviorArc<B>) -> Self {
Self {
child: Some(child),
has_run: false,
}
}
}
impl<B: 'static> BehaviorNode<B> for Succeeder<B> {
fn tick(mut self: Arc<Self>, blackboard: &mut B) -> crate::NodeResult<B> {
if self.child.is_some() {
let inner = Arc::make_mut(&mut self);
if let Some(child) = inner.child.take() {
match child.tick(blackboard) {
NodeResult::Failure | NodeResult::Success => NodeResult::Success,
NodeResult::Running(resume) => {
inner.child = Some(resume);
inner.has_run = true;
NodeResult::Running(self)
}
}
} else {
unreachable!()
}
} else {
NodeResult::Success
}
}
fn status(&self, _parent: ReportStatus, context: &B) -> crate::BehaviorStatus {
let status = if self.has_run {
ReportStatus::Running
} else {
ReportStatus::Unexecuted
};
crate::BehaviorStatus {
name: std::any::type_name_of_val(self).into(),
status,
children: self
.child
.iter()
.map(|c| c.status(status, context))
.collect(),
current: if self.has_run { Some(0) } else { None },
}
}
}
#[cfg(test)]
mod tests {}