Skip to main content

bonsai_bt/
event.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4/// Update arguments, such as delta time in seconds.
5/// To move the behavior tree forward in time it must be ticked on each iteration of the
6/// game/application loop.
7///
8/// dt: states how much forward in time we should move the behavior tree
9#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct UpdateArgs {
12    /// Delta time in seconds.
13    pub dt: Float,
14}
15
16impl UpdateArgs {
17    /// Creates [UpdateArgs] with `0.0` delta time.
18    pub fn zero_dt() -> UpdateArgs {
19        Self { dt: 0.0 }
20    }
21}
22
23/// Models loop events.
24#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub enum Loop {
27    /// Update the state of the application.
28    Update(UpdateArgs),
29}
30
31impl From<UpdateArgs> for Event {
32    fn from(args: UpdateArgs) -> Self {
33        Event::Loop(Loop::Update(args))
34    }
35}
36
37/// Models all events.
38#[derive(Clone)]
39pub enum Event {
40    /// Input events.
41    ///
42    /// Events that commonly used by event loops.
43    Loop(Loop),
44}
45impl Event {
46    /// Creates [Event] from [UpdateArgs] with `0.0` delta time.
47    pub fn zero_dt_args() -> Self {
48        UpdateArgs::zero_dt().into()
49    }
50}
51
52/// When the application state should be updated.
53pub trait UpdateEvent: Sized {
54    /// Creates an update event.
55    fn from_update_args(args: &UpdateArgs, old_event: &Self) -> Option<Self>;
56    /// Creates an update event with delta time.
57    fn from_dt(dt: Float, old_event: &Self) -> Option<Self> {
58        UpdateEvent::from_update_args(&UpdateArgs { dt }, old_event)
59    }
60    /// Calls closure if this is an update event.
61    fn update<U, F>(&self, f: F) -> Option<U>
62    where
63        F: FnMut(&UpdateArgs) -> U;
64    /// Returns update arguments.
65    fn update_args(&self) -> Option<UpdateArgs> {
66        self.update(|args| *args)
67    }
68}
69
70impl UpdateEvent for Event {
71    fn from_update_args(args: &UpdateArgs, _old_event: &Self) -> Option<Self> {
72        Some(Event::Loop(Loop::Update(*args)))
73    }
74
75    fn update<U, F>(&self, mut f: F) -> Option<U>
76    where
77        F: FnMut(&UpdateArgs) -> U,
78    {
79        match *self {
80            Event::Loop(Loop::Update(ref args)) => Some(f(args)),
81        }
82    }
83}
84
85use std::time::Instant;
86
87use crate::Float;
88
89/// A monotonic clock/timer that can be used to keep track
90/// of the time increments (delta time) between tick/tree traversals
91/// and the total duration since the behavior tree was first invoked/traversed
92#[derive(Debug, Clone)]
93pub struct Timer {
94    start: Instant,
95    now: Instant,
96}
97
98impl Timer {
99    /// Initialize monotonic clock
100    pub fn init_time() -> Timer {
101        let init = Instant::now();
102        Timer { start: init, now: init }
103    }
104
105    /// Compute duration since timer started
106    pub fn duration_since_start(&self) -> Float {
107        let new_now: Instant = Instant::now();
108        let duration = new_now.duration_since(self.start);
109        #[cfg(feature = "f32")]
110        return duration.as_secs_f32();
111        #[cfg(not(feature = "f32"))]
112        return duration.as_secs_f64();
113    }
114
115    /// Compute time difference last invocation of `get_dt()` function
116    pub fn get_dt(&mut self) -> Float {
117        let new_now: Instant = Instant::now();
118        let duration = new_now.duration_since(self.now);
119        self.now = new_now;
120        #[cfg(feature = "f32")]
121        return duration.as_secs_f32();
122        #[cfg(not(feature = "f32"))]
123        return duration.as_secs_f64();
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130    use std::thread::sleep;
131    use std::time::Duration;
132
133    #[test]
134    fn test_update_args() {
135        use Event;
136        use UpdateArgs;
137
138        let e: Event = UpdateArgs { dt: 0.0 }.into();
139        let _: Option<Event> = UpdateEvent::from_update_args(&UpdateArgs { dt: 1.0 }, &e);
140    }
141
142    #[test]
143    fn test_timer() {
144        let mut timer = Timer::init_time();
145        sleep(Duration::new(0, 0.1e+9 as u32));
146        let duration = timer.duration_since_start();
147        let dt = timer.get_dt();
148
149        assert!(duration < 1.0);
150        assert!(dt < 0.2);
151        assert!(dt >= 0.1);
152
153        sleep(Duration::new(0, 0.3e+9 as u32));
154        let duration = timer.duration_since_start();
155        let dt = timer.get_dt();
156
157        assert!(duration < 1.0);
158        assert!(duration > 0.3);
159        assert!(dt > 0.2);
160        assert!(dt < 0.4);
161    }
162}