mecha10_behavior_runtime/actions/
timing.rs1use super::elapsed_timer::{reset_timer_field, ElapsedTimer};
4use crate::{BehaviorNode, Context, NodeStatus};
5use async_trait::async_trait;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::time::Duration;
9
10macro_rules! from_json_with_duration {
11 ($config:ident) => {
12 pub fn from_json(config: Value) -> anyhow::Result<Self> {
14 let cfg: $config = serde_json::from_value(config)?;
15 Ok(Self {
16 duration: Duration::from_secs_f64(cfg.duration_secs),
17 timer: ElapsedTimer::default(),
18 })
19 }
20 };
21}
22
23#[derive(Debug, Default)]
24pub struct TimerNode {
25 duration: Duration,
26 timer: ElapsedTimer,
27}
28
29#[derive(Debug, Serialize, Deserialize)]
30struct TimerConfig {
31 duration_secs: f64,
32}
33
34impl TimerNode {
35 from_json_with_duration!(TimerConfig);
36}
37
38#[async_trait]
39impl BehaviorNode for TimerNode {
40 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
41 if self.timer.elapsed_since_start(self.duration) {
42 Ok(NodeStatus::Success)
43 } else {
44 Ok(NodeStatus::Running)
45 }
46 }
47
48 reset_timer_field!(timer);
49
50 fn name(&self) -> &str {
51 "TimerNode"
52 }
53}
54
55#[derive(Debug)]
56pub struct IdleNode;
57
58impl IdleNode {
59 pub fn from_json(_config: Value) -> anyhow::Result<Self> {
61 Ok(Self)
62 }
63}
64
65#[async_trait]
66impl BehaviorNode for IdleNode {
67 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
68 Ok(NodeStatus::Success)
69 }
70
71 fn name(&self) -> &str {
72 "IdleNode"
73 }
74}
75
76#[derive(Debug, Default)]
77pub struct PauseNode {
78 duration: Duration,
79 timer: ElapsedTimer,
80}
81
82#[derive(Debug, Serialize, Deserialize)]
83struct PauseConfig {
84 duration_secs: f64,
85}
86
87impl PauseNode {
88 from_json_with_duration!(PauseConfig);
89}
90
91#[async_trait]
92impl BehaviorNode for PauseNode {
93 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
94 if !self.timer.is_running() {
95 tracing::debug!("PauseNode: starting pause for {:?}", self.duration);
96 }
97
98 if self.timer.elapsed_since_start(self.duration) {
99 tracing::debug!("PauseNode: pause complete");
100 Ok(NodeStatus::Success)
101 } else {
102 Ok(NodeStatus::Running)
103 }
104 }
105
106 reset_timer_field!(timer);
107
108 fn name(&self) -> &str {
109 "PauseNode"
110 }
111}