1use bevy::{
4 math::{Vec2, Vec3},
5 platform::time::Instant,
6 reflect::Reflect,
7};
8use serde::{Deserialize, Serialize};
9
10use crate::buttonlike::ButtonValue;
11#[cfg(feature = "timing")]
12use crate::timing::Timing;
13use crate::{InputControlKind, buttonlike::ButtonState};
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Reflect)]
20pub struct ActionData {
21 pub disabled: bool,
25 pub kind_data: ActionKindData,
27}
28
29impl ActionData {
30 pub fn from_kind(input_control_kind: InputControlKind) -> Self {
32 Self {
33 disabled: false,
34 kind_data: match input_control_kind {
35 InputControlKind::Button => ActionKindData::Button(ButtonData::default()),
36 InputControlKind::Axis => ActionKindData::Axis(AxisData::default()),
37 InputControlKind::DualAxis => ActionKindData::DualAxis(DualAxisData::default()),
38 InputControlKind::TripleAxis => {
39 ActionKindData::TripleAxis(TripleAxisData::default())
40 }
41 },
42 }
43 }
44
45 pub fn tick(&mut self, _current_instant: Instant, _previous_instant: Instant) {
47 match self.kind_data {
48 ActionKindData::Button(ref mut data) => {
49 data.state.tick();
50
51 #[cfg(feature = "timing")]
52 data.timing.tick(_current_instant, _previous_instant);
53 }
54 ActionKindData::Axis(ref mut _data) => {}
55 ActionKindData::DualAxis(ref mut _data) => {}
56 ActionKindData::TripleAxis(ref mut _data) => {}
57 }
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Reflect)]
63pub enum ActionKindData {
64 Button(ButtonData),
66 Axis(AxisData),
68 DualAxis(DualAxisData),
70 TripleAxis(TripleAxisData),
72}
73
74impl ActionKindData {
75 pub(super) fn swap_to_update_state(&mut self) {
76 match self {
79 Self::Button(data) => {
80 data.fixed_update_state = data.state;
81 data.fixed_update_value = data.value;
82 data.state = data.update_state;
83 data.value = data.update_value;
84 }
85 Self::Axis(data) => {
86 data.fixed_update_value = data.value;
87 data.value = data.update_value;
88 }
89 Self::DualAxis(data) => {
90 data.fixed_update_pair = data.pair;
91 data.pair = data.update_pair;
92 }
93 Self::TripleAxis(data) => {
94 data.fixed_update_triple = data.triple;
95 data.triple = data.update_triple;
96 }
97 }
98 }
99
100 pub(super) fn swap_to_fixed_update_state(&mut self) {
101 match self {
104 Self::Button(data) => {
105 data.update_state = data.state;
106 data.update_value = data.value;
107 data.state = data.fixed_update_state;
108 data.value = data.fixed_update_value;
109 }
110 Self::Axis(data) => {
111 data.update_value = data.value;
112 data.value = data.fixed_update_value;
113 }
114 Self::DualAxis(data) => {
115 data.update_pair = data.pair;
116 data.pair = data.fixed_update_pair;
117 }
118 Self::TripleAxis(data) => {
119 data.update_triple = data.triple;
120 data.triple = data.fixed_update_triple;
121 }
122 }
123 }
124
125 pub(super) fn set_update_state_from_state(&mut self) {
127 match self {
128 Self::Button(data) => {
129 data.update_state = data.state;
130 data.update_value = data.value;
131 }
132 Self::Axis(data) => {
133 data.update_value = data.value;
134 }
135 Self::DualAxis(data) => {
136 data.update_pair = data.pair;
137 }
138 Self::TripleAxis(data) => {
139 data.update_triple = data.triple;
140 }
141 }
142 }
143
144 pub(super) fn set_fixed_update_state_from_state(&mut self) {
146 match self {
147 Self::Button(data) => {
148 data.fixed_update_state = data.state;
149 data.fixed_update_value = data.value;
150 }
151 Self::Axis(data) => {
152 data.fixed_update_value = data.value;
153 }
154 Self::DualAxis(data) => {
155 data.fixed_update_pair = data.pair;
156 }
157 Self::TripleAxis(data) => {
158 data.fixed_update_triple = data.triple;
159 }
160 }
161 }
162}
163
164#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, Reflect)]
166pub struct ButtonData {
167 pub state: ButtonState,
169 pub update_state: ButtonState,
171 pub fixed_update_state: ButtonState,
173 pub value: f32,
175 pub update_value: f32,
177 pub fixed_update_value: f32,
179 #[cfg(feature = "timing")]
181 pub timing: Timing,
182}
183
184impl ButtonData {
185 pub const JUST_PRESSED: Self = Self {
187 state: ButtonState::JustPressed,
188 update_state: ButtonState::JustPressed,
189 fixed_update_state: ButtonState::JustPressed,
190 value: 1.0,
191 update_value: 1.0,
192 fixed_update_value: 1.0,
193 #[cfg(feature = "timing")]
194 timing: Timing::NEW,
195 };
196
197 pub const JUST_RELEASED: Self = Self {
199 state: ButtonState::JustReleased,
200 update_state: ButtonState::JustReleased,
201 fixed_update_state: ButtonState::JustReleased,
202 value: 0.0,
203 update_value: 0.0,
204 fixed_update_value: 0.0,
205 #[cfg(feature = "timing")]
206 timing: Timing::NEW,
207 };
208
209 pub const RELEASED: Self = Self {
215 state: ButtonState::Released,
216 update_state: ButtonState::Released,
217 fixed_update_state: ButtonState::Released,
218 value: 0.0,
219 update_value: 0.0,
220 fixed_update_value: 0.0,
221 #[cfg(feature = "timing")]
222 timing: Timing::NEW,
223 };
224
225 #[inline]
227 #[must_use]
228 pub fn pressed(&self) -> bool {
229 self.state.pressed()
230 }
231
232 #[inline]
234 #[must_use]
235 pub fn just_pressed(&self) -> bool {
236 self.state.just_pressed()
237 }
238
239 #[inline]
241 #[must_use]
242 pub fn released(&self) -> bool {
243 self.state.released()
244 }
245
246 #[inline]
248 #[must_use]
249 pub fn just_released(&self) -> bool {
250 self.state.just_released()
251 }
252
253 #[inline]
255 #[must_use]
256 pub fn to_button_value(&self) -> ButtonValue {
257 ButtonValue::new(self.state.pressed(), self.value)
258 }
259}
260
261#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, Reflect)]
263pub struct AxisData {
264 pub value: f32,
266 pub update_value: f32,
268 pub fixed_update_value: f32,
270}
271
272#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, Reflect)]
274pub struct DualAxisData {
275 pub pair: Vec2,
277 pub update_pair: Vec2,
279 pub fixed_update_pair: Vec2,
281}
282
283#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, Reflect)]
285pub struct TripleAxisData {
286 pub triple: Vec3,
288 pub update_triple: Vec3,
290 pub fixed_update_triple: Vec3,
292}
293
294#[cfg(test)]
295mod tests {
296 use crate::buttonlike::ButtonState;
297
298 #[test]
299 fn test_tick_triple_axis() {
300 use super::ActionData;
301 use super::ActionKindData;
302 use super::TripleAxisData;
303 use bevy::platform::time::Instant;
304
305 let mut action_data = ActionData {
306 disabled: false,
307 kind_data: ActionKindData::TripleAxis(TripleAxisData {
308 triple: bevy::math::Vec3::new(1.0, 2.0, 3.0),
309 update_triple: bevy::math::Vec3::new(4.0, 5.0, 6.0),
310 fixed_update_triple: bevy::math::Vec3::new(7.0, 8.0, 9.0),
311 }),
312 };
313
314 let previous_instant = Instant::now();
315 let current_instant = previous_instant + std::time::Duration::from_secs(1);
316
317 action_data.tick(current_instant, previous_instant);
318
319 if let ActionKindData::TripleAxis(data) = &action_data.kind_data {
320 assert_eq!(data.triple, bevy::math::Vec3::new(1.0, 2.0, 3.0));
321 } else {
322 panic!("Expected TripleAxisData");
323 }
324 }
325
326 #[test]
327 fn test_swap_update_to_update_state_triple_axis() {
328 use super::ActionData;
329 use super::ActionKindData;
330 use super::TripleAxisData;
331 use bevy::math::Vec3;
332
333 let mut action_data = ActionData {
334 disabled: false,
335 kind_data: ActionKindData::TripleAxis(TripleAxisData {
336 triple: Vec3::new(1.0, 2.0, 3.0),
337 update_triple: Vec3::new(4.0, 5.0, 6.0),
338 fixed_update_triple: Vec3::new(7.0, 8.0, 9.0),
339 }),
340 };
341
342 action_data.kind_data.swap_to_update_state();
343
344 if let ActionKindData::TripleAxis(data) = &action_data.kind_data {
345 assert_eq!(data.triple, Vec3::new(4.0, 5.0, 6.0));
346 } else {
347 panic!("Expected TripleAxisData");
348 }
349 }
350
351 #[test]
352 fn test_swap_to_fixed_update_state_triple_axis() {
353 use super::ActionData;
354 use super::ActionKindData;
355 use super::TripleAxisData;
356 use bevy::math::Vec3;
357
358 let mut action_data = ActionData {
359 disabled: false,
360 kind_data: ActionKindData::TripleAxis(TripleAxisData {
361 triple: Vec3::new(1.0, 2.0, 3.0),
362 update_triple: Vec3::new(4.0, 5.0, 6.0),
363 fixed_update_triple: Vec3::new(7.0, 8.0, 9.0),
364 }),
365 };
366
367 action_data.kind_data.swap_to_fixed_update_state();
368
369 if let ActionKindData::TripleAxis(data) = &action_data.kind_data {
370 assert_eq!(data.triple, Vec3::new(7.0, 8.0, 9.0));
371 } else {
372 panic!("Expected TripleAxisData");
373 }
374 }
375
376 #[test]
377 fn test_set_update_state_from_state_axis() {
378 use super::ActionData;
379 use super::ActionKindData;
380 use super::AxisData;
381
382 let mut action_data = ActionData {
383 disabled: false,
384 kind_data: ActionKindData::Axis(AxisData {
385 value: 1.0,
386 update_value: 2.0,
387 fixed_update_value: 3.0,
388 }),
389 };
390
391 action_data.kind_data.set_update_state_from_state();
392
393 if let ActionKindData::Axis(data) = &action_data.kind_data {
394 assert_eq!(data.update_value, 1.0);
395 } else {
396 panic!("Expected AxisData");
397 }
398 }
399
400 #[test]
401 fn test_set_update_state_from_state_dual_axis() {
402 use super::ActionData;
403 use super::ActionKindData;
404 use super::DualAxisData;
405 use bevy::math::Vec2;
406
407 let mut action_data = ActionData {
408 disabled: false,
409 kind_data: ActionKindData::DualAxis(DualAxisData {
410 pair: Vec2::new(1.0, 2.0),
411 update_pair: Vec2::new(3.0, 4.0),
412 fixed_update_pair: Vec2::new(5.0, 6.0),
413 }),
414 };
415
416 action_data.kind_data.set_update_state_from_state();
417
418 if let ActionKindData::DualAxis(data) = &action_data.kind_data {
419 assert_eq!(data.update_pair, Vec2::new(1.0, 2.0));
420 } else {
421 panic!("Expected DualAxisData");
422 }
423 }
424
425 #[test]
426 fn test_set_update_state_from_state_triple_axis() {
427 use super::ActionData;
428 use super::ActionKindData;
429 use super::TripleAxisData;
430 use bevy::math::Vec3;
431
432 let mut action_data = ActionData {
433 disabled: false,
434 kind_data: ActionKindData::TripleAxis(TripleAxisData {
435 triple: Vec3::new(1.0, 2.0, 3.0),
436 update_triple: Vec3::new(4.0, 5.0, 6.0),
437 fixed_update_triple: Vec3::new(7.0, 8.0, 9.0),
438 }),
439 };
440
441 action_data.kind_data.set_update_state_from_state();
442
443 if let ActionKindData::TripleAxis(data) = &action_data.kind_data {
444 assert_eq!(data.update_triple, Vec3::new(1.0, 2.0, 3.0));
445 } else {
446 panic!("Expected TripleAxisData");
447 }
448 }
449
450 #[test]
451 fn test_set_fixed_update_state_from_state_button() {
452 use super::ActionData;
453 use super::ActionKindData;
454 use super::ButtonData;
455
456 let mut action_data = ActionData {
457 disabled: false,
458 kind_data: ActionKindData::Button(ButtonData {
459 state: ButtonState::Pressed,
460 update_state: ButtonState::JustPressed,
461 fixed_update_state: ButtonState::Released,
462 value: 1.0,
463 update_value: 0.5,
464 fixed_update_value: 0.0,
465 #[cfg(feature = "timing")]
466 timing: Default::default(),
467 }),
468 };
469
470 action_data.kind_data.set_fixed_update_state_from_state();
471 if let ActionKindData::Button(data) = &action_data.kind_data {
472 assert_eq!(data.fixed_update_state, ButtonState::Pressed);
473 assert_eq!(data.fixed_update_value, 1.0);
474 } else {
475 panic!("Expected ButtonData");
476 }
477 }
478
479 #[test]
480 fn test_set_fixed_update_state_from_state_axis() {
481 use super::ActionData;
482 use super::ActionKindData;
483 use super::AxisData;
484
485 let mut action_data = ActionData {
486 disabled: false,
487 kind_data: ActionKindData::Axis(AxisData {
488 value: 1.0,
489 update_value: 2.0,
490 fixed_update_value: 3.0,
491 }),
492 };
493
494 action_data.kind_data.set_fixed_update_state_from_state();
495
496 if let ActionKindData::Axis(data) = &action_data.kind_data {
497 assert_eq!(data.fixed_update_value, 1.0);
498 } else {
499 panic!("Expected AxisData");
500 }
501 }
502
503 #[test]
504 fn test_set_fixed_update_state_from_state_dual_axis() {
505 use super::ActionData;
506 use super::ActionKindData;
507 use super::DualAxisData;
508 use bevy::math::Vec2;
509
510 let mut action_data = ActionData {
511 disabled: false,
512 kind_data: ActionKindData::DualAxis(DualAxisData {
513 pair: Vec2::new(1.0, 2.0),
514 update_pair: Vec2::new(3.0, 4.0),
515 fixed_update_pair: Vec2::new(5.0, 6.0),
516 }),
517 };
518
519 action_data.kind_data.set_fixed_update_state_from_state();
520
521 if let ActionKindData::DualAxis(data) = &action_data.kind_data {
522 assert_eq!(data.fixed_update_pair, Vec2::new(1.0, 2.0));
523 } else {
524 panic!("Expected DualAxisData");
525 }
526 }
527
528 #[test]
529 fn test_set_fixed_update_state_from_state_triple_axis() {
530 use super::ActionData;
531 use super::ActionKindData;
532 use super::TripleAxisData;
533 use bevy::math::Vec3;
534
535 let mut action_data = ActionData {
536 disabled: false,
537 kind_data: ActionKindData::TripleAxis(TripleAxisData {
538 triple: Vec3::new(1.0, 2.0, 3.0),
539 update_triple: Vec3::new(4.0, 5.0, 6.0),
540 fixed_update_triple: Vec3::new(7.0, 8.0, 9.0),
541 }),
542 };
543
544 action_data.kind_data.set_fixed_update_state_from_state();
545
546 if let ActionKindData::TripleAxis(data) = &action_data.kind_data {
547 assert_eq!(data.fixed_update_triple, Vec3::new(1.0, 2.0, 3.0));
548 } else {
549 panic!("Expected TripleAxisData");
550 }
551 }
552}