behaviortree-core 0.1.0

Core implementaion of behaviortree
Documentation
// Copyright © 2026 Stephan Kunz
//! Core implementation of behaviortree.
#![no_std]
#![doc = include_str!("../README.md")]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[doc(hidden)]
extern crate alloc;
#[cfg(feature = "std")]
#[doc(hidden)]
extern crate std;

pub mod behavior_data;
pub mod behavior_description;
pub mod behavior_kind;
pub mod behavior_state;
pub mod behavior_traits;
pub mod behaviors;
pub mod error;
pub mod pre_post_conditions;
pub mod tree;
pub mod xml;

#[doc(hidden)]
pub extern crate portable_atomic_util;
#[doc(hidden)]
pub extern crate spin;

// re-export Arc, Mutex, RwLock & Guards
#[allow(unused)]
pub use dataport::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};

// exports:
pub use behavior_data::BehaviorData;
pub use behavior_description::BehaviorDescription;
pub use behavior_kind::BehaviorKind;
pub use behavior_state::BehaviorState;
pub use behavior_traits::{Behavior, BehaviorExecution, BehaviorRegistry};
#[cfg(feature = "mock_behavior")]
pub use behaviors::mock_behavior::{MockBehavior, MockBehaviorConfig};
#[cfg(feature = "simple_behavior")]
pub use behaviors::simple_behavior::{ComplexBhvrTickFn, SimpleBehavior, SimpleBhvrTickFn};
pub use error::Error;
pub use pre_post_conditions::{POST_CONDITIONS, PRE_CONDITIONS};
#[cfg(feature = "observer")]
pub use tree::observer::tree_observer::BehaviorTreeObserver;
pub use tree::{BehaviorTree, BehaviorTreeElement, BehaviorTreeElementList, TreeElementKind};
#[cfg(feature = "groot")]
pub use tree::{BehaviorTreeMessage, observer::groot2::connector_data::Groot2ConnectorData};
#[cfg(feature = "groot")]
pub use xml::creator::XmlCreator;

#[cfg(all(feature = "groot", not(feature = "std")))]
pub use tree::observer::groot2::connector_no_std::Groot2Connector;
#[cfg(all(feature = "groot", feature = "std"))]
pub use tree::observer::groot2::connector_std::Groot2Connector;

// re-exports
pub use dataport::create_port_array;

/// An immutable thread safe `String` type
/// see: [Logan Smith](https://www.youtube.com/watch?v=A4cKi7PTJSs).
type ConstString = crate::Arc<str>;

/// Often needed empty str
pub const EMPTY_STR: &str = "";

/// [`BehaviorKind`] literal "Action"
pub const ACTION: &str = "Action";
/// [`BehaviorKind`] literal "Condition"
pub const CONDITION: &str = "Condition";
/// [`BehaviorKind`] literal "Control"
pub const CONTROL: &str = "Control";
/// [`BehaviorKind`] literal "Decorator"
pub const DECORATOR: &str = "Decorator";
/// [`BehaviorKind`] literal `"SubTree"`
pub const SUBTREE: &str = "SubTree";

/// [`BehaviorState`] literal "Failure"
pub const FAILURE: &str = "Failure";
/// [`BehaviorState`] literal "Idle"
pub const IDLE: &str = "Idle";
/// [`BehaviorState`] literal "Running"
pub const RUNNING: &str = "Running";
/// [`BehaviorState`] literal "Skipped"
pub const SKIPPED: &str = "Skipped";
/// [`BehaviorState`] literal "Success"
pub const SUCCESS: &str = "Success";

/// Literals for scripting ports
pub const AUTOREMAP: &str = "_autoremap";
pub const FAILURE_IF: &str = "_failureIf";
pub const SUCCESS_IF: &str = "_successIf";
pub const SKIP_IF: &str = "_skipIf";
pub const WHILE: &str = "_while";
pub const ON_HALTED: &str = "_onHalted";
pub const ON_FAILURE: &str = "_onFailure";
pub const ON_SUCCESS: &str = "_onSuccess";
pub const POST: &str = "_post";

/// Literal "name" for ports etc.
pub const NAME: &str = "name";
/// Literal "ID" for ports etc.
pub const ID: &str = "ID";
/// Literal "default" for ports etc.
pub const DEFAULT: &str = "default";

/// Pointer to a behavior.
pub type BehaviorPtr = alloc::boxed::Box<dyn crate::behavior_traits::BehaviorExecution>;

/// Result type definition for behaviors.
pub type BehaviorResult<Output = BehaviorState> = Result<Output, Error>;

/// Type alias for a behavior creation function
pub type BehaviorCreationFn = dyn Fn(databoard::Databoard) -> BehaviorPtr + Send + Sync;

/// [`BehaviorData`] state change callback signature.
///
/// This callback can be used to observe [`BehaviorData`] and manipulate the resulting [`BehaviorState`] of a tick.
pub type BehaviorTickCallback = dyn Fn(&BehaviorData, &mut BehaviorState) + Send + Sync;

/// Creation macro for [`PortArray`](dataport::PortArray) init function
#[macro_export]
macro_rules! port_array_init {
	($size:literal, $($content:expr),+ $(,)?) => {
		#[allow(unused)]
		fn port_collection_init(blackboard: &databoard::Databoard) -> Result<dataport::PortArray<$size>, behaviortree_core::error::Error> {
			Ok($crate::create_port_array!($($content,)+))
		}
	};
}

/// Macro to register enums for scripting.
/// Enum must derive [`ScriptEnum`](https://docs.rs/tinyscript/latest/tinyscript/trait.ScriptEnum.html).
/// It is also possible to register discrete value(s).
///
/// # Usage:
///
/// With an enum type:
/// ```no-test
/// register_scripting_enum!(<mutable reference to behavior registry>, <enum to register>)
/// ```
///
/// With discrete value(s)
/// ```no-test
/// register_scripting_enum!(<mutable reference to behavior registry>, <Identifier as str>, <Value as int>)
/// ```
///
/// # Examples:
///
/// ```no-test
/// #[derive(ScriptEnum)]
/// enum Color {
///     RED,
///     BLUE,
///     GREEN,
/// }
///
/// register_scripting_enum!(registry, Color);
/// ```
///
/// ```no-test
/// register_scripting_enum!(registry "THE_ANSWER", 42, "OTHER_ANSWER", 44);
/// ```
#[macro_export]
macro_rules! register_scripting_enum {
	// register an enum type
	($registry:ident, $tp:ty) => {
		for (key, value) in <$tp>::key_value_tuples() {
			$registry.register_enum_tuple(key, value)?;
		}
	};
	// register a key value pair
	($registry:ident, $($key:literal, $value:literal),+ $(,)?) => {
		$( $registry.register_enum_tuple($key, $value)?; )+;
	};
}