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 {
15 ($config:ident) => {
16 pub fn from_json(config: Value) -> anyhow::Result<Self> {
18 let cfg: $config = serde_json::from_value(config)?;
19 Ok(Self {
20 duration: Duration::from_secs_f64(cfg.duration_secs),
21 timer: ElapsedTimer::default(),
22 })
23 }
24 };
25}
26
27#[derive(Debug, Default)]
42pub struct TimerNode {
43 duration: Duration,
44 timer: ElapsedTimer,
45}
46
47#[derive(Debug, Serialize, Deserialize)]
48struct TimerConfig {
49 duration_secs: f64,
50}
51
52impl TimerNode {
53 from_json_with_duration!(TimerConfig);
54}
55
56#[async_trait]
57impl BehaviorNode for TimerNode {
58 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
59 if self.timer.elapsed_since_start(self.duration) {
60 Ok(NodeStatus::Success)
61 } else {
62 Ok(NodeStatus::Running)
63 }
64 }
65
66 reset_timer_field!(timer);
67
68 fn name(&self) -> &str {
69 "TimerNode"
70 }
71}
72
73#[derive(Debug)]
87pub struct IdleNode;
88
89impl IdleNode {
90 pub fn from_json(_config: Value) -> anyhow::Result<Self> {
92 Ok(Self)
93 }
94}
95
96#[async_trait]
97impl BehaviorNode for IdleNode {
98 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
99 Ok(NodeStatus::Success)
100 }
101
102 fn name(&self) -> &str {
103 "IdleNode"
104 }
105}
106
107#[derive(Debug, Default)]
123pub struct PauseNode {
124 duration: Duration,
125 timer: ElapsedTimer,
126}
127
128#[derive(Debug, Serialize, Deserialize)]
129struct PauseConfig {
130 duration_secs: f64,
131}
132
133impl PauseNode {
134 from_json_with_duration!(PauseConfig);
135}
136
137#[async_trait]
138impl BehaviorNode for PauseNode {
139 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
140 if !self.timer.is_running() {
141 tracing::debug!("PauseNode: starting pause for {:?}", self.duration);
142 }
143
144 if self.timer.elapsed_since_start(self.duration) {
145 tracing::debug!("PauseNode: pause complete");
146 Ok(NodeStatus::Success)
147 } else {
148 Ok(NodeStatus::Running)
149 }
150 }
151
152 reset_timer_field!(timer);
153
154 fn name(&self) -> &str {
155 "PauseNode"
156 }
157}