Skip to main content

behaviortree_core/
lib.rs

1// Copyright © 2026 Stephan Kunz
2//! Core implementation of behaviortree.
3#![no_std]
4#![doc = include_str!("../README.md")]
5
6#[cfg(doctest)]
7doc_comment::doctest!("../README.md");
8
9#[doc(hidden)]
10extern crate alloc;
11#[cfg(feature = "std")]
12#[doc(hidden)]
13extern crate std;
14
15pub mod behavior_data;
16pub mod behavior_description;
17pub mod behavior_kind;
18pub mod behavior_state;
19pub mod behavior_traits;
20pub mod behaviors;
21pub mod error;
22pub mod pre_post_conditions;
23pub mod tree;
24pub mod xml;
25
26#[doc(hidden)]
27pub extern crate portable_atomic_util;
28#[doc(hidden)]
29pub extern crate spin;
30
31// re-export Arc, Mutex, RwLock & Guards
32#[allow(unused)]
33pub use dataport::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
34
35// exports:
36pub use behavior_data::BehaviorData;
37pub use behavior_description::BehaviorDescription;
38pub use behavior_kind::BehaviorKind;
39pub use behavior_state::BehaviorState;
40pub use behavior_traits::{Behavior, BehaviorExecution, BehaviorRegistry};
41#[cfg(feature = "mock_behavior")]
42pub use behaviors::mock_behavior::{MockBehavior, MockBehaviorConfig};
43#[cfg(feature = "simple_behavior")]
44pub use behaviors::simple_behavior::{ComplexBhvrTickFn, SimpleBehavior, SimpleBhvrTickFn};
45pub use error::Error;
46pub use pre_post_conditions::{POST_CONDITIONS, PRE_CONDITIONS};
47#[cfg(feature = "observer")]
48pub use tree::observer::tree_observer::BehaviorTreeObserver;
49pub use tree::{BehaviorTree, BehaviorTreeElement, BehaviorTreeElementList, TreeElementKind};
50#[cfg(feature = "groot")]
51pub use tree::{BehaviorTreeMessage, observer::groot2::connector_data::Groot2ConnectorData};
52#[cfg(feature = "groot")]
53pub use xml::creator::XmlCreator;
54
55#[cfg(all(feature = "groot", not(feature = "std")))]
56pub use tree::observer::groot2::connector_no_std::Groot2Connector;
57#[cfg(all(feature = "groot", feature = "std"))]
58pub use tree::observer::groot2::connector_std::Groot2Connector;
59
60// re-exports
61pub use dataport::create_port_array;
62
63/// An immutable thread safe `String` type
64/// see: [Logan Smith](https://www.youtube.com/watch?v=A4cKi7PTJSs).
65type ConstString = crate::Arc<str>;
66
67/// Often needed empty str
68pub const EMPTY_STR: &str = "";
69
70/// [`BehaviorKind`] literal "Action"
71pub const ACTION: &str = "Action";
72/// [`BehaviorKind`] literal "Condition"
73pub const CONDITION: &str = "Condition";
74/// [`BehaviorKind`] literal "Control"
75pub const CONTROL: &str = "Control";
76/// [`BehaviorKind`] literal "Decorator"
77pub const DECORATOR: &str = "Decorator";
78/// [`BehaviorKind`] literal `"SubTree"`
79pub const SUBTREE: &str = "SubTree";
80
81/// [`BehaviorState`] literal "Failure"
82pub const FAILURE: &str = "Failure";
83/// [`BehaviorState`] literal "Idle"
84pub const IDLE: &str = "Idle";
85/// [`BehaviorState`] literal "Running"
86pub const RUNNING: &str = "Running";
87/// [`BehaviorState`] literal "Skipped"
88pub const SKIPPED: &str = "Skipped";
89/// [`BehaviorState`] literal "Success"
90pub const SUCCESS: &str = "Success";
91
92/// Literals for scripting ports
93pub const AUTOREMAP: &str = "_autoremap";
94pub const FAILURE_IF: &str = "_failureIf";
95pub const SUCCESS_IF: &str = "_successIf";
96pub const SKIP_IF: &str = "_skipIf";
97pub const WHILE: &str = "_while";
98pub const ON_HALTED: &str = "_onHalted";
99pub const ON_FAILURE: &str = "_onFailure";
100pub const ON_SUCCESS: &str = "_onSuccess";
101pub const POST: &str = "_post";
102
103/// Literal "name" for ports etc.
104pub const NAME: &str = "name";
105/// Literal "ID" for ports etc.
106pub const ID: &str = "ID";
107/// Literal "default" for ports etc.
108pub const DEFAULT: &str = "default";
109
110/// Pointer to a behavior.
111pub type BehaviorPtr = alloc::boxed::Box<dyn crate::behavior_traits::BehaviorExecution>;
112
113/// Result type definition for behaviors.
114pub type BehaviorResult<Output = BehaviorState> = Result<Output, Error>;
115
116/// Type alias for a behavior creation function
117pub type BehaviorCreationFn = dyn Fn(databoard::Databoard) -> BehaviorPtr + Send + Sync;
118
119/// [`BehaviorData`] state change callback signature.
120///
121/// This callback can be used to observe [`BehaviorData`] and manipulate the resulting [`BehaviorState`] of a tick.
122pub type BehaviorTickCallback = dyn Fn(&BehaviorData, &mut BehaviorState) + Send + Sync;
123
124/// Creation macro for [`PortArray`](dataport::PortArray) init function
125#[macro_export]
126macro_rules! port_array_init {
127	($size:literal, $($content:expr),+ $(,)?) => {
128		#[allow(unused)]
129		fn port_collection_init(blackboard: &databoard::Databoard) -> Result<dataport::PortArray<$size>, behaviortree_core::error::Error> {
130			Ok($crate::create_port_array!($($content,)+))
131		}
132	};
133}
134
135/// Macro to register enums for scripting.
136/// Enum must derive [`ScriptEnum`](https://docs.rs/tinyscript/latest/tinyscript/trait.ScriptEnum.html).
137/// It is also possible to register discrete value(s).
138///
139/// # Usage:
140///
141/// With an enum type:
142/// ```no-test
143/// register_scripting_enum!(<mutable reference to behavior registry>, <enum to register>)
144/// ```
145///
146/// With discrete value(s)
147/// ```no-test
148/// register_scripting_enum!(<mutable reference to behavior registry>, <Identifier as str>, <Value as int>)
149/// ```
150///
151/// # Examples:
152///
153/// ```no-test
154/// #[derive(ScriptEnum)]
155/// enum Color {
156///     RED,
157///     BLUE,
158///     GREEN,
159/// }
160///
161/// register_scripting_enum!(registry, Color);
162/// ```
163///
164/// ```no-test
165/// register_scripting_enum!(registry "THE_ANSWER", 42, "OTHER_ANSWER", 44);
166/// ```
167#[macro_export]
168macro_rules! register_scripting_enum {
169	// register an enum type
170	($registry:ident, $tp:ty) => {
171		for (key, value) in <$tp>::key_value_tuples() {
172			$registry.register_enum_tuple(key, value)?;
173		}
174	};
175	// register a key value pair
176	($registry:ident, $($key:literal, $value:literal),+ $(,)?) => {
177		$( $registry.register_enum_tuple($key, $value)?; )+;
178	};
179}