leafwing_input_manager/
timing.rs1use bevy::{platform::time::Instant, reflect::Reflect};
4use core::time::Duration;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Reflect)]
12pub struct Timing {
13 #[serde(skip)]
17 pub instant_started: Option<Instant>,
18 pub current_duration: Duration,
22 pub previous_duration: Duration,
24}
25
26impl Timing {
27 pub const NEW: Timing = Timing {
29 instant_started: None,
30 current_duration: Duration::ZERO,
31 previous_duration: Duration::ZERO,
32 };
33}
34
35impl PartialOrd for Timing {
36 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
37 self.current_duration.partial_cmp(&other.current_duration)
38 }
39}
40
41impl Timing {
42 pub fn tick(&mut self, current_instant: Instant, previous_instant: Instant) {
47 if let Some(instant_started) = self.instant_started {
48 self.current_duration = current_instant - instant_started;
49 } else {
50 self.current_duration = current_instant - previous_instant;
51 self.instant_started = Some(previous_instant);
52 }
53 }
54
55 pub fn flip(&mut self) {
59 self.previous_duration = self.current_duration;
60 self.current_duration = Duration::ZERO;
61 self.instant_started = None;
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use crate as leafwing_input_manager;
68 use bevy::prelude::Reflect;
69 use leafwing_input_manager_macros::Actionlike;
70
71 #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
72 enum Action {
73 Run,
74 Jump,
75 Hide,
76 }
77
78 #[test]
79 fn time_tick_ticks_away() {
80 use crate::action_state::ActionState;
81 use bevy::platform::time::Instant;
82 use core::time::Duration;
83
84 let mut action_state = ActionState::<Action>::default();
85
86 assert!(action_state.released(&Action::Run));
88 assert!(!action_state.just_released(&Action::Jump));
89
90 action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
92 assert!(action_state.released(&Action::Jump));
93 assert!(!action_state.just_released(&Action::Jump));
94 action_state.press(&Action::Jump);
95 assert!(action_state.just_pressed(&Action::Jump));
96
97 action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
99 assert!(action_state.pressed(&Action::Jump));
100 assert!(!action_state.just_pressed(&Action::Jump));
101 }
102
103 #[test]
104 #[ignore = "Behavior has subtly changed around Bevy 0.16, needs investigation"]
105 fn durations() {
106 use crate::action_state::ActionState;
107 use bevy::platform::time::Instant;
108 use core::time::Duration;
109
110 let mut action_state = ActionState::<Action>::default();
111
112 assert!(action_state.released(&Action::Jump));
114 assert_eq!(action_state.instant_started(&Action::Jump), None,);
115 assert_eq!(action_state.current_duration(&Action::Jump), Duration::ZERO);
116 assert_eq!(
117 action_state.previous_duration(&Action::Jump),
118 Duration::ZERO
119 );
120
121 action_state.press(&Action::Jump);
123 assert!(action_state.pressed(&Action::Jump));
124 assert_eq!(action_state.instant_started(&Action::Jump), None);
125 assert_eq!(action_state.current_duration(&Action::Jump), Duration::ZERO);
126 assert_eq!(
127 action_state.previous_duration(&Action::Jump),
128 Duration::ZERO
129 );
130
131 let t0 = Instant::now();
133 let t1 = t0 + Duration::new(1, 0);
134
135 action_state.tick(t1, t0);
136 assert_eq!(action_state.instant_started(&Action::Jump), Some(t0));
137 assert_eq!(action_state.current_duration(&Action::Jump), t1 - t0);
138 assert_eq!(
139 action_state.previous_duration(&Action::Jump),
140 Duration::ZERO
141 );
142
143 let t2 = t1 + Duration::new(5, 0);
145
146 action_state.tick(t2, t1);
148 assert_eq!(action_state.instant_started(&Action::Jump), Some(t0));
149 assert_eq!(action_state.current_duration(&Action::Jump), t2 - t0);
150 assert_eq!(
151 action_state.previous_duration(&Action::Jump),
152 Duration::ZERO
153 );
154
155 action_state.release(&Action::Jump);
157 assert_eq!(action_state.instant_started(&Action::Jump), None);
158 assert_eq!(action_state.current_duration(&Action::Jump), Duration::ZERO);
159 assert_eq!(action_state.previous_duration(&Action::Jump), t2 - t0);
160 }
161}