behaviortree-core 0.1.0

Core implementaion of behaviortree
Documentation
// Copyright © 2025 Stephan Kunz
//! [`SubTree`]  implementation.

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,
};

/// A `Subtree` is a placeholder for behavior (sub)trees with its own [`BehaviorKind`].
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 {
	/// Creates a `creation_fn()` for a `SubTree` with the given configuration.
	fn create_fn() -> Box<crate::BehaviorCreationFn> {
		alloc::boxed::Box::new(|_blackboard| alloc::boxed::Box::new(Self))
	}

	/// Registers the `SubTree` behavior in the factory.
	/// # Errors
	/// - if registration fails
	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)
	}
}