animgraph/processors/
timed_event.rs1use serde_derive::{Deserialize, Serialize};
2
3use crate::{
4 io::{Event, EventEmit, NumberRef, Timer},
5 FlowState, GraphBoolean, GraphNodeConstructor, Seconds,
6};
7
8use super::{GraphNode, GraphVisitor};
9
10#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
11pub struct TimedEventNode {
12 pub timer: Timer,
13 pub event: Event,
14 pub condition: GraphBoolean,
15 pub duration: NumberRef<Seconds>,
16 pub emit: EventEmit,
17 pub elapsed: bool,
18}
19
20impl GraphNodeConstructor for TimedEventNode {
21 fn identity() -> &'static str {
22 "timed_event"
23 }
24
25 fn construct_entry(
26 self,
27 metrics: &crate::GraphMetrics,
28 ) -> anyhow::Result<crate::GraphNodeEntry> {
29 metrics.validate_timer(&self.timer, Self::identity())?;
30 metrics.validate_event(&self.event, Self::identity())?;
31 metrics.validate_bool(self.condition, Self::identity())?;
32 metrics.validate_number_ref(&self.duration, Self::identity())?;
33 Ok(crate::GraphNodeEntry::Process(Box::new(self)))
34 }
35}
36
37impl GraphNode for TimedEventNode {
38 fn visit(&self, visitor: &mut GraphVisitor) {
39 let emit = if visitor.graph.get_bool(self.condition) {
40 self.emit
41 } else {
42 EventEmit::Never
43 };
44
45 let duration = self.duration.get(visitor.graph);
46
47 let in_event = if self.elapsed {
48 self.timer.elapsed(visitor.graph).0 >= duration.0
49 } else {
50 self.timer.remaining(visitor.graph).0 <= duration.0
51 };
52
53 let state = if in_event {
54 visitor.graph.get_state(visitor.context.state)
55 } else {
56 FlowState::Exited
57 };
58
59 self.event.emit(visitor, state, emit);
60 }
61}
62
63#[cfg(feature = "compiler")]
64pub mod compile {
65 use serde_derive::{Deserialize, Serialize};
66 use serde_json::Value;
67
68 use crate::{
69 compiler::prelude::{
70 Extras, IOSlot, IOType, Node, NodeCompilationError, NodeCompiler,
71 NodeSerializationContext, NodeSettings,
72 },
73 io::{Event, EventEmit, Timer},
74 GraphNodeConstructor, Seconds,
75 };
76
77 pub use super::TimedEventNode;
78
79 #[derive(Debug, Clone, Serialize, Deserialize, Default)]
80 pub struct TimedEventSettings {
81 pub emit: EventEmit,
82 pub elapsed: bool,
83 }
84
85 impl NodeSettings for TimedEventSettings {
86 fn name() -> &'static str {
87 TimedEventNode::identity()
88 }
89
90 fn input() -> &'static [(&'static str, IOType)] {
91 use IOType::*;
92 &[
93 ("timer", Timer),
94 ("event", Event),
95 ("condition", Bool),
96 ("duration", Number),
97 ]
98 }
99
100 fn output() -> &'static [(&'static str, IOType)] {
101 &[]
102 }
103
104 fn build(self) -> anyhow::Result<Extras> {
105 Ok(serde_json::to_value(self)?)
106 }
107 }
108
109 impl NodeCompiler for TimedEventNode {
110 type Settings = TimedEventSettings;
111 fn build<'a>(
112 context: &NodeSerializationContext<'a>,
113 ) -> Result<Value, NodeCompilationError> {
114 let timer = context.input_timer(0)?;
115 let event = context.input_event(1)?;
116 let condition = context.input_bool(2)?;
117 let duration = context.input_number::<Seconds>(3)?;
118 let settings = context.settings::<TimedEventSettings>()?;
119
120 context.serialize_node(TimedEventNode {
121 timer,
122 event,
123 condition,
124 duration,
125 emit: settings.emit,
126 elapsed: settings.elapsed,
127 })
128 }
129 }
130
131 pub fn remaining_event(
132 timer: impl IOSlot<Timer>,
133 event: impl IOSlot<Event>,
134 condition: impl IOSlot<bool>,
135 duration: impl IOSlot<Seconds>,
136 emit: EventEmit,
137 ) -> Node {
138 let settings = TimedEventSettings {
139 emit,
140 elapsed: false,
141 };
142 let input = vec![
143 timer.into_slot("timer"),
144 event.into_slot("event"),
145 condition.into_slot("condition"),
146 duration.into_slot("duration"),
147 ];
148 Node::new(input, vec![], settings).expect("Valid")
149 }
150}