diff --git a/bonsai/Cargo.toml b/bonsai/Cargo.toml
index 4498b53..9203bbc 100644
--- a/bonsai/Cargo.toml
+++ b/bonsai/Cargo.toml
@@ -24,6 +24,7 @@ serde = { version = "1.0.137", features = ["derive"], optional = true }
[features]
visualize = ["dep:petgraph"]
+f32 = []
[dev-dependencies]
serde_json = { version = "1.0.81" }
diff --git a/bonsai/src/behavior.rs b/bonsai/src/behavior.rs
index 2b7882a..783fbe4 100644
--- a/bonsai/src/behavior.rs
+++ b/bonsai/src/behavior.rs
@@ -1,6 +1,8 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
+use crate::Float;
+
/// Describes a behavior.
///
/// This is used for more complex event logic.
@@ -10,8 +12,8 @@ use serde::{Deserialize, Serialize};
pub enum Behavior {
/// Waits an amount of time before continuing
///
- /// f64: Time in seconds
- Wait(f64),
+ /// Float: Time in seconds
+ Wait(Float),
/// Wait forever.
WaitForever,
/// A high level description of an action.
@@ -131,20 +133,23 @@ pub enum Behavior {
#[cfg(test)]
#[cfg(feature = "serde")]
mod tests {
- use crate::Behavior::{self, Action, Sequence, Wait, WaitForever, WhenAny, While};
+ use crate::{
+ Behavior::{self, Action, Sequence, Wait, WaitForever, WhenAny, While},
+ Float,
+ };
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug)]
pub(crate) enum EnemyAction {
/// Circles forever around target pos.
Circling,
/// Waits until player is within distance.
- PlayerWithinDistance(f64),
+ PlayerWithinDistance(Float),
/// Fly toward player.
FlyTowardPlayer,
/// Waits until player is far away from target.
- PlayerFarAwayFromTarget(f64),
+ PlayerFarAwayFromTarget(Float),
/// Makes player loose more blood.
- AttackPlayer(f64),
+ AttackPlayer(Float),
}
#[test]
diff --git a/bonsai/src/bt.rs b/bonsai/src/bt.rs
index cd17b51..cc727f4 100644
--- a/bonsai/src/bt.rs
+++ b/bonsai/src/bt.rs
@@ -1,6 +1,6 @@
use std::fmt::Debug;
-use crate::{state::State, ActionArgs, Behavior, Status, UpdateEvent};
+use crate::{state::State, ActionArgs, Behavior, Float, Status, UpdateEvent};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -45,15 +45,15 @@ impl BT {
/// Passes event, delta time in seconds, action and state to closure.
/// The closure should return a status and remaining delta time.
///
- /// return: (Status, f64)
+ /// return: (Status, Float)
/// function returns the result of the tree traversal, and how long
/// it actually took to complete the traversal and propagate the
/// results back up to the root node
#[inline]
- pub fn tick(&mut self, e: &E, f: &mut F) -> Option<(Status, f64)>
+ pub fn tick(&mut self, e: &E, f: &mut F) -> Option<(Status, Float)>
where
E: UpdateEvent,
- F: FnMut(ActionArgs, &mut B) -> (Status, f64),
+ F: FnMut(ActionArgs, &mut B) -> (Status, Float),
{
if self.finished {
return None;
diff --git a/bonsai/src/event.rs b/bonsai/src/event.rs
index 54d0c9d..c3c0530 100644
--- a/bonsai/src/event.rs
+++ b/bonsai/src/event.rs
@@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct UpdateArgs {
/// Delta time in seconds.
- pub dt: f64,
+ pub dt: Float,
}
impl UpdateArgs {
@@ -54,7 +54,7 @@ pub trait UpdateEvent: Sized {
/// Creates an update event.
fn from_update_args(args: &UpdateArgs, old_event: &Self) -> Option;
/// Creates an update event with delta time.
- fn from_dt(dt: f64, old_event: &Self) -> Option {
+ fn from_dt(dt: Float, old_event: &Self) -> Option {
UpdateEvent::from_update_args(&UpdateArgs { dt }, old_event)
}
/// Calls closure if this is an update event.
@@ -84,6 +84,8 @@ impl UpdateEvent for Event {
use std::time::Instant;
+use crate::Float;
+
/// A monotonic clock/timer that can be used to keep track
/// of the time increments (delta time) between tick/tree traversals
/// and the total duration since the behavior tree was first invoked/traversed
@@ -101,18 +103,24 @@ impl Timer {
}
/// Compute duration since timer started
- pub fn duration_since_start(&self) -> f64 {
+ pub fn duration_since_start(&self) -> Float {
let new_now: Instant = Instant::now();
let duration = new_now.duration_since(self.start);
- duration.as_secs_f64()
+ #[cfg(feature = "f32")]
+ return duration.as_secs_f32();
+ #[cfg(not(feature = "f32"))]
+ return duration.as_secs_f64();
}
/// Compute time difference last invocation of `get_dt()` function
- pub fn get_dt(&mut self) -> f64 {
+ pub fn get_dt(&mut self) -> Float {
let new_now: Instant = Instant::now();
let duration = new_now.duration_since(self.now);
self.now = new_now;
- duration.as_secs_f64()
+ #[cfg(feature = "f32")]
+ return duration.as_secs_f32();
+ #[cfg(not(feature = "f32"))]
+ return duration.as_secs_f64();
}
}
diff --git a/bonsai/src/lib.rs b/bonsai/src/lib.rs
index a8f7b57..9defa7b 100644
--- a/bonsai/src/lib.rs
+++ b/bonsai/src/lib.rs
@@ -137,3 +137,9 @@ mod when_all;
#[cfg(feature = "visualize")]
mod visualizer;
+
+#[cfg(feature = "f32")]
+pub type Float = f32;
+
+#[cfg(not(feature = "f32"))]
+pub type Float = f64;
diff --git a/bonsai/src/sequence.rs b/bonsai/src/sequence.rs
index 15e3139..c0fc143 100644
--- a/bonsai/src/sequence.rs
+++ b/bonsai/src/sequence.rs
@@ -1,9 +1,10 @@
use crate::status::Status::*;
+use crate::Float;
use crate::{event::UpdateEvent, state::State, ActionArgs, Behavior, Status, RUNNING};
pub struct SequenceArgs<'a, A, E, F, B> {
pub select: bool,
- pub upd: Option,
+ pub upd: Option,
pub seq: &'a [Behavior],
pub i: &'a mut usize,
pub cursor: &'a mut Box>,
@@ -16,11 +17,11 @@ pub struct SequenceArgs<'a, A, E, F, B> {
//
// `Sequence` fails if any fails and succeeds when all succeeds.
// `Select` succeeds if any succeeds and fails when all fails.
-pub fn sequence(args: SequenceArgs) -> (Status, f64)
+pub fn sequence(args: SequenceArgs) -> (Status, Float)
where
A: Clone,
E: UpdateEvent,
- F: FnMut(ActionArgs, &mut B) -> (Status, f64),
+ F: FnMut(ActionArgs, &mut B) -> (Status, Float),
{
let SequenceArgs {
select,
diff --git a/bonsai/src/state.rs b/bonsai/src/state.rs
index 73064a7..2c7365f 100644
--- a/bonsai/src/state.rs
+++ b/bonsai/src/state.rs
@@ -3,7 +3,7 @@ use crate::sequence::{sequence, SequenceArgs};
use crate::state::State::*;
use crate::status::Status::*;
use crate::when_all::when_all;
-use crate::{Behavior, Status};
+use crate::{Behavior, Float, Status};
use std::fmt::Debug;
#[cfg(feature = "serde")]
@@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
/// The action is still running, and thus the action consumes
/// all the remaining delta time for the tick
-pub const RUNNING: (Status, f64) = (Running, 0.0);
+pub const RUNNING: (Status, Float) = (Running, 0.0);
/// The arguments in the action callback.
pub struct ActionArgs<'a, E: 'a, A: 'a> {
@@ -20,7 +20,7 @@ pub struct ActionArgs<'a, E: 'a, A: 'a> {
/// The remaining delta time. When one action terminates,
/// it can consume some of dt and the remaining is passed
/// onto the next action.
- pub dt: f64,
+ pub dt: Float,
/// The action running.
pub action: &'a A,
}
@@ -36,7 +36,7 @@ pub(crate) enum State {
/// Ignores failures and always return `Success`.
AlwaysSucceed(Box>),
/// Keeps track of waiting for a period of time before continuing.
- Wait { time_to_wait: f64, elapsed_time: f64 },
+ Wait { time_to_wait: Float, elapsed_time: Float },
/// Waits forever.
WaitForever,
/// Keeps track of an `If` behavior.
@@ -196,14 +196,14 @@ impl State {
/// Passes event, delta time in seconds, action and state to closure.
/// The closure should return a status and remaining delta time.
///
- /// return: (Status, f64)
+ /// return: (Status, Float)
/// function returns the result of the tree traversal, and how long
/// it actually took to complete the traversal and propagate the
/// results back up to the root node
- pub fn tick(&mut self, e: &E, blackboard: &mut B, f: &mut F) -> (Status, f64)
+ pub fn tick(&mut self, e: &E, blackboard: &mut B, f: &mut F) -> (Status, Float)
where
E: UpdateEvent,
- F: FnMut(ActionArgs, &mut B) -> (Status, f64),
+ F: FnMut(ActionArgs, &mut B) -> (Status, Float),
{
let upd = e.update(|args| Some(args.dt)).unwrap_or(None);
@@ -413,7 +413,7 @@ impl State {
) => {
// println!("In AfterState: {}", next_success_index);
// Get the least delta time left over.
- let mut min_dt = f64::MAX;
+ let mut min_dt = Float::MAX;
for (j, item) in states.iter_mut().enumerate().skip(*next_success_index) {
match item.tick(e, blackboard, f) {
(Running, _) => {
diff --git a/bonsai/src/visualizer.rs b/bonsai/src/visualizer.rs
index 63def0e..1b601c4 100644
--- a/bonsai/src/visualizer.rs
+++ b/bonsai/src/visualizer.rs
@@ -1,12 +1,12 @@
#![allow(dead_code, unused_imports, unused_variables)]
-use crate::{state::State, Behavior, Select, Sequence, BT};
+use crate::{state::State, Behavior, Float, Select, Sequence, BT};
use petgraph::{graph::Graph, stable_graph::NodeIndex, Direction::Outgoing};
use std::{collections::VecDeque, fmt::Debug};
#[derive(Debug, Clone)]
pub(crate) enum NodeType {
Root,
- Wait(f64),
+ Wait(Float),
WaitForever,
Action(A),
Invert,
@@ -152,7 +152,7 @@ mod tests {
}
// A test state machine that can increment and decrement.
- fn tick(mut acc: i32, dt: f64, bt: &mut BT>) -> (i32, Status, f64) {
+ fn tick(mut acc: i32, dt: Float, bt: &mut BT>) -> (i32, Status, Float) {
let e: Event = UpdateArgs { dt }.into();
let (s, t) = bt
.tick(&e, &mut |args, blackboard| match args.action {
diff --git a/bonsai/src/when_all.rs b/bonsai/src/when_all.rs
index 8a1df76..29503b1 100644
--- a/bonsai/src/when_all.rs
+++ b/bonsai/src/when_all.rs
@@ -1,4 +1,5 @@
use crate::status::Status::*;
+use crate::Float;
use crate::{event::UpdateEvent, state::State, ActionArgs, Status, RUNNING};
// `WhenAll` and `WhenAny` share same algorithm.
@@ -8,16 +9,16 @@ use crate::{event::UpdateEvent, state::State, ActionArgs, Status, RUNNING};
#[rustfmt::skip]
pub fn when_all(
any: bool,
- upd: Option,
+ upd: Option,
cursors: &mut [Option>],
e: &E,
f: &mut F,
blackboard: &mut B,
-) -> (Status, f64)
+) -> (Status, Float)
where
A: Clone,
E: UpdateEvent,
- F: FnMut(ActionArgs, &mut B) -> (Status, f64),
+ F: FnMut(ActionArgs, &mut B) -> (Status, Float),
{
let (status, inv_status) = if any {
// `WhenAny`
@@ -27,7 +28,7 @@ where
(Status::Success, Status::Failure)
};
// Get the least delta time left over.
- let mut min_dt = f64::MAX;
+ let mut min_dt = Float::MAX;
// Count number of terminated events.
let mut terminated = 0;
for cur in cursors.iter_mut() {
diff --git a/bonsai/tests/behavior_tests.rs b/bonsai/tests/behavior_tests.rs
index bfaa03b..fbbe47c 100644
--- a/bonsai/tests/behavior_tests.rs
+++ b/bonsai/tests/behavior_tests.rs
@@ -1,7 +1,7 @@
use crate::behavior_tests::TestActions::{Dec, Inc, LessThan, LessThanRunningSuccess};
use bonsai_bt::{
- Action, ActionArgs, After, AlwaysSucceed, Event, Failure, If, Invert, Select, Sequence, Status::Running, Success,
- UpdateArgs, Wait, WaitForever, WhenAll, While, WhileAll, BT,
+ Action, ActionArgs, After, AlwaysSucceed, Event, Failure, Float, If, Invert, Select, Sequence, Status::Running,
+ Success, UpdateArgs, Wait, WaitForever, WhenAll, While, WhileAll, BT,
};
/// Some test actions.
@@ -18,7 +18,7 @@ enum TestActions {
}
// A test state machine that can increment and decrement.
-fn tick(mut acc: i32, dt: f64, state: &mut BT) -> (i32, bonsai_bt::Status, f64) {
+fn tick(mut acc: i32, dt: Float, state: &mut BT) -> (i32, bonsai_bt::Status, Float) {
let e: Event = UpdateArgs { dt }.into();
println!("acc {}", acc);
let (s, t) = state
@@ -59,7 +59,7 @@ fn tick(mut acc: i32, dt: f64, state: &mut BT) -> (i32, bonsai_
}
// A test state machine that can increment and decrement.
-fn tick_with_ref(acc: &mut i32, dt: f64, state: &mut BT) {
+fn tick_with_ref(acc: &mut i32, dt: Float, state: &mut BT) {
let e: Event = UpdateArgs { dt }.into();
state
diff --git a/bonsai/tests/blackboard_tests.rs b/bonsai/tests/blackboard_tests.rs
index 558dc22..a1abd9d 100644
--- a/bonsai/tests/blackboard_tests.rs
+++ b/bonsai/tests/blackboard_tests.rs
@@ -1,6 +1,6 @@
use std::collections::HashMap;
-use bonsai_bt::{Action, Event, Sequence, Success, UpdateArgs, Wait, BT};
+use bonsai_bt::{Action, Event, Float, Sequence, Success, UpdateArgs, Wait, BT};
use crate::blackboard_tests::TestActions::{Dec, Inc};
@@ -14,7 +14,7 @@ pub enum TestActions {
}
// A test state machine that can increment and decrement.
-fn tick(mut acc: i32, dt: f64, bt: &mut BT>) -> i32 {
+fn tick(mut acc: i32, dt: Float, bt: &mut BT>) -> i32 {
let e: Event = UpdateArgs { dt }.into();
let (_s, _t) = bt
diff --git a/bonsai/tests/bt_tests.rs b/bonsai/tests/bt_tests.rs
index 4b96552..50ff582 100644
--- a/bonsai/tests/bt_tests.rs
+++ b/bonsai/tests/bt_tests.rs
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use crate::bt_tests::TestActions::{Dec, Inc, LessThan};
-use bonsai_bt::{Action, Behavior::Select, Event, Failure, Success, UpdateArgs, BT};
+use bonsai_bt::{Action, Behavior::Select, Event, Failure, Float, Success, UpdateArgs, BT};
/// Some test actions.
#[derive(Clone, Debug)]
@@ -15,7 +15,7 @@ enum TestActions {
}
// A test state machine that can increment and decrement.
-fn tick(mut acc: i32, dt: f64, bt: &mut BT>) -> (i32, bonsai_bt::Status, f64) {
+fn tick(mut acc: i32, dt: Float, bt: &mut BT>) -> (i32, bonsai_bt::Status, Float) {
let e: Event = UpdateArgs { dt }.into();
println!("acc {}", acc);
let (s, t) = bt
diff --git a/bonsai/tests/dynamic_behavior_tests.rs b/bonsai/tests/dynamic_behavior_tests.rs
index 4ae1df4..19d43db 100644
--- a/bonsai/tests/dynamic_behavior_tests.rs
+++ b/bonsai/tests/dynamic_behavior_tests.rs
@@ -1,7 +1,7 @@
use crate::dynamic_behavior_tests::TestActions::{DynamicWait, Inc};
-use bonsai_bt::{Action, ActionArgs, Event, Success, UpdateArgs, Wait, While, BT, RUNNING};
+use bonsai_bt::{Action, ActionArgs, Event, Float, Success, UpdateArgs, Wait, While, BT, RUNNING};
-type Times = Vec;
+type Times = Vec;
/// Some test actions.
#[derive(Clone, Debug)]
enum TestActions {
@@ -12,7 +12,7 @@ enum TestActions {
}
// A test state machine that can increment and decrement.
-fn tick(mut acc: usize, dt: f64, t: &mut f64, counter: &mut usize, state: &mut BT) -> usize {
+fn tick(mut acc: usize, dt: Float, t: &mut Float, counter: &mut usize, state: &mut BT) -> usize {
let e: Event = UpdateArgs { dt }.into();
let (_s, _t) = state
@@ -49,7 +49,7 @@ fn tick(mut acc: usize, dt: f64, t: &mut f64, counter: &mut usize, state: &mut B
fn test_alter_wait_time() {
let a: usize = 0;
let mut counter = 0;
- let mut timer: f64 = 0.0;
+ let mut timer: Float = 0.0;
let rep = While(
Box::new(Wait(50.0)),
vec![Action(DynamicWait(vec![1.0, 2.0, 3.0])), Action(Inc)],
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index ab78381..fd94ad5 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -25,6 +25,9 @@ rand = "0.8"
serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.81"
+[features]
+f32 = ["bonsai-bt/f32"]
+
[[bin]]
name = "async_drone"
path = "src/async_drone/main.rs"
diff --git a/examples/src/3d/main.rs b/examples/src/3d/main.rs
index c4f6e79..094bb8d 100644
--- a/examples/src/3d/main.rs
+++ b/examples/src/3d/main.rs
@@ -1,6 +1,6 @@
use bonsai_bt::Behavior::{If, Invert, Wait, WhenAny, While};
use bonsai_bt::Status::{self};
-use bonsai_bt::{Action, RUNNING};
+use bonsai_bt::{Action, Float, RUNNING};
use bonsai_bt::{Event, Status::Failure, Status::Success, UpdateArgs};
use bonsai_bt::{Timer, BT};
use kiss3d::event::EventManager;
@@ -24,7 +24,7 @@ pub enum Animation {
/// check for events with the mouse
MouseCallback,
/// time has passed longer than
- LongerThan(f64),
+ LongerThan(Float),
/// counter
///
/// Random complex condition
diff --git a/examples/src/boids/boid.rs b/examples/src/boids/boid.rs
index d3075ee..dea8876 100644
--- a/examples/src/boids/boid.rs
+++ b/examples/src/boids/boid.rs
@@ -1,4 +1,4 @@
-use bonsai_bt::{Event, Status::Success, UpdateArgs, BT, RUNNING};
+use bonsai_bt::{Event, Float, Status::Success, UpdateArgs, BT, RUNNING};
use ggez::mint;
use std::collections::HashMap;
@@ -54,9 +54,9 @@ impl Boid {
}
}
-pub fn game_tick(dt: f32, cursor: mint::Point2, boid: &mut Boid, other_boids: Vec) {
+pub fn game_tick(dt: Float, cursor: mint::Point2, boid: &mut Boid, other_boids: Vec) {
// proceed to next iteration in event loop
- let e: Event = UpdateArgs { dt: dt.into() }.into();
+ let e: Event = UpdateArgs { dt }.into();
// unwrap bt for boid
let mut bt = boid.bt.clone();
diff --git a/examples/src/boids/main.rs b/examples/src/boids/main.rs
index 8453d5e..13d589a 100644
--- a/examples/src/boids/main.rs
+++ b/examples/src/boids/main.rs
@@ -1,7 +1,7 @@
mod boid;
use boid::{game_tick, Action};
-use bonsai_bt::BT;
+use bonsai_bt::{Float, BT};
use ggez::{conf, event, graphics, input, timer, Context, ContextBuilder, GameResult};
use std::collections::HashMap;
@@ -86,7 +86,18 @@ impl event::EventHandler for GameState {
for i in 0..(self.boids).len() {
let boids_vec = self.boids.to_vec();
let b = &mut self.boids[i];
- game_tick(self.dt.as_secs_f32(), input::mouse::position(ctx), b, boids_vec);
+
+ let dt: Float = {
+ #[cfg(feature = "f32")]
+ {
+ self.dt.as_secs_f32()
+ }
+ #[cfg(not(feature = "f32"))]
+ {
+ self.dt.as_secs_f64()
+ }
+ };
+ game_tick(dt, input::mouse::position(ctx), b, boids_vec);
//Convert new velocity to postion change
b.x += b.dx * tick;