leafwing_input_manager/action_state/
mod.rs

1//! This module contains [`ActionState`] and its supporting methods and impls.
2
3use crate::buttonlike::ButtonValue;
4use crate::input_map::UpdatedValue;
5use crate::{Actionlike, InputControlKind};
6use crate::{action_diff::ActionDiff, input_map::UpdatedActions};
7
8use bevy::platform::{collections::HashMap, time::Instant};
9use bevy::prelude::Resource;
10use bevy::reflect::Reflect;
11use bevy::{ecs::component::Component, prelude::ReflectComponent};
12use bevy::{
13    math::{Vec2, Vec3},
14    prelude::ReflectResource,
15};
16#[cfg(feature = "timing")]
17use core::time::Duration;
18use serde::{Deserialize, Serialize};
19
20mod action_data;
21pub use action_data::*;
22
23/// Stores the canonical input-method-agnostic representation of the inputs received
24///
25/// Can be used as either a resource or as a [`Component`] on entities that you wish to control directly from player input.
26///
27/// # Disabling actions
28///
29/// Actions can be disabled in four different ways, with increasing granularity:
30///
31/// 1. By disabling updates to all actions using a run condition on [`InputManagerSystem::Update`](crate::plugin::InputManagerSystem::Update).
32/// 2. By disabling updates to all actions of type `A` using a run condition on [`TickActionStateSystem::<A>`](crate::plugin::TickActionStateSystem).
33/// 3. By setting a specific action state to disabled using [`ActionState::disable`].
34/// 4. By disabling a specific action using [`ActionState::disable_action`].
35///
36/// More general mechanisms of disabling actions will cause specific mechanisms to be ignored.
37/// For example, if an entire action state is disabled, then enabling or disabling individual actions will have no effect.
38///
39/// Actions that are disabled will report as released (but not just released), and their values will be zero.
40/// Under the hood, their values are still updated to avoid surprising behavior when re-enabled,
41/// but they are not reported to the user using standard methods like [`ActionState::pressed`].
42/// To check the underlying values, access their [`ActionData`] directly.
43///
44/// # Example
45///
46/// ```rust
47/// use bevy::reflect::Reflect;
48/// use leafwing_input_manager::prelude::*;
49/// use bevy::platform::time::Instant;
50///
51/// #[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
52/// enum Action {
53///     Left,
54///     Right,
55///     Jump,
56/// }
57///
58/// let mut action_state = ActionState::<Action>::default();
59///
60/// // Typically, this is done automatically by the `InputManagerPlugin` from user inputs
61/// // using the `ActionState::update` method
62/// action_state.press(&Action::Jump);
63///
64/// assert!(action_state.pressed(&Action::Jump));
65/// assert!(action_state.just_pressed(&Action::Jump));
66/// assert!(action_state.released(&Action::Left));
67///
68/// // Resets just_pressed and just_released
69/// let t0 = Instant::now();
70/// let t1 = Instant::now();
71///
72///  action_state.tick(t1, t0);
73/// assert!(action_state.pressed(&Action::Jump));
74/// assert!(!action_state.just_pressed(&Action::Jump));
75///
76/// action_state.release(&Action::Jump);
77/// assert!(!action_state.pressed(&Action::Jump));
78/// assert!(action_state.released(&Action::Jump));
79/// assert!(action_state.just_released(&Action::Jump));
80///
81/// let t2 = Instant::now();
82/// action_state.tick(t2, t1);
83/// assert!(action_state.released(&Action::Jump));
84/// assert!(!action_state.just_released(&Action::Jump));
85/// ```
86#[derive(Resource, Component, Clone, Debug, PartialEq, Serialize, Deserialize, Reflect)]
87#[reflect(Resource, Component)]
88pub struct ActionState<A: Actionlike> {
89    /// Whether or not all of the actions are disabled.
90    disabled: bool,
91    /// The shared action data for each action
92    action_data: HashMap<A, ActionData>,
93}
94
95// The derive does not work unless A: Default,
96// so we have to implement it manually
97impl<A: Actionlike> Default for ActionState<A> {
98    fn default() -> Self {
99        Self {
100            disabled: false,
101            action_data: HashMap::default(),
102        }
103    }
104}
105
106impl<A: Actionlike> ActionState<A> {
107    /// Returns a reference to the complete [`ActionData`] for all actions.
108    #[inline]
109    #[must_use]
110    pub fn all_action_data(&self) -> &HashMap<A, ActionData> {
111        &self.action_data
112    }
113
114    /// We are about to enter the `Main` schedule, so we:
115    /// - save all the changes applied to `state` into the `fixed_update_state`
116    /// - switch to loading the `update_state`
117    pub(crate) fn swap_to_update_state(&mut self) {
118        for action_datum in self.action_data.values_mut() {
119            action_datum.kind_data.swap_to_update_state();
120        }
121    }
122
123    /// We are about to enter the `FixedMain` schedule, so we:
124    /// - save all the changes applied to `state` into the `update_state`
125    /// - switch to loading the `fixed_update_state`
126    pub(crate) fn swap_to_fixed_update_state(&mut self) {
127        for action_datum in self.action_data.values_mut() {
128            action_datum.kind_data.swap_to_fixed_update_state();
129        }
130    }
131
132    /// Function for advanced users to override the `state` from the `update_state`
133    pub fn set_update_state_from_state(&mut self) {
134        for action_datum in self.action_data.values_mut() {
135            action_datum.kind_data.set_update_state_from_state();
136        }
137    }
138
139    /// Function for advanced users to override the `state` from the `fixed_update_state`
140    pub fn set_fixed_update_state_from_state(&mut self) {
141        for action_datum in self.action_data.values_mut() {
142            action_datum.kind_data.set_fixed_update_state_from_state();
143        }
144    }
145
146    /// Updates the [`ActionState`] based on the provided [`UpdatedActions`].
147    ///
148    /// The `action_data` is typically constructed from [`InputMap::process_actions`](crate::input_map::InputMap::process_actions),
149    /// which reads from the assorted [`ButtonInput`](bevy::input::ButtonInput) resources.
150    ///
151    /// Actions that are disabled will still be updated: instead, their values will be read as released / zero.
152    /// You can see their underlying values by checking their [`ActionData`] directly.
153    pub fn update(&mut self, updated_actions: UpdatedActions<A>) {
154        for (action, updated_value) in updated_actions.iter() {
155            match updated_value {
156                UpdatedValue::Button(ButtonValue { pressed, value }) => {
157                    if *pressed {
158                        self.press(action);
159                    } else {
160                        self.release(action);
161                    }
162                    self.set_button_value(action, *value);
163                }
164                UpdatedValue::Axis(value) => {
165                    self.set_value(action, *value);
166                }
167                UpdatedValue::DualAxis(pair) => {
168                    self.set_axis_pair(action, *pair);
169                }
170                UpdatedValue::TripleAxis(triple) => {
171                    self.set_axis_triple(action, *triple);
172                }
173            }
174        }
175    }
176
177    /// Advances the time for all actions,
178    /// transitioning them from `just_pressed` to `pressed`, and `just_released` to `released`.
179    ///
180    /// If the `timing` feature flag is enabled, the underlying timing and action data will be advanced according to the `current_instant`.
181    /// - if no [`Instant`] is set, the `current_instant` will be set as the initial time at which the button was pressed / released
182    /// - the [`Duration`] will advance to reflect elapsed time
183    ///
184    ///
185    /// # Example
186    /// ```rust
187    /// use bevy::prelude::Reflect;
188    /// use leafwing_input_manager::prelude::*;
189    /// use leafwing_input_manager::buttonlike::ButtonState;
190    /// use bevy::platform::time::Instant;
191    ///
192    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
193    /// enum Action {
194    ///     Run,
195    ///     Jump,
196    /// }
197    ///
198    /// let mut action_state = ActionState::<Action>::default();
199    ///
200    /// // Actions start released
201    /// assert!(action_state.released(&Action::Jump));
202    /// assert!(!action_state.just_released(&Action::Run));
203    ///
204    /// // Ticking time moves causes buttons just released to no longer be just released
205    /// let t0 = Instant::now();
206    /// let t1 = Instant::now();
207    ///
208    /// action_state.tick(t1, t0);
209    /// assert!(action_state.released(&Action::Jump));
210    /// assert!(!action_state.just_released(&Action::Jump));
211    ///
212    /// action_state.press(&Action::Jump);
213    /// assert!(action_state.just_pressed(&Action::Jump));
214    ///
215    /// // Ticking time moves causes buttons just pressed to no longer be just pressed
216    /// let t2 = Instant::now();
217    ///
218    /// action_state.tick(t2, t1);
219    /// assert!(action_state.pressed(&Action::Jump));
220    /// assert!(!action_state.just_pressed(&Action::Jump));
221    /// ```
222    pub fn tick(&mut self, _current_instant: Instant, _previous_instant: Instant) {
223        // Advanced the action states
224        self.action_data
225            .values_mut()
226            .for_each(|action_datum| action_datum.tick(_current_instant, _previous_instant));
227    }
228
229    /// A reference to the [`ActionData`] corresponding to the `action`.
230    #[inline]
231    #[must_use]
232    pub fn action_data(&self, action: &A) -> Option<&ActionData> {
233        self.action_data.get(action)
234    }
235
236    /// A mutable reference to the [`ActionData`] corresponding to the `action`.
237    ///
238    /// To initialize the [`ActionData`] if it has not yet been triggered,
239    /// use [`action_data_mut_or_default`](Self::action_data_mut_or_default) method.
240    #[inline]
241    #[must_use]
242    pub fn action_data_mut(&mut self, action: &A) -> Option<&mut ActionData> {
243        self.action_data.get_mut(action)
244    }
245
246    /// A mutable reference to the [`ActionData`] corresponding to the `action`, initializing it if needed.
247    ///
248    /// If the `action` has no data yet (because the `action` has not been triggered),
249    /// this method will create and insert a default [`ActionData`] for you,
250    /// avoiding potential errors from unwrapping [`None`].
251    pub fn action_data_mut_or_default(&mut self, action: &A) -> &mut ActionData {
252        if self.action_data.contains_key(action) {
253            // Safe to unwrap because we just checked
254            self.action_data.get_mut(action).unwrap()
255        } else {
256            self.action_data.insert(
257                action.clone(),
258                ActionData::from_kind(action.input_control_kind()),
259            );
260            // Safe to unwrap because we just inserted
261            self.action_data_mut(action).unwrap()
262        }
263    }
264
265    /// A reference of the [`ButtonData`] corresponding to the `action`.
266    ///
267    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
268    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
269    ///
270    /// # Caution
271    ///
272    /// To access the [`ButtonData`] regardless of whether the `action` has been triggered,
273    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
274    ///
275    /// # Returns
276    ///
277    /// - `Some(ButtonData)` if it exists.
278    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
279    #[inline]
280    #[must_use]
281    pub fn button_data(&self, action: &A) -> Option<&ButtonData> {
282        match self.action_data(action) {
283            Some(action_data) => match action_data.kind_data {
284                ActionKindData::Button(ref button_data) => Some(button_data),
285                _ => None,
286            },
287            None => None,
288        }
289    }
290
291    /// A mutable reference of the [`ButtonData`] corresponding to the `action`.
292    ///
293    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
294    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
295    ///
296    /// # Caution
297    ///
298    /// To access the [`ButtonData`] regardless of whether the `action` has been triggered,
299    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
300    ///
301    /// To insert a default [`ButtonData`] if it doesn't exist,
302    /// use [`button_data_mut_or_default`](Self::button_data_mut_or_default) method.
303    ///
304    /// # Returns
305    ///
306    /// - `Some(ButtonData)` if it exists.
307    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
308    #[inline]
309    #[must_use]
310    pub fn button_data_mut(&mut self, action: &A) -> Option<&mut ButtonData> {
311        match self.action_data_mut(action) {
312            Some(action_data) => match &mut action_data.kind_data {
313                ActionKindData::Button(button_data) => Some(button_data),
314                _ => None,
315            },
316            None => None,
317        }
318    }
319
320    /// A mutable reference of the [`ButtonData`] corresponding to the `action`, initializing it if needed.
321    ///
322    /// If the `action` has no data yet (because the `action` has not been triggered),
323    /// this method will create and insert a default [`ButtonData`] for you,
324    /// avoiding potential errors from unwrapping [`None`].
325    ///
326    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
327    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
328    #[inline]
329    #[must_use]
330    #[track_caller]
331    pub fn button_data_mut_or_default(&mut self, action: &A) -> &mut ButtonData {
332        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
333
334        let action_data = self.action_data_mut_or_default(action);
335        let ActionKindData::Button(ref mut button_data) = action_data.kind_data else {
336            panic!("{action:?} is not a Button");
337        };
338        button_data
339    }
340
341    /// A reference of the [`AxisData`] corresponding to the `action`.
342    ///
343    /// # Caution
344    ///
345    /// To access the [`AxisData`] regardless of whether the `action` has been triggered,
346    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
347    ///
348    /// # Returns
349    ///
350    /// - `Some(AxisData)` if it exists.
351    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
352    #[inline]
353    #[must_use]
354    #[track_caller]
355    pub fn axis_data(&self, action: &A) -> Option<&AxisData> {
356        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
357
358        match self.action_data(action) {
359            Some(action_data) => match action_data.kind_data {
360                ActionKindData::Axis(ref axis_data) => Some(axis_data),
361                _ => None,
362            },
363            None => None,
364        }
365    }
366
367    /// A mutable reference of the [`AxisData`] corresponding to the `action`.
368    ///
369    /// # Caution
370    ///
371    /// To insert a default [`AxisData`] if it doesn't exist,
372    /// use [`axis_data_mut_or_default`](Self::axis_data_mut_or_default) method.
373    ///
374    /// # Returns
375    ///
376    /// - `Some(AxisData)` if it exists.
377    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
378    #[inline]
379    #[must_use]
380    pub fn axis_data_mut(&mut self, action: &A) -> Option<&mut AxisData> {
381        match self.action_data_mut(action) {
382            Some(action_data) => match &mut action_data.kind_data {
383                ActionKindData::Axis(axis_data) => Some(axis_data),
384                _ => None,
385            },
386            None => None,
387        }
388    }
389
390    /// A mutable reference of the [`AxisData`] corresponding to the `action`, initializing it if needed..
391    ///
392    /// If the `action` has no data yet (because the `action` has not been triggered),
393    /// this method will create and insert a default [`AxisData`] for you,
394    /// avoiding potential errors from unwrapping [`None`].
395    ///
396    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
397    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
398    #[inline]
399    #[must_use]
400    #[track_caller]
401    pub fn axis_data_mut_or_default(&mut self, action: &A) -> &mut AxisData {
402        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
403
404        let action_data = self.action_data_mut_or_default(action);
405        let ActionKindData::Axis(ref mut axis_data) = action_data.kind_data else {
406            panic!("{action:?} is not an Axis");
407        };
408        axis_data
409    }
410
411    /// A reference of the [`DualAxisData`] corresponding to the `action`.
412    ///
413    /// # Caution
414    ///
415    /// To access the [`DualAxisData`] regardless of whether the `action` has been triggered,
416    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
417    ///
418    /// # Returns
419    ///
420    /// - `Some(DualAxisData)` if it exists.
421    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
422    #[inline]
423    #[must_use]
424    #[track_caller]
425    pub fn dual_axis_data(&self, action: &A) -> Option<&DualAxisData> {
426        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
427
428        match self.action_data(action) {
429            Some(action_data) => match action_data.kind_data {
430                ActionKindData::DualAxis(ref dual_axis_data) => Some(dual_axis_data),
431                _ => None,
432            },
433            None => None,
434        }
435    }
436
437    /// A mutable reference of the [`DualAxisData`] corresponding to the `action`.
438    ///
439    /// # Caution
440    ///
441    /// To insert a default [`DualAxisData`] if it doesn't exist,
442    /// use [`dual_axis_data_mut_or_default`](Self::dual_axis_data_mut_or_default) method.
443    ///
444    /// # Returns
445    ///
446    /// - `Some(DualAxisData)` if it exists.
447    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
448    #[inline]
449    #[must_use]
450    #[track_caller]
451    pub fn dual_axis_data_mut(&mut self, action: &A) -> Option<&mut DualAxisData> {
452        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
453
454        match self.action_data_mut(action) {
455            Some(action_data) => match &mut action_data.kind_data {
456                ActionKindData::DualAxis(dual_axis_data) => Some(dual_axis_data),
457                _ => None,
458            },
459            None => None,
460        }
461    }
462
463    /// A mutable reference of the [`DualAxisData`] corresponding to the `action` initializing it if needed.
464    ///
465    /// If the `action` has no data yet (because the `action` has not been triggered),
466    /// this method will create and insert a default [`DualAxisData`] for you,
467    /// avoiding potential errors from unwrapping [`None`].
468    ///
469    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
470    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
471    #[inline]
472    #[must_use]
473    #[track_caller]
474    pub fn dual_axis_data_mut_or_default(&mut self, action: &A) -> &mut DualAxisData {
475        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
476
477        let action_data = self.action_data_mut_or_default(action);
478        let ActionKindData::DualAxis(ref mut dual_axis_data) = action_data.kind_data else {
479            panic!("{action:?} is not a DualAxis");
480        };
481        dual_axis_data
482    }
483
484    /// A reference of the [`TripleAxisData`] corresponding to the `action`.
485    ///
486    /// # Caution
487    ///
488    /// To access the [`TripleAxisData`] regardless of whether the `action` has been triggered,
489    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
490    ///
491    /// # Returns
492    ///
493    /// - `Some(TripleAxisData)` if it exists.
494    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
495    #[inline]
496    #[must_use]
497    #[track_caller]
498    pub fn triple_axis_data(&self, action: &A) -> Option<&TripleAxisData> {
499        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
500
501        match self.action_data(action) {
502            Some(action_data) => match action_data.kind_data {
503                ActionKindData::TripleAxis(ref triple_axis_data) => Some(triple_axis_data),
504                _ => None,
505            },
506            None => None,
507        }
508    }
509
510    /// A mutable reference of the [`TripleAxisData`] corresponding to the `action`.
511    ///
512    /// # Caution
513    ///
514    /// To insert a default [`TripleAxisData`] if it doesn't exist,
515    /// use [`triple_axis_data_mut_or_default`](Self::dual_axis_data_mut_or_default) method.
516    ///
517    /// # Returns
518    ///
519    /// - `Some(ButtonData)` if it exists.
520    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
521    #[inline]
522    #[must_use]
523    #[track_caller]
524    pub fn triple_axis_data_mut(&mut self, action: &A) -> Option<&mut TripleAxisData> {
525        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
526
527        match self.action_data_mut(action) {
528            Some(action_data) => match &mut action_data.kind_data {
529                ActionKindData::TripleAxis(triple_axis_data) => Some(triple_axis_data),
530                _ => None,
531            },
532            None => None,
533        }
534    }
535
536    /// A mutable reference of the [`TripleAxisData`] corresponding to the `action` initializing it if needed.
537    ///
538    /// If the `action` has no data yet (because the `action` has not been triggered),
539    /// this method will create and insert a default [`TripleAxisData`] for you,
540    /// avoiding potential errors from unwrapping [`None`].
541    ///
542    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
543    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
544    #[inline]
545    #[must_use]
546    #[track_caller]
547    pub fn triple_axis_data_mut_or_default(&mut self, action: &A) -> &mut TripleAxisData {
548        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
549
550        let action_data = self.action_data_mut_or_default(action);
551        let ActionKindData::TripleAxis(ref mut triple_axis_data) = action_data.kind_data else {
552            panic!("{action:?} is not a TripleAxis");
553        };
554        triple_axis_data
555    }
556
557    /// Get the value associated with the corresponding buttonlike `action` if present.
558    ///
559    /// # Warnings
560    ///
561    /// This value may not be bounded as you might expect.
562    /// Consider clamping this to account for multiple triggering inputs,
563    /// typically using the [`clamped_button_value`](Self::clamped_button_value) method instead.
564    #[inline]
565    #[must_use]
566    #[track_caller]
567    pub fn button_value(&self, action: &A) -> f32 {
568        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
569
570        if self.action_disabled(action) {
571            return 0.0;
572        }
573
574        let action_data = self.button_data(action);
575        action_data.map_or(0.0, |action_data| action_data.value)
576    }
577
578    /// Sets the value of the buttonlike `action` to the provided `value`.
579    /// A threshold of `0.02` must be overcome for the button to count as "pressed"
580    /// This is used to account for a semi-frequent issue with analog inputs
581    /// (e.g., gamepad triggers) reporting very small non-zero values when
582    /// not physically pressed, due to sensor imprecision.
583    ///
584    /// Also updates the state of the button based on the `value`:
585    /// - If `value > 0.02`, the button will be pressed.
586    /// - If `value <= 0.0`, the button will be released.
587    #[track_caller]
588    pub fn set_button_value(&mut self, action: &A, value: f32) {
589        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
590        const BUTTON_PRESS_THRESHOLD: f32 = 0.02;
591
592        let button_data = self.button_data_mut_or_default(action);
593        button_data.value = value;
594
595        if value > BUTTON_PRESS_THRESHOLD {
596            #[cfg(feature = "timing")]
597            if button_data.state.released() {
598                button_data.timing.flip();
599            }
600
601            button_data.state.press();
602        } else {
603            #[cfg(feature = "timing")]
604            if button_data.state.pressed() {
605                button_data.timing.flip();
606            }
607
608            button_data.state.release();
609        }
610    }
611
612    /// Get the value associated with the corresponding `action`, clamped to `[0.0, 1.0]`.
613    ///
614    /// # Warning
615    ///
616    /// This value will be 0. by default,
617    /// even if the action is not a buttonlike action.
618    pub fn clamped_button_value(&self, action: &A) -> f32 {
619        self.button_value(action).clamp(0., 1.)
620    }
621
622    /// Get the value associated with the corresponding axislike `action` if present.
623    ///
624    /// # Warnings
625    ///
626    /// This value may not be bounded as you might expect.
627    /// Consider clamping this to account for multiple triggering inputs,
628    /// typically using the [`clamped_value`](Self::clamped_value) method instead.
629    #[inline]
630    #[must_use]
631    #[track_caller]
632    pub fn value(&self, action: &A) -> f32 {
633        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
634
635        if self.action_disabled(action) {
636            return 0.0;
637        }
638
639        let action_data = self.axis_data(action);
640        action_data.map_or(0.0, |action_data| action_data.value)
641    }
642
643    /// Sets the value of the axislike `action` to the provided `value`.
644    #[track_caller]
645    pub fn set_value(&mut self, action: &A, value: f32) {
646        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
647
648        let axis_data = self.axis_data_mut_or_default(action);
649        axis_data.value = value;
650    }
651
652    /// Get the value associated with the corresponding `action`, clamped to `[-1.0, 1.0]`.
653    ///
654    /// # Warning
655    ///
656    /// This value will be 0. by default,
657    /// even if the action is not an axislike action.
658    pub fn clamped_value(&self, action: &A) -> f32 {
659        self.value(action).clamp(-1., 1.)
660    }
661
662    /// Get the [`Vec2`] from the binding that triggered the corresponding `action`.
663    ///
664    /// Only messages that represent dual-axis control provide a [`Vec2`],
665    /// and this will return [`None`] for other messages.
666    ///
667    /// If multiple inputs with an axis pair trigger the same game action at the same time, the
668    /// value of each axis pair will be added together.
669    ///
670    /// # Warning
671    ///
672    /// This value will be [`Vec2::ZERO`] by default,
673    /// even if the action is not a dual-axislike action.
674    ///
675    /// These values may not be bounded as you might expect.
676    /// Consider clamping this to account for multiple triggering inputs,
677    /// typically using the [`clamped_axis_pair`](Self::clamped_axis_pair) method instead.
678    #[must_use]
679    #[track_caller]
680    pub fn axis_pair(&self, action: &A) -> Vec2 {
681        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
682
683        if self.action_disabled(action) {
684            return Vec2::ZERO;
685        }
686
687        let action_data = self.dual_axis_data(action);
688        action_data.map_or(Vec2::ZERO, |action_data| action_data.pair)
689    }
690
691    /// Sets the [`Vec2`] of the `action` to the provided `pair`.
692    #[track_caller]
693    pub fn set_axis_pair(&mut self, action: &A, pair: Vec2) {
694        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
695
696        let dual_axis_data = self.dual_axis_data_mut_or_default(action);
697        dual_axis_data.pair = pair;
698    }
699
700    /// Get the [`Vec2`] associated with the corresponding `action`, clamped to `[-1.0, 1.0]`.
701    ///  
702    /// # Warning
703    ///
704    /// This value will be [`Vec2::ZERO`] by default,
705    /// even if the action is not a dual-axislike action.
706    pub fn clamped_axis_pair(&self, action: &A) -> Vec2 {
707        let pair = self.axis_pair(action);
708        pair.clamp(Vec2::NEG_ONE, Vec2::ONE)
709    }
710
711    /// Get the [`Vec3`] from the binding that triggered the corresponding `action`.
712    ///
713    /// Only messages that represent triple-axis control provide a [`Vec3`],
714    /// and this will return [`None`] for other messages.
715    ///
716    /// If multiple inputs with an axis triple trigger the same game action at the same time, the
717    /// value of each axis triple will be added together.
718    ///
719    /// # Warning
720    ///
721    /// This value will be [`Vec3::ZERO`] by default,
722    /// even if the action is not a triple-axislike action.
723    ///
724    /// These values may not be bounded as you might expect.
725    /// Consider clamping this to account for multiple triggering inputs,
726    /// typically using the [`clamped_axis_triple`](Self::clamped_axis_triple) method instead.
727    #[must_use]
728    #[track_caller]
729    pub fn axis_triple(&self, action: &A) -> Vec3 {
730        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
731
732        if self.action_disabled(action) {
733            return Vec3::ZERO;
734        }
735
736        let action_data = self.triple_axis_data(action);
737        action_data.map_or(Vec3::ZERO, |action_data| action_data.triple)
738    }
739
740    /// Sets the [`Vec2`] of the `action` to the provided `pair`.
741    #[track_caller]
742    pub fn set_axis_triple(&mut self, action: &A, triple: Vec3) {
743        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
744
745        let triple_axis_data = self.triple_axis_data_mut_or_default(action);
746        triple_axis_data.triple = triple;
747    }
748
749    /// Get the [`Vec3`] associated with the corresponding `action`, clamped to the cube of values bounded by -1 and 1 on all axes.
750    ///
751    /// # Warning
752    ///
753    /// This value will be [`Vec3::ZERO`] by default,
754    /// even if the action is not a dual-axislike action.
755    pub fn clamped_axis_triple(&self, action: &A) -> Vec3 {
756        let triple = self.axis_triple(action);
757        triple.clamp(Vec3::NEG_ONE, Vec3::ONE)
758    }
759
760    /// Manually sets the [`ButtonData`] of the corresponding `action`
761    ///
762    /// You should almost always use more direct methods, as they are simpler and less error-prone.
763    ///
764    /// However, this method can be useful for testing,
765    /// or when transferring [`ButtonData`] between action states.
766    ///
767    /// # Example
768    /// ```rust
769    /// use bevy::prelude::Reflect;
770    /// use leafwing_input_manager::prelude::*;
771    ///
772    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
773    /// enum AbilitySlot {
774    ///     Slot1,
775    ///     Slot2,
776    /// }
777    ///
778    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
779    /// enum Action {
780    ///     Run,
781    ///     Jump,
782    /// }
783    ///
784    /// let mut ability_slot_state = ActionState::<AbilitySlot>::default();
785    /// let mut action_state = ActionState::<Action>::default();
786    ///
787    /// // Extract the state from the ability slot
788    /// let slot_1_state = ability_slot_state.button_data(&AbilitySlot::Slot1);
789    ///
790    /// // And transfer it to the actual ability that we care about
791    /// // without losing timing information
792    /// if let Some(state) = slot_1_state {
793    ///    action_state.set_button_data(Action::Run, state.clone());
794    /// }
795    /// ```
796    #[inline]
797    #[track_caller]
798    pub fn set_button_data(&mut self, action: A, data: ButtonData) {
799        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
800
801        let button_data = self.button_data_mut_or_default(&action);
802        *button_data = data;
803    }
804
805    /// Press the `action`
806    ///
807    /// No initial instant or reasons why the button was pressed will be recorded.
808    /// Instead, this is set through [`ActionState::tick()`]
809    #[inline]
810    #[track_caller]
811    pub fn press(&mut self, action: &A) {
812        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
813
814        let action_data = self.button_data_mut_or_default(action);
815
816        #[cfg(feature = "timing")]
817        if action_data.update_state.released() {
818            action_data.timing.flip();
819        }
820
821        action_data.state.press();
822        action_data.value = 1.0;
823    }
824
825    /// Release the `action`
826    ///
827    /// No initial instant will be recorded.
828    /// Instead, this is set through [`ActionState::tick()`]
829    #[inline]
830    pub fn release(&mut self, action: &A) {
831        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
832
833        let action_data = self.button_data_mut_or_default(action);
834
835        #[cfg(feature = "timing")]
836        if action_data.update_state.pressed() {
837            action_data.timing.flip();
838        }
839
840        action_data.state.release();
841        action_data.value = 0.0;
842    }
843
844    /// Resets an action to its default state.
845    ///
846    /// Buttons will be released, and axes will be set to 0.
847    pub fn reset(&mut self, action: &A) {
848        match action.input_control_kind() {
849            InputControlKind::Button => self.release(action),
850            InputControlKind::Axis => {
851                self.set_value(action, 0.0);
852            }
853            InputControlKind::DualAxis => {
854                self.set_axis_pair(action, Vec2::ZERO);
855            }
856            InputControlKind::TripleAxis => {
857                self.set_axis_triple(action, Vec3::ZERO);
858            }
859        }
860    }
861
862    /// Releases all [`Buttonlike`](crate::user_input::Buttonlike) actions,
863    /// sets all [`Axislike`](crate::user_input::Axislike) actions to 0,
864    /// sets all [`DualAxislike`](crate::user_input::DualAxislike) actions to [`Vec2::ZERO`],
865    /// and sets all [`TripleAxislike`](crate::user_input::TripleAxislike) actions to [`Vec3::ZERO`].
866    pub fn reset_all(&mut self) {
867        // Collect out to avoid angering the borrow checker
868        let all_actions = self.action_data.keys().cloned().collect::<Vec<A>>();
869        for action in all_actions.into_iter() {
870            self.reset(&action);
871        }
872    }
873
874    /// Is the entire [`ActionState`] currently disabled?
875    pub fn disabled(&self) -> bool {
876        self.disabled
877    }
878
879    /// Is this `action` currently disabled?
880    #[inline]
881    #[must_use]
882    pub fn action_disabled(&self, action: &A) -> bool {
883        if self.disabled {
884            return true;
885        }
886
887        match self.action_data(action) {
888            Some(action_data) => action_data.disabled,
889            None => false,
890        }
891    }
892
893    /// Disables the entire [`ActionState`].
894    ///
895    /// All values will be reset to their default state.
896    #[inline]
897    pub fn disable(&mut self) {
898        self.disabled = true;
899        self.reset_all();
900    }
901
902    /// Disables the `action`.
903    ///
904    /// The action's value will be reset to its default state.
905    #[inline]
906    pub fn disable_action(&mut self, action: &A) {
907        let action_data = self.action_data_mut_or_default(action);
908
909        action_data.disabled = true;
910        self.reset(action);
911    }
912
913    /// Disables all actions
914    #[inline]
915    pub fn disable_all_actions(&mut self) {
916        for action in self.keys() {
917            self.disable_action(&action);
918        }
919    }
920
921    /// Enables the entire [`ActionState`]
922    #[inline]
923    pub fn enable(&mut self) {
924        self.disabled = false;
925    }
926
927    /// Enables the `action`
928    #[inline]
929    pub fn enable_action(&mut self, action: &A) {
930        let action_data = self.action_data_mut_or_default(action);
931
932        action_data.disabled = false;
933    }
934
935    /// Enables all actions
936    #[inline]
937    pub fn enable_all_actions(&mut self) {
938        for action in self.keys() {
939            self.enable_action(&action);
940        }
941    }
942
943    /// Is this `action` currently pressed?
944    ///
945    /// # Warning
946    ///
947    /// This value will be `false` by default,
948    /// even if the action is not a buttonlike action.
949    #[inline]
950    #[must_use]
951    #[track_caller]
952    pub fn pressed(&self, action: &A) -> bool {
953        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
954
955        if self.action_disabled(action) {
956            return false;
957        }
958
959        match self.button_data(action) {
960            Some(button_data) => button_data.pressed(),
961            None => false,
962        }
963    }
964
965    /// Was this `action` pressed since the last time [tick](ActionState::tick) was called?
966    ///
967    /// # Warning
968    ///
969    /// This value will be `false` by default,
970    /// even if the action is not a buttonlike action.
971    #[inline]
972    #[must_use]
973    #[track_caller]
974    pub fn just_pressed(&self, action: &A) -> bool {
975        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
976
977        if self.action_disabled(action) {
978            return false;
979        }
980
981        match self.button_data(action) {
982            Some(button_data) => button_data.just_pressed(),
983            None => false,
984        }
985    }
986
987    /// Is this `action` currently released?
988    ///
989    /// This is always the logical negation of [pressed](ActionState::pressed)
990    ///
991    /// # Warning
992    ///
993    /// This value will be `true` by default,
994    /// even if the action is not a buttonlike action.
995    #[inline]
996    #[must_use]
997    #[track_caller]
998    pub fn released(&self, action: &A) -> bool {
999        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1000
1001        if self.action_disabled(action) {
1002            return true;
1003        }
1004
1005        match self.button_data(action) {
1006            Some(button_data) => button_data.released(),
1007            None => true,
1008        }
1009    }
1010
1011    /// Was this `action` released since the last time [tick](ActionState::tick) was called?
1012    ///
1013    /// # Warning
1014    ///
1015    /// This value will be `false` by default,
1016    /// even if the action is not a buttonlike action.
1017    #[inline]
1018    #[must_use]
1019    #[track_caller]
1020    pub fn just_released(&self, action: &A) -> bool {
1021        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1022
1023        if self.action_disabled(action) {
1024            return false;
1025        }
1026
1027        match self.button_data(action) {
1028            Some(button_data) => button_data.just_released(),
1029            None => false,
1030        }
1031    }
1032
1033    #[must_use]
1034    /// Which actions are currently pressed?
1035    pub fn get_pressed(&self) -> Vec<A> {
1036        let all_actions = self.action_data.keys().cloned();
1037
1038        all_actions
1039            .into_iter()
1040            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1041            .filter(|action| self.pressed(action))
1042            .collect()
1043    }
1044
1045    #[must_use]
1046    /// Which actions were just pressed?
1047    pub fn get_just_pressed(&self) -> Vec<A> {
1048        let all_actions = self.action_data.keys().cloned();
1049
1050        all_actions
1051            .into_iter()
1052            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1053            .filter(|action| self.just_pressed(action))
1054            .collect()
1055    }
1056
1057    #[must_use]
1058    /// Which actions are currently released?
1059    pub fn get_released(&self) -> Vec<A> {
1060        let all_actions = self.action_data.keys().cloned();
1061
1062        all_actions
1063            .into_iter()
1064            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1065            .filter(|action| self.released(action))
1066            .collect()
1067    }
1068
1069    #[must_use]
1070    /// Which actions were just released?
1071    pub fn get_just_released(&self) -> Vec<A> {
1072        let all_actions = self.action_data.keys().cloned();
1073
1074        all_actions
1075            .into_iter()
1076            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1077            .filter(|action| self.just_released(action))
1078            .collect()
1079    }
1080
1081    /// The [`Instant`] that the action was last pressed or released
1082    ///
1083    ///
1084    ///
1085    /// If the action was pressed or released since the last time [`ActionState::tick`] was called
1086    /// the value will be [`None`].
1087    /// This ensures that all our actions are assigned a timing and duration
1088    /// that corresponds exactly to the start of a frame, rather than relying on idiosyncratic timing.
1089    ///
1090    /// This will also be [`None`] if the action was never pressed or released.
1091    #[cfg(feature = "timing")]
1092    #[must_use]
1093    #[track_caller]
1094    pub fn instant_started(&self, action: &A) -> Option<Instant> {
1095        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1096
1097        let button_data = self.button_data(action)?;
1098        button_data.timing.instant_started
1099    }
1100
1101    /// The [`Duration`] for which the action has been held or released
1102    ///
1103    /// This will be [`Duration::ZERO`] if the action was never pressed or released.
1104    #[cfg(feature = "timing")]
1105    #[must_use]
1106    #[track_caller]
1107    pub fn current_duration(&self, action: &A) -> Duration {
1108        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1109
1110        self.button_data(action)
1111            .map(|data| data.timing.current_duration)
1112            .unwrap_or_default()
1113    }
1114
1115    /// The [`Duration`] for which the action was last held or released
1116    ///
1117    /// This is a snapshot of the [`ActionState::current_duration`] state at the time
1118    /// the action was last pressed or released.
1119    ///
1120    /// This will be [`Duration::ZERO`] if the action was never pressed or released.
1121    #[cfg(feature = "timing")]
1122    #[must_use]
1123    #[track_caller]
1124    pub fn previous_duration(&self, action: &A) -> Duration {
1125        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1126
1127        self.button_data(action)
1128            .map(|data| data.timing.previous_duration)
1129            .unwrap_or_default()
1130    }
1131
1132    /// Applies an [`ActionDiff`] (usually received over the network) to the [`ActionState`].
1133    ///
1134    /// This lets you reconstruct an [`ActionState`] from a stream of [`ActionDiff`]s
1135    pub fn apply_diff(&mut self, action_diff: &ActionDiff<A>) {
1136        match action_diff {
1137            ActionDiff::Pressed { action, value } => {
1138                self.set_button_value(action, *value);
1139            }
1140            ActionDiff::Released { action } => {
1141                self.release(action);
1142            }
1143            ActionDiff::AxisChanged { action, value } => {
1144                self.set_value(action, *value);
1145            }
1146            ActionDiff::DualAxisChanged { action, axis_pair } => {
1147                self.set_axis_pair(action, *axis_pair);
1148            }
1149            ActionDiff::TripleAxisChanged {
1150                action,
1151                axis_triple,
1152            } => {
1153                self.set_axis_triple(action, *axis_triple);
1154            }
1155        };
1156    }
1157
1158    /// Returns an owned list of the [`Actionlike`] keys in this [`ActionState`].
1159    #[inline]
1160    #[must_use]
1161    pub fn keys(&self) -> Vec<A> {
1162        self.action_data.keys().cloned().collect()
1163    }
1164}
1165
1166#[cfg(test)]
1167mod tests {
1168    use crate as leafwing_input_manager;
1169    use crate::action_diff::ActionDiff;
1170    use crate::action_state::{
1171        ActionData, ActionKindData, ActionState, AxisData, ButtonData, DualAxisData,
1172    };
1173    use crate::buttonlike::{ButtonState, ButtonValue};
1174    use crate::input_map::UpdatedActions;
1175    #[cfg(any(feature = "gamepad", feature = "keyboard"))]
1176    use crate::prelude::{ButtonlikeChord, InputMap};
1177    #[cfg(feature = "gamepad")]
1178    use bevy::input::gamepad::GamepadButton;
1179    #[cfg(feature = "keyboard")]
1180    use bevy::input::keyboard::KeyCode;
1181    use bevy::platform::collections::HashMap;
1182    use bevy::prelude::*;
1183    use leafwing_input_manager_macros::Actionlike;
1184
1185    #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
1186    enum TestAction {
1187        Trigger,
1188        Run,
1189        Jump,
1190        Hide,
1191        One,
1192        Two,
1193        OneAndTwo,
1194        #[actionlike(Axis)]
1195        Axis,
1196        #[actionlike(DualAxis)]
1197        DualAxis,
1198        #[actionlike(TripleAxis)]
1199        TripleAxis,
1200    }
1201
1202    #[cfg(any(feature = "keyboard", feature = "gamepad"))]
1203    struct TestContext {
1204        pub app: App,
1205        pub input_map: InputMap<TestAction>,
1206    }
1207
1208    #[cfg(any(feature = "keyboard", feature = "gamepad"))]
1209    impl TestContext {
1210        pub fn new() -> Self {
1211            use bevy::input::InputPlugin;
1212
1213            use crate::plugin::InputManagerPlugin;
1214
1215            let mut app = App::new();
1216            app.add_plugins((
1217                MinimalPlugins,
1218                InputPlugin,
1219                InputManagerPlugin::<TestAction>::default(),
1220            ));
1221
1222            let mut input_map = InputMap::default();
1223            #[cfg(feature = "gamepad")]
1224            input_map.insert(TestAction::Trigger, GamepadButton::RightTrigger);
1225
1226            #[cfg(feature = "keyboard")]
1227            {
1228                input_map.insert(TestAction::One, KeyCode::Digit1);
1229                input_map.insert(TestAction::Two, KeyCode::Digit2);
1230                input_map.insert(
1231                    TestAction::OneAndTwo,
1232                    ButtonlikeChord::new([KeyCode::Digit1, KeyCode::Digit2]),
1233                );
1234                input_map.insert(TestAction::Run, KeyCode::KeyR);
1235            }
1236
1237            app.insert_resource(input_map.clone())
1238                .init_resource::<ActionState<TestAction>>();
1239
1240            app.update();
1241
1242            Self { app, input_map }
1243        }
1244
1245        #[cfg(feature = "gamepad")]
1246        pub fn send_gamepad_connection_event(&mut self, gamepad: Option<Entity>) -> Entity {
1247            use bevy::input::gamepad::{GamepadConnection, GamepadConnectionEvent};
1248
1249            let gamepad = gamepad.unwrap_or_else(|| self.app.world_mut().spawn_empty().id());
1250            self.app
1251                .world_mut()
1252                .resource_mut::<Messages<GamepadConnectionEvent>>()
1253                .write(GamepadConnectionEvent::new(
1254                    gamepad,
1255                    GamepadConnection::Connected {
1256                        name: "TestController".to_string(),
1257                        vendor_id: None,
1258                        product_id: None,
1259                    },
1260                ));
1261            gamepad
1262        }
1263
1264        pub fn update(&mut self) {
1265            self.app.update();
1266        }
1267    }
1268
1269    #[test]
1270    fn action_state_default_state() {
1271        let action_state = ActionState::<TestAction>::default();
1272
1273        assert!(!action_state.disabled);
1274        assert_eq!(action_state.action_data, HashMap::default());
1275    }
1276
1277    #[test]
1278    fn action_state_all_action_data() {
1279        let action_state = ActionState::<TestAction>::default();
1280
1281        assert_eq!(action_state.all_action_data(), &action_state.action_data);
1282    }
1283
1284    #[test]
1285    fn action_state_button() {
1286        let mut action_state = ActionState::<TestAction>::default();
1287
1288        assert!(!action_state.pressed(&TestAction::Jump));
1289        assert_eq!(action_state.button_value(&TestAction::Jump), 0.0);
1290
1291        let mut updated_actions = UpdatedActions::<TestAction>::default();
1292        updated_actions.0.insert(
1293            TestAction::Jump,
1294            crate::input_map::UpdatedValue::Button(ButtonValue {
1295                pressed: true,
1296                value: 0.5,
1297            }),
1298        );
1299
1300        action_state.update(updated_actions);
1301
1302        assert!(action_state.pressed(&TestAction::Jump));
1303        assert_eq!(action_state.button_value(&TestAction::Jump), 0.5);
1304    }
1305
1306    #[test]
1307    fn action_state_axis() {
1308        let mut action_state = ActionState::<TestAction>::default();
1309
1310        assert_eq!(action_state.value(&TestAction::Axis), 0.0);
1311
1312        let mut updated_actions = UpdatedActions::<TestAction>::default();
1313        updated_actions
1314            .0
1315            .insert(TestAction::Axis, crate::input_map::UpdatedValue::Axis(0.5));
1316
1317        action_state.update(updated_actions);
1318
1319        assert_eq!(action_state.value(&TestAction::Axis), 0.5);
1320    }
1321
1322    #[test]
1323    fn action_state_dual_axis() {
1324        let mut action_state = ActionState::<TestAction>::default();
1325
1326        assert_eq!(
1327            action_state.axis_pair(&TestAction::DualAxis),
1328            Vec2::new(0.0, 0.0)
1329        );
1330
1331        let mut updated_actions = UpdatedActions::<TestAction>::default();
1332        updated_actions.0.insert(
1333            TestAction::DualAxis,
1334            crate::input_map::UpdatedValue::DualAxis(Vec2::new(0.5, 0.5)),
1335        );
1336
1337        action_state.update(updated_actions);
1338
1339        assert_eq!(
1340            action_state.axis_pair(&TestAction::DualAxis),
1341            Vec2::new(0.5, 0.5)
1342        );
1343    }
1344
1345    #[test]
1346    fn action_state_triple_axis() {
1347        let mut action_state = ActionState::<TestAction>::default();
1348
1349        assert_eq!(
1350            action_state.axis_triple(&TestAction::TripleAxis),
1351            Vec3::new(0.0, 0.0, 0.0)
1352        );
1353
1354        let mut updated_actions = UpdatedActions::<TestAction>::default();
1355        updated_actions.0.insert(
1356            TestAction::TripleAxis,
1357            crate::input_map::UpdatedValue::TripleAxis(Vec3::new(0.5, 0.5, 0.5)),
1358        );
1359
1360        action_state.update(updated_actions);
1361
1362        assert_eq!(
1363            action_state.axis_triple(&TestAction::TripleAxis),
1364            Vec3::new(0.5, 0.5, 0.5)
1365        );
1366    }
1367
1368    #[cfg(feature = "keyboard")]
1369    #[test]
1370    fn press_lifecycle() {
1371        use std::time::{Duration, Instant};
1372
1373        use crate::prelude::Buttonlike;
1374        use crate::prelude::ClashStrategy;
1375        use crate::prelude::updating::CentralInputStore;
1376
1377        let ctx = TestContext::new();
1378        let mut app = ctx.app;
1379        let input_map = ctx.input_map;
1380
1381        // Action state
1382        let mut action_state = ActionState::<TestAction>::default();
1383        println!(
1384            "Default button data: {:?}",
1385            action_state.button_data(&TestAction::Run)
1386        );
1387
1388        // Starting state
1389        let input_store = app.world().resource::<CentralInputStore>();
1390        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1391
1392        println!(
1393            "Initialized button data: {:?}",
1394            action_state.button_data(&TestAction::Run)
1395        );
1396
1397        assert!(!action_state.pressed(&TestAction::Run));
1398        assert!(!action_state.just_pressed(&TestAction::Run));
1399        assert!(action_state.released(&TestAction::Run));
1400        assert!(!action_state.just_released(&TestAction::Run));
1401
1402        // Pressing
1403        KeyCode::KeyR.press(app.world_mut());
1404        // Process the input messages into Input<KeyCode> data
1405        app.update();
1406        let input_store = app.world().resource::<CentralInputStore>();
1407
1408        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1409
1410        assert!(action_state.pressed(&TestAction::Run));
1411        assert!(action_state.just_pressed(&TestAction::Run));
1412        assert!(!action_state.released(&TestAction::Run));
1413        assert!(!action_state.just_released(&TestAction::Run));
1414
1415        // Waiting
1416        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1417        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1418
1419        assert!(action_state.pressed(&TestAction::Run));
1420        assert!(!action_state.just_pressed(&TestAction::Run));
1421        assert!(!action_state.released(&TestAction::Run));
1422        assert!(!action_state.just_released(&TestAction::Run));
1423
1424        // Releasing
1425        KeyCode::KeyR.release(app.world_mut());
1426        app.update();
1427        let input_store = app.world().resource::<CentralInputStore>();
1428
1429        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1430
1431        assert!(!action_state.pressed(&TestAction::Run));
1432        assert!(!action_state.just_pressed(&TestAction::Run));
1433        assert!(action_state.released(&TestAction::Run));
1434        assert!(action_state.just_released(&TestAction::Run));
1435
1436        // Waiting
1437        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1438        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1439
1440        assert!(!action_state.pressed(&TestAction::Run));
1441        assert!(!action_state.just_pressed(&TestAction::Run));
1442        assert!(action_state.released(&TestAction::Run));
1443        assert!(!action_state.just_released(&TestAction::Run));
1444    }
1445
1446    #[test]
1447    fn synthetic_press() {
1448        let mut action_state = ActionState::<TestAction>::default();
1449        action_state.press(&TestAction::One);
1450        dbg!(&action_state);
1451
1452        assert!(action_state.pressed(&TestAction::One));
1453        assert!(action_state.just_pressed(&TestAction::One));
1454        assert!(!action_state.released(&TestAction::One));
1455        assert!(!action_state.just_released(&TestAction::One));
1456
1457        assert!(!action_state.pressed(&TestAction::Two));
1458        assert!(!action_state.just_pressed(&TestAction::Two));
1459        assert!(action_state.released(&TestAction::Two));
1460        assert!(!action_state.just_released(&TestAction::Two));
1461    }
1462
1463    #[cfg(feature = "keyboard")]
1464    #[test]
1465    #[ignore = "Clashing inputs for non-buttonlike inputs is broken."]
1466    fn update_with_clashes_prioritizing_longest() {
1467        use std::time::{Duration, Instant};
1468
1469        use crate::prelude::ClashStrategy;
1470        use crate::prelude::updating::CentralInputStore;
1471        use crate::user_input::Buttonlike;
1472        use bevy::prelude::KeyCode::*;
1473
1474        let ctx = TestContext::new();
1475        let mut app = ctx.app;
1476        let input_map = ctx.input_map;
1477
1478        // Action state
1479        let mut action_state = ActionState::<TestAction>::default();
1480
1481        // Starting state
1482        let input_store = app.world().resource::<CentralInputStore>();
1483        action_state.update(input_map.process_actions(
1484            None,
1485            input_store,
1486            ClashStrategy::PrioritizeLongest,
1487        ));
1488        assert!(action_state.released(&TestAction::One));
1489        assert!(action_state.released(&TestAction::Two));
1490        assert!(action_state.released(&TestAction::OneAndTwo));
1491
1492        // Pressing One
1493        Digit1.press(app.world_mut());
1494        app.update();
1495        let input_store = app.world().resource::<CentralInputStore>();
1496
1497        action_state.update(input_map.process_actions(
1498            None,
1499            input_store,
1500            ClashStrategy::PrioritizeLongest,
1501        ));
1502
1503        assert!(action_state.pressed(&TestAction::One));
1504        assert!(action_state.released(&TestAction::Two));
1505        assert!(action_state.released(&TestAction::OneAndTwo));
1506
1507        // Waiting
1508        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1509        action_state.update(input_map.process_actions(
1510            None,
1511            input_store,
1512            ClashStrategy::PrioritizeLongest,
1513        ));
1514
1515        assert!(action_state.pressed(&TestAction::One));
1516        assert!(action_state.released(&TestAction::Two));
1517        assert!(action_state.released(&TestAction::OneAndTwo));
1518
1519        // Pressing Two
1520        Digit2.press(app.world_mut());
1521        app.update();
1522        let input_store = app.world().resource::<CentralInputStore>();
1523
1524        action_state.update(input_map.process_actions(
1525            None,
1526            input_store,
1527            ClashStrategy::PrioritizeLongest,
1528        ));
1529
1530        // Now only the longest OneAndTwo has been pressed,
1531        // while both One and Two have been released
1532        assert!(action_state.released(&TestAction::One));
1533        assert!(action_state.released(&TestAction::Two));
1534        assert!(action_state.pressed(&TestAction::OneAndTwo));
1535
1536        // Waiting
1537        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1538        action_state.update(input_map.process_actions(
1539            None,
1540            input_store,
1541            ClashStrategy::PrioritizeLongest,
1542        ));
1543
1544        assert!(action_state.released(&TestAction::One));
1545        assert!(action_state.released(&TestAction::Two));
1546        assert!(action_state.pressed(&TestAction::OneAndTwo));
1547    }
1548
1549    #[test]
1550    fn test_set_update_state_from_state() {
1551        let mut action_state = ActionState::<TestAction>::default();
1552
1553        // Initial state
1554        assert!(action_state.released(&TestAction::Run));
1555        assert!(!action_state.just_released(&TestAction::Run));
1556        assert!(!action_state.pressed(&TestAction::Run));
1557        assert!(!action_state.just_pressed(&TestAction::Run));
1558
1559        // Update the state manually
1560        action_state.action_data.insert(
1561            TestAction::Run,
1562            ActionData {
1563                disabled: false,
1564                kind_data: ActionKindData::Button(ButtonData {
1565                    state: ButtonState::Pressed,
1566                    update_state: ButtonState::Pressed,
1567                    fixed_update_state: ButtonState::Pressed,
1568                    value: 1.0,
1569                    update_value: 1.0,
1570                    fixed_update_value: 1.0,
1571                    #[cfg(feature = "timing")]
1572                    timing: Default::default(),
1573                }),
1574            },
1575        );
1576        action_state.set_update_state_from_state();
1577
1578        // Check the state
1579        assert!(action_state.pressed(&TestAction::Run));
1580        assert!(!action_state.just_pressed(&TestAction::Run));
1581        assert!(!action_state.released(&TestAction::Run));
1582        assert!(!action_state.just_released(&TestAction::Run));
1583    }
1584
1585    #[test]
1586    fn test_set_fixed_update_state_from_state() {
1587        let mut action_state = ActionState::<TestAction>::default();
1588
1589        // Initial state
1590        assert!(action_state.released(&TestAction::Run));
1591        assert!(!action_state.just_released(&TestAction::Run));
1592        assert!(!action_state.pressed(&TestAction::Run));
1593        assert!(!action_state.just_pressed(&TestAction::Run));
1594
1595        // Update the state manually
1596        action_state.action_data.insert(
1597            TestAction::Run,
1598            ActionData {
1599                disabled: false,
1600                kind_data: ActionKindData::Button(ButtonData {
1601                    state: ButtonState::Pressed,
1602                    update_state: ButtonState::Pressed,
1603                    fixed_update_state: ButtonState::Pressed,
1604                    value: 1.0,
1605                    update_value: 1.0,
1606                    fixed_update_value: 1.0,
1607                    #[cfg(feature = "timing")]
1608                    timing: Default::default(),
1609                }),
1610            },
1611        );
1612        action_state.set_fixed_update_state_from_state();
1613
1614        assert!(action_state.pressed(&TestAction::Run));
1615        assert!(!action_state.just_pressed(&TestAction::Run));
1616        assert!(!action_state.released(&TestAction::Run));
1617        assert!(!action_state.just_released(&TestAction::Run));
1618    }
1619
1620    #[test]
1621    fn test_button_data_for_button_action_without_data() {
1622        let mut action_state = ActionState::<TestAction>::default();
1623        action_state.action_data.remove(&TestAction::Run);
1624        assert!(action_state.button_data(&TestAction::Run).is_none());
1625    }
1626
1627    #[test]
1628    fn test_button_data_for_non_button_action() {
1629        let mut action_state = ActionState::<TestAction>::default();
1630        action_state.action_data.insert(
1631            TestAction::Axis,
1632            ActionData {
1633                disabled: false,
1634                kind_data: ActionKindData::Axis(AxisData {
1635                    value: 0.5,
1636                    update_value: 0.5,
1637                    fixed_update_value: 0.5,
1638                }),
1639            },
1640        );
1641        assert!(action_state.button_data(&TestAction::Axis).is_none());
1642    }
1643
1644    #[test]
1645    fn test_button_data_mut_for_button_action() {
1646        let mut action_state = ActionState::<TestAction>::default();
1647        action_state.action_data.insert(
1648            TestAction::Run,
1649            ActionData {
1650                disabled: false,
1651                kind_data: ActionKindData::Button(ButtonData {
1652                    state: ButtonState::Released,
1653                    update_state: ButtonState::Released,
1654                    fixed_update_state: ButtonState::Released,
1655                    value: 0.0,
1656                    update_value: 0.0,
1657                    fixed_update_value: 0.0,
1658                    #[cfg(feature = "timing")]
1659                    timing: Default::default(),
1660                }),
1661            },
1662        );
1663
1664        assert!(action_state.button_data_mut(&TestAction::Run).is_some());
1665    }
1666
1667    #[test]
1668    fn test_button_data_mut_for_button_action_without_data() {
1669        let mut action_state = ActionState::<TestAction>::default();
1670
1671        assert!(action_state.button_data_mut(&TestAction::Run).is_none());
1672    }
1673
1674    #[test]
1675    fn test_button_data_mut_for_non_button_action() {
1676        let mut action_state = ActionState::<TestAction>::default();
1677        action_state.action_data.insert(
1678            TestAction::Axis,
1679            ActionData {
1680                disabled: false,
1681                kind_data: ActionKindData::Axis(AxisData {
1682                    value: 0.5,
1683                    update_value: 0.5,
1684                    fixed_update_value: 0.5,
1685                }),
1686            },
1687        );
1688        assert!(action_state.button_data_mut(&TestAction::Axis).is_none());
1689    }
1690
1691    #[test]
1692    #[should_panic(expected = "assertion `left == right` failed\n  left: Axis\n right: Button")]
1693    fn test_button_data_mut_or_default_for_non_button_action() {
1694        let mut action_state = ActionState::<TestAction>::default();
1695        let _ = action_state.button_data_mut_or_default(&TestAction::Axis);
1696    }
1697
1698    #[test]
1699    fn test_axis_data_for_axis_action_without_data() {
1700        let action_state = ActionState::<TestAction>::default();
1701        assert!(action_state.axis_data(&TestAction::Axis).is_none());
1702    }
1703
1704    #[test]
1705    #[should_panic(expected = "assertion `left == right` failed\n  left: Button\n right: Axis")]
1706    fn test_axis_data_for_non_axis_action() {
1707        let action_state = ActionState::<TestAction>::default();
1708        assert!(action_state.axis_data(&TestAction::Run).is_none());
1709    }
1710
1711    #[test]
1712    fn test_axis_data_mut_for_axis_action() {
1713        let mut action_state = ActionState::<TestAction>::default();
1714        action_state.action_data.insert(
1715            TestAction::Axis,
1716            ActionData {
1717                disabled: false,
1718                kind_data: ActionKindData::Axis(AxisData {
1719                    value: 0.5,
1720                    update_value: 0.5,
1721                    fixed_update_value: 0.5,
1722                }),
1723            },
1724        );
1725        assert!(action_state.axis_data_mut(&TestAction::Axis).is_some());
1726    }
1727
1728    #[test]
1729    fn test_axis_data_mut_for_axis_action_without_data() {
1730        let mut action_state = ActionState::<TestAction>::default();
1731        assert!(action_state.axis_data_mut(&TestAction::Axis).is_none());
1732    }
1733
1734    #[test]
1735    fn test_axis_data_mut_for_non_axis_action() {
1736        let mut action_state = ActionState::<TestAction>::default();
1737        action_state.action_data.insert(
1738            TestAction::Run,
1739            ActionData {
1740                disabled: false,
1741                kind_data: ActionKindData::Button(ButtonData {
1742                    state: ButtonState::Released,
1743                    update_state: ButtonState::Released,
1744                    fixed_update_state: ButtonState::Released,
1745                    value: 0.0,
1746                    update_value: 0.0,
1747                    fixed_update_value: 0.0,
1748                    #[cfg(feature = "timing")]
1749                    timing: Default::default(),
1750                }),
1751            },
1752        );
1753        assert!(action_state.axis_data_mut(&TestAction::Run).is_none());
1754    }
1755
1756    #[test]
1757    #[should_panic(expected = "assertion `left == right` failed\n  left: Button\n right: Axis")]
1758    fn test_axis_data_mut_or_default_for_non_axis_action() {
1759        let mut action_state = ActionState::<TestAction>::default();
1760        let _ = action_state.axis_data_mut_or_default(&TestAction::Run);
1761    }
1762
1763    #[test]
1764    fn test_dual_axis_data_for_dual_axis_action_without_data() {
1765        let action_state = ActionState::<TestAction>::default();
1766        assert!(action_state.dual_axis_data(&TestAction::DualAxis).is_none());
1767    }
1768
1769    #[test]
1770    fn test_dual_axis_data_mut_for_dual_axis_action() {
1771        let mut action_state = ActionState::<TestAction>::default();
1772        action_state.action_data.insert(
1773            TestAction::DualAxis,
1774            ActionData {
1775                disabled: false,
1776                kind_data: ActionKindData::DualAxis(DualAxisData {
1777                    pair: Vec2::new(0.5, 0.5),
1778                    update_pair: Vec2::new(0.5, 0.5),
1779                    fixed_update_pair: Vec2::new(0.5, 0.5),
1780                }),
1781            },
1782        );
1783        assert!(
1784            action_state
1785                .dual_axis_data_mut(&TestAction::DualAxis)
1786                .is_some()
1787        );
1788    }
1789
1790    #[test]
1791    fn test_dual_axis_data_mut_for_dual_axis_action_without_data() {
1792        let mut action_state = ActionState::<TestAction>::default();
1793        assert!(
1794            action_state
1795                .dual_axis_data_mut(&TestAction::DualAxis)
1796                .is_none()
1797        );
1798    }
1799
1800    #[test]
1801    #[should_panic(expected = "assertion `left == right` failed\n  left: Button\n right: DualAxis")]
1802    fn test_dual_axis_data_mut_for_non_dual_axis_action() {
1803        let mut action_state = ActionState::<TestAction>::default();
1804        assert!(action_state.dual_axis_data_mut(&TestAction::Run).is_none());
1805    }
1806
1807    #[test]
1808    fn test_triple_axis_data_for_triple_axis_action_without_data() {
1809        let action_state = ActionState::<TestAction>::default();
1810        assert!(
1811            action_state
1812                .triple_axis_data(&TestAction::TripleAxis)
1813                .is_none()
1814        );
1815    }
1816
1817    #[test]
1818    fn test_triple_axis_data_mut_for_triple_axis_action() {
1819        let mut action_state = ActionState::<TestAction>::default();
1820        action_state.action_data.insert(
1821            TestAction::TripleAxis,
1822            ActionData {
1823                disabled: false,
1824                kind_data: ActionKindData::TripleAxis(crate::action_state::TripleAxisData {
1825                    triple: Vec3::new(0.5, 0.5, 0.5),
1826                    update_triple: Vec3::new(0.5, 0.5, 0.5),
1827                    fixed_update_triple: Vec3::new(0.5, 0.5, 0.5),
1828                }),
1829            },
1830        );
1831        assert!(
1832            action_state
1833                .triple_axis_data_mut(&TestAction::TripleAxis)
1834                .is_some()
1835        );
1836    }
1837
1838    #[test]
1839    fn test_button_value_for_disabled_button_action() {
1840        let mut action_state = ActionState::<TestAction>::default();
1841        action_state.action_data.insert(
1842            TestAction::Run,
1843            ActionData {
1844                disabled: true,
1845                kind_data: ActionKindData::Button(ButtonData {
1846                    state: ButtonState::Pressed,
1847                    update_state: ButtonState::Pressed,
1848                    fixed_update_state: ButtonState::Pressed,
1849                    value: 1.0,
1850                    update_value: 1.0,
1851                    fixed_update_value: 1.0,
1852                    #[cfg(feature = "timing")]
1853                    timing: Default::default(),
1854                }),
1855            },
1856        );
1857        action_state.disable_action(&TestAction::Run);
1858        assert_eq!(action_state.button_value(&TestAction::Run), 0.0);
1859    }
1860
1861    #[test]
1862    fn test_clamped_button_value_less_than_zero() {
1863        let mut action_state = ActionState::<TestAction>::default();
1864        action_state.set_button_value(&TestAction::Run, -0.5);
1865        assert_eq!(action_state.clamped_button_value(&TestAction::Run), 0.0);
1866    }
1867
1868    #[test]
1869    fn test_clamped_button_value_greater_than_zero() {
1870        let mut action_state: ActionState<TestAction> = ActionState::<TestAction>::default();
1871        action_state.set_button_value(&TestAction::Run, 1.5);
1872        assert_eq!(action_state.clamped_button_value(&TestAction::Run), 1.0);
1873    }
1874
1875    #[test]
1876    fn test_value_for_disabled_axis_action() {
1877        let mut action_state = ActionState::<TestAction>::default();
1878        action_state.action_data.insert(
1879            TestAction::Axis,
1880            ActionData {
1881                disabled: true,
1882                kind_data: ActionKindData::Axis(AxisData {
1883                    value: 1.0,
1884                    update_value: 1.0,
1885                    fixed_update_value: 1.0,
1886                }),
1887            },
1888        );
1889        action_state.disable_action(&TestAction::Axis);
1890        assert_eq!(action_state.value(&TestAction::Axis), 0.0);
1891    }
1892
1893    #[test]
1894    fn test_clamped_value_less_than_negative_one() {
1895        let mut action_state = ActionState::<TestAction>::default();
1896        action_state.set_value(&TestAction::Axis, -2.0);
1897        assert_eq!(action_state.clamped_value(&TestAction::Axis), -1.0);
1898    }
1899
1900    #[test]
1901    fn test_clamped_value_greater_than_one() {
1902        let mut action_state = ActionState::<TestAction>::default();
1903        action_state.set_value(&TestAction::Axis, 2.0);
1904        assert_eq!(action_state.clamped_value(&TestAction::Axis), 1.0);
1905    }
1906
1907    #[test]
1908    fn test_axis_pair_for_disabled_dual_axis_action() {
1909        let mut action_state = ActionState::<TestAction>::default();
1910        action_state.disable_action(&TestAction::DualAxis);
1911        assert_eq!(action_state.axis_pair(&TestAction::DualAxis), Vec2::ZERO);
1912    }
1913
1914    #[test]
1915    fn test_clamped_axis_pair_greater_than_vec2_one() {
1916        let mut action_state = ActionState::<TestAction>::default();
1917        action_state.set_axis_pair(&TestAction::DualAxis, Vec2::new(2.0, 2.0));
1918        assert_eq!(
1919            action_state.clamped_axis_pair(&TestAction::DualAxis),
1920            Vec2::ONE
1921        );
1922    }
1923
1924    #[test]
1925    fn test_clamped_axis_pair_less_than_vec2_negative_one() {
1926        let mut action_state = ActionState::<TestAction>::default();
1927        action_state.set_axis_pair(&TestAction::DualAxis, Vec2::new(-2.0, -2.0));
1928        assert_eq!(
1929            action_state.clamped_axis_pair(&TestAction::DualAxis),
1930            Vec2::NEG_ONE
1931        );
1932    }
1933
1934    #[test]
1935    fn test_axis_triple_for_disabled_triple_axis_action() {
1936        let mut action_state = ActionState::<TestAction>::default();
1937        action_state.disable_action(&TestAction::TripleAxis);
1938        assert_eq!(
1939            action_state.axis_triple(&TestAction::TripleAxis),
1940            Vec3::ZERO
1941        );
1942    }
1943
1944    #[test]
1945    fn test_clamped_axis_triple_greater_than_vec3_one() {
1946        let mut action_state = ActionState::<TestAction>::default();
1947        action_state.set_axis_triple(&TestAction::TripleAxis, Vec3::new(2.0, 2.0, 2.0));
1948        assert_eq!(
1949            action_state.clamped_axis_triple(&TestAction::TripleAxis),
1950            Vec3::ONE
1951        );
1952    }
1953
1954    #[test]
1955    fn test_clamped_axis_triple_less_than_vec3_negative_one() {
1956        let mut action_state = ActionState::<TestAction>::default();
1957        action_state.set_axis_triple(&TestAction::TripleAxis, Vec3::new(-2.0, -2.0, -2.0));
1958        assert_eq!(
1959            action_state.clamped_axis_triple(&TestAction::TripleAxis),
1960            Vec3::NEG_ONE
1961        );
1962    }
1963
1964    #[test]
1965    fn test_set_button_data_for_button_action() {
1966        let mut action_state = ActionState::<TestAction>::default();
1967        let button_data = ButtonData {
1968            state: ButtonState::Pressed,
1969            update_state: ButtonState::Pressed,
1970            fixed_update_state: ButtonState::Pressed,
1971            value: 1.0,
1972            update_value: 1.0,
1973            fixed_update_value: 1.0,
1974            #[cfg(feature = "timing")]
1975            timing: Default::default(),
1976        };
1977        action_state.set_button_data(TestAction::Run, button_data);
1978
1979        let returned_data = action_state.button_data(&TestAction::Run).unwrap();
1980        assert_eq!(returned_data.state, ButtonState::Pressed);
1981        assert_eq!(returned_data.value, 1.0);
1982    }
1983
1984    #[test]
1985    #[should_panic(expected = "assertion `left == right` failed\n  left: Axis\n right: Button")]
1986    fn test_set_button_data_for_non_button_action() {
1987        let mut action_state = ActionState::<TestAction>::default();
1988        let button_data = ButtonData {
1989            state: ButtonState::Pressed,
1990            update_state: ButtonState::Pressed,
1991            fixed_update_state: ButtonState::Pressed,
1992            value: 1.0,
1993            update_value: 1.0,
1994            fixed_update_value: 1.0,
1995            #[cfg(feature = "timing")]
1996            timing: Default::default(),
1997        };
1998        action_state.set_button_data(TestAction::Axis, button_data);
1999    }
2000
2001    #[test]
2002    fn test_reset_button_action() {
2003        let mut action_state = ActionState::<TestAction>::default();
2004        action_state.set_button_value(&TestAction::Run, 1.0);
2005        action_state.reset(&TestAction::Run);
2006
2007        assert!(!action_state.pressed(&TestAction::Run));
2008        assert_eq!(action_state.button_value(&TestAction::Run), 0.0);
2009    }
2010
2011    #[test]
2012    fn test_reset_axis_action() {
2013        let mut action_state = ActionState::<TestAction>::default();
2014        action_state.set_value(&TestAction::Axis, 1.0);
2015        action_state.reset(&TestAction::Axis);
2016
2017        assert_eq!(action_state.value(&TestAction::Axis), 0.0);
2018    }
2019
2020    #[test]
2021    fn test_reset_dual_axis_action() {
2022        let mut action_state = ActionState::<TestAction>::default();
2023        action_state.set_axis_pair(&TestAction::DualAxis, Vec2::ONE);
2024        action_state.reset(&TestAction::DualAxis);
2025
2026        assert_eq!(action_state.axis_pair(&TestAction::DualAxis), Vec2::ZERO);
2027    }
2028
2029    #[test]
2030    fn test_reset_triple_axis_action() {
2031        let mut action_state = ActionState::<TestAction>::default();
2032        action_state.set_axis_triple(&TestAction::TripleAxis, Vec3::ONE);
2033        action_state.reset(&TestAction::TripleAxis);
2034
2035        assert_eq!(
2036            action_state.axis_triple(&TestAction::TripleAxis),
2037            Vec3::ZERO
2038        );
2039    }
2040
2041    #[test]
2042    fn test_action_disabled_when_action_state_disabled() {
2043        let mut action_state = ActionState::<TestAction>::default();
2044        action_state.disable();
2045
2046        assert!(action_state.action_disabled(&TestAction::Run));
2047    }
2048
2049    #[test]
2050    fn test_action_disabled_when_action_state_not_disabled() {
2051        let mut action_state = ActionState::<TestAction>::default();
2052        assert!(!action_state.action_disabled(&TestAction::Run));
2053
2054        action_state.disable_action(&TestAction::Run);
2055        assert!(action_state.action_disabled(&TestAction::Run));
2056    }
2057
2058    #[test]
2059    fn test_disable() {
2060        let mut action_state = ActionState::<TestAction>::default();
2061        action_state.disable();
2062
2063        assert!(action_state.disabled);
2064    }
2065
2066    #[test]
2067    fn test_enable() {
2068        let mut action_state = ActionState::<TestAction>::default();
2069        action_state.disable();
2070        action_state.enable();
2071        assert!(!action_state.disabled);
2072    }
2073
2074    #[test]
2075    fn test_just_pressed_when_action_disabled() {
2076        let mut action_state = ActionState::<TestAction>::default();
2077        action_state.disable_action(&TestAction::Run);
2078
2079        assert!(!action_state.just_pressed(&TestAction::Run));
2080    }
2081
2082    #[test]
2083    fn test_released_when_action_disabled() {
2084        let mut action_state = ActionState::<TestAction>::default();
2085        action_state.disable_action(&TestAction::Run);
2086
2087        assert!(action_state.released(&TestAction::Run));
2088    }
2089
2090    #[test]
2091    fn test_just_released_when_action_disabled() {
2092        let mut action_state = ActionState::<TestAction>::default();
2093        action_state.disable_action(&TestAction::Run);
2094
2095        assert!(!action_state.just_released(&TestAction::Run));
2096    }
2097
2098    #[test]
2099    fn test_pressed_when_action_disabled() {
2100        let mut action_state = ActionState::<TestAction>::default();
2101        action_state.disable();
2102
2103        assert!(!action_state.pressed(&TestAction::Run));
2104    }
2105
2106    #[test]
2107    fn apply_diff_triple_axis() {
2108        let mut action_state = ActionState::<TestAction>::default();
2109        action_state.set_axis_triple(&TestAction::TripleAxis, Vec3::new(1.0, 1.0, 1.0));
2110
2111        let diff = ActionDiff::TripleAxisChanged {
2112            action: TestAction::TripleAxis,
2113            axis_triple: Vec3::new(0.5, 1.0, 1.5),
2114        };
2115        action_state.apply_diff(&diff);
2116
2117        assert_eq!(
2118            action_state.axis_triple(&TestAction::TripleAxis),
2119            Vec3::new(0.5, 1.0, 1.5)
2120        );
2121    }
2122
2123    #[test]
2124    fn test_get_pressed() {
2125        let mut action_state = ActionState::<TestAction>::default();
2126        action_state.set_button_value(&TestAction::Run, 1.0);
2127
2128        let pressed_actions: Vec<TestAction> = action_state.get_pressed();
2129        assert_eq!(pressed_actions.len(), 1);
2130        assert!(pressed_actions.contains(&TestAction::Run));
2131    }
2132
2133    #[test]
2134    fn test_get_just_pressed() {
2135        let mut action_state = ActionState::<TestAction>::default();
2136        action_state.set_button_value(&TestAction::Run, 1.0);
2137
2138        let just_pressed_actions: Vec<TestAction> = action_state.get_just_pressed();
2139        assert_eq!(just_pressed_actions.len(), 1);
2140        assert!(just_pressed_actions.contains(&TestAction::Run));
2141    }
2142
2143    #[test]
2144    fn test_get_released() {
2145        let mut action_state = ActionState::<TestAction>::default();
2146        action_state.set_button_value(&TestAction::Run, 0.0);
2147
2148        let released_actions: Vec<TestAction> = action_state.get_released();
2149        assert_eq!(released_actions.len(), 1);
2150        assert!(released_actions.contains(&TestAction::Run));
2151    }
2152
2153    #[test]
2154    fn test_get_just_released() {
2155        let mut action_state = ActionState::<TestAction>::default();
2156        action_state.set_button_value(&TestAction::Run, 1.0);
2157        action_state.set_button_value(&TestAction::Run, 0.0);
2158
2159        let just_released_actions: Vec<TestAction> = action_state.get_just_released();
2160        assert_eq!(just_released_actions.len(), 1);
2161        assert!(just_released_actions.contains(&TestAction::Run));
2162    }
2163
2164    #[cfg(feature = "gamepad")]
2165    #[test]
2166    fn test_triggerlikes() {
2167        use crate::prelude::Buttonlike;
2168
2169        let mut ctx = TestContext::new();
2170        let _gamepad = ctx.send_gamepad_connection_event(None);
2171        ctx.update();
2172
2173        let action_state = ctx.app.world().resource::<ActionState<TestAction>>();
2174        assert!(action_state.released(&TestAction::Trigger));
2175
2176        // App Context
2177        let mut ctx = TestContext::new();
2178        let gamepad = ctx.send_gamepad_connection_event(None);
2179        ctx.update();
2180
2181        GamepadButton::RightTrigger.set_value_as_gamepad(ctx.app.world_mut(), 0.8, Some(gamepad));
2182        ctx.update();
2183
2184        let action_state = ctx.app.world().resource::<ActionState<TestAction>>();
2185        assert!(action_state.pressed(&TestAction::Trigger));
2186        assert!(action_state.just_pressed(&TestAction::Trigger));
2187        assert_eq!(action_state.button_value(&TestAction::Trigger), 0.8);
2188    }
2189}