leafwing_input_manager/action_state/
mod.rs

1//! This module contains [`ActionState`] and its supporting methods and impls.
2
3use crate::input_map::UpdatedValue;
4use crate::{action_diff::ActionDiff, input_map::UpdatedActions};
5use crate::{Actionlike, InputControlKind};
6
7use bevy::platform::{collections::HashMap, time::Instant};
8use bevy::prelude::Resource;
9use bevy::reflect::Reflect;
10use bevy::{ecs::component::Component, prelude::ReflectComponent};
11use bevy::{
12    math::{Vec2, Vec3},
13    prelude::ReflectResource,
14};
15#[cfg(feature = "timing")]
16use core::time::Duration;
17use serde::{Deserialize, Serialize};
18
19mod action_data;
20pub use action_data::*;
21
22/// Stores the canonical input-method-agnostic representation of the inputs received
23///
24/// Can be used as either a resource or as a [`Component`] on entities that you wish to control directly from player input.
25///
26/// # Disabling actions
27///
28/// Actions can be disabled in four different ways, with increasing granularity:
29///
30/// 1. By disabling updates to all actions using a run condition on [`InputManagerSystem::Update`](crate::plugin::InputManagerSystem::Update).
31/// 2. By disabling updates to all actions of type `A` using a run condition on [`TickActionStateSystem::<A>`](crate::plugin::TickActionStateSystem).
32/// 3. By setting a specific action state to disabled using [`ActionState::disable`].
33/// 4. By disabling a specific action using [`ActionState::disable_action`].
34///
35/// More general mechanisms of disabling actions will cause specific mechanisms to be ignored.
36/// For example, if an entire action state is disabled, then enabling or disabling individual actions will have no effect.
37///
38/// Actions that are disabled will report as released (but not just released), and their values will be zero.
39/// Under the hood, their values are still updated to avoid surprising behavior when re-enabled,
40/// but they are not reported to the user using standard methods like [`ActionState::pressed`].
41/// To check the underlying values, access their [`ActionData`] directly.
42///
43/// # Example
44///
45/// ```rust
46/// use bevy::reflect::Reflect;
47/// use leafwing_input_manager::prelude::*;
48/// use bevy::platform::time::Instant;
49///
50/// #[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
51/// enum Action {
52///     Left,
53///     Right,
54///     Jump,
55/// }
56///
57/// let mut action_state = ActionState::<Action>::default();
58///
59/// // Typically, this is done automatically by the `InputManagerPlugin` from user inputs
60/// // using the `ActionState::update` method
61/// action_state.press(&Action::Jump);
62///
63/// assert!(action_state.pressed(&Action::Jump));
64/// assert!(action_state.just_pressed(&Action::Jump));
65/// assert!(action_state.released(&Action::Left));
66///
67/// // Resets just_pressed and just_released
68/// let t0 = Instant::now();
69/// let t1 = Instant::now();
70///
71///  action_state.tick(t1, t0);
72/// assert!(action_state.pressed(&Action::Jump));
73/// assert!(!action_state.just_pressed(&Action::Jump));
74///
75/// action_state.release(&Action::Jump);
76/// assert!(!action_state.pressed(&Action::Jump));
77/// assert!(action_state.released(&Action::Jump));
78/// assert!(action_state.just_released(&Action::Jump));
79///
80/// let t2 = Instant::now();
81/// action_state.tick(t2, t1);
82/// assert!(action_state.released(&Action::Jump));
83/// assert!(!action_state.just_released(&Action::Jump));
84/// ```
85#[derive(Resource, Component, Clone, Debug, PartialEq, Serialize, Deserialize, Reflect)]
86#[reflect(Resource, Component)]
87pub struct ActionState<A: Actionlike> {
88    /// Whether or not all of the actions are disabled.
89    disabled: bool,
90    /// The shared action data for each action
91    action_data: HashMap<A, ActionData>,
92}
93
94// The derive does not work unless A: Default,
95// so we have to implement it manually
96impl<A: Actionlike> Default for ActionState<A> {
97    fn default() -> Self {
98        Self {
99            disabled: false,
100            action_data: HashMap::default(),
101        }
102    }
103}
104
105impl<A: Actionlike> ActionState<A> {
106    /// Returns a reference to the complete [`ActionData`] for all actions.
107    #[inline]
108    #[must_use]
109    pub fn all_action_data(&self) -> &HashMap<A, ActionData> {
110        &self.action_data
111    }
112
113    /// We are about to enter the `Main` schedule, so we:
114    /// - save all the changes applied to `state` into the `fixed_update_state`
115    /// - switch to loading the `update_state`
116    pub(crate) fn swap_to_update_state(&mut self) {
117        for action_datum in self.action_data.values_mut() {
118            action_datum.kind_data.swap_to_update_state();
119        }
120    }
121
122    /// We are about to enter the `FixedMain` schedule, so we:
123    /// - save all the changes applied to `state` into the `update_state`
124    /// - switch to loading the `fixed_update_state`
125    pub(crate) fn swap_to_fixed_update_state(&mut self) {
126        for action_datum in self.action_data.values_mut() {
127            action_datum.kind_data.swap_to_fixed_update_state();
128        }
129    }
130
131    /// Updates the [`ActionState`] based on the provided [`UpdatedActions`].
132    ///
133    /// The `action_data` is typically constructed from [`InputMap::process_actions`](crate::input_map::InputMap::process_actions),
134    /// which reads from the assorted [`ButtonInput`](bevy::input::ButtonInput) resources.
135    ///
136    /// Actions that are disabled will still be updated: instead, their values will be read as released / zero.
137    /// You can see their underlying values by checking their [`ActionData`] directly.
138    pub fn update(&mut self, updated_actions: UpdatedActions<A>) {
139        for (action, updated_value) in updated_actions.iter() {
140            match updated_value {
141                UpdatedValue::Button(pressed) => {
142                    if *pressed {
143                        self.press(action);
144                    } else {
145                        self.release(action);
146                    }
147                }
148                UpdatedValue::Axis(value) => {
149                    self.set_value(action, *value);
150                }
151                UpdatedValue::DualAxis(pair) => {
152                    self.set_axis_pair(action, *pair);
153                }
154                UpdatedValue::TripleAxis(triple) => {
155                    self.set_axis_triple(action, *triple);
156                }
157            }
158        }
159    }
160
161    /// Advances the time for all actions,
162    /// transitioning them from `just_pressed` to `pressed`, and `just_released` to `released`.
163    ///
164    /// If the `timing` feature flag is enabled, the underlying timing and action data will be advanced according to the `current_instant`.
165    /// - if no [`Instant`] is set, the `current_instant` will be set as the initial time at which the button was pressed / released
166    /// - the [`Duration`] will advance to reflect elapsed time
167    ///
168    ///
169    /// # Example
170    /// ```rust
171    /// use bevy::prelude::Reflect;
172    /// use leafwing_input_manager::prelude::*;
173    /// use leafwing_input_manager::buttonlike::ButtonState;
174    /// use bevy::platform::time::Instant;
175    ///
176    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
177    /// enum Action {
178    ///     Run,
179    ///     Jump,
180    /// }
181    ///
182    /// let mut action_state = ActionState::<Action>::default();
183    ///
184    /// // Actions start released
185    /// assert!(action_state.released(&Action::Jump));
186    /// assert!(!action_state.just_released(&Action::Run));
187    ///
188    /// // Ticking time moves causes buttons just released to no longer be just released
189    /// let t0 = Instant::now();
190    /// let t1 = Instant::now();
191    ///
192    /// action_state.tick(t1, t0);
193    /// assert!(action_state.released(&Action::Jump));
194    /// assert!(!action_state.just_released(&Action::Jump));
195    ///
196    /// action_state.press(&Action::Jump);
197    /// assert!(action_state.just_pressed(&Action::Jump));
198    ///
199    /// // Ticking time moves causes buttons just pressed to no longer be just pressed
200    /// let t2 = Instant::now();
201    ///
202    /// action_state.tick(t2, t1);
203    /// assert!(action_state.pressed(&Action::Jump));
204    /// assert!(!action_state.just_pressed(&Action::Jump));
205    /// ```
206    pub fn tick(&mut self, _current_instant: Instant, _previous_instant: Instant) {
207        // Advanced the action states
208        self.action_data
209            .values_mut()
210            .for_each(|action_datum| action_datum.tick(_current_instant, _previous_instant));
211    }
212
213    /// A reference to the [`ActionData`] corresponding to the `action`.
214    #[inline]
215    #[must_use]
216    pub fn action_data(&self, action: &A) -> Option<&ActionData> {
217        self.action_data.get(action)
218    }
219
220    /// A mutable reference to the [`ActionData`] corresponding to the `action`.
221    ///
222    /// To initialize the [`ActionData`] if it has not yet been triggered,
223    /// use [`action_data_mut_or_default`](Self::action_data_mut_or_default) method.
224    #[inline]
225    #[must_use]
226    pub fn action_data_mut(&mut self, action: &A) -> Option<&mut ActionData> {
227        self.action_data.get_mut(action)
228    }
229
230    /// A mutable reference to the [`ActionData`] corresponding to the `action`, initializing it if needed.
231    ///
232    /// If the `action` has no data yet (because the `action` has not been triggered),
233    /// this method will create and insert a default [`ActionData`] for you,
234    /// avoiding potential errors from unwrapping [`None`].
235    pub fn action_data_mut_or_default(&mut self, action: &A) -> &mut ActionData {
236        if self.action_data.contains_key(action) {
237            // Safe to unwrap because we just checked
238            self.action_data.get_mut(action).unwrap()
239        } else {
240            self.action_data.insert(
241                action.clone(),
242                ActionData::from_kind(action.input_control_kind()),
243            );
244            // Safe to unwrap because we just inserted
245            self.action_data_mut(action).unwrap()
246        }
247    }
248
249    /// A reference of the [`ButtonData`] corresponding to the `action`.
250    ///
251    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
252    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
253    ///
254    /// # Caution
255    ///
256    /// To access the [`ButtonData`] regardless of whether the `action` has been triggered,
257    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
258    ///
259    /// # Returns
260    ///
261    /// - `Some(ButtonData)` if it exists.
262    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
263    #[inline]
264    #[must_use]
265    pub fn button_data(&self, action: &A) -> Option<&ButtonData> {
266        match self.action_data(action) {
267            Some(action_data) => match action_data.kind_data {
268                ActionKindData::Button(ref button_data) => Some(button_data),
269                _ => None,
270            },
271            None => None,
272        }
273    }
274
275    /// A mutable reference of the [`ButtonData`] corresponding to the `action`.
276    ///
277    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
278    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
279    ///
280    /// # Caution
281    ///
282    /// To access the [`ButtonData`] regardless of whether the `action` has been triggered,
283    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
284    ///
285    /// To insert a default [`ButtonData`] if it doesn't exist,
286    /// use [`button_data_mut_or_default`](Self::button_data_mut_or_default) method.
287    ///
288    /// # Returns
289    ///
290    /// - `Some(ButtonData)` if it exists.
291    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
292    #[inline]
293    #[must_use]
294    pub fn button_data_mut(&mut self, action: &A) -> Option<&mut ButtonData> {
295        match self.action_data_mut(action) {
296            Some(action_data) => match &mut action_data.kind_data {
297                ActionKindData::Button(ref mut button_data) => Some(button_data),
298                _ => None,
299            },
300            None => None,
301        }
302    }
303
304    /// A mutable reference of the [`ButtonData`] corresponding to the `action`, initializing it if needed.
305    ///
306    /// If the `action` has no data yet (because the `action` has not been triggered),
307    /// this method will create and insert a default [`ButtonData`] for you,
308    /// avoiding potential errors from unwrapping [`None`].
309    ///
310    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
311    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
312    #[inline]
313    #[must_use]
314    #[track_caller]
315    pub fn button_data_mut_or_default(&mut self, action: &A) -> &mut ButtonData {
316        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
317
318        let action_data = self.action_data_mut_or_default(action);
319        let ActionKindData::Button(ref mut button_data) = action_data.kind_data else {
320            panic!("{action:?} is not a Button");
321        };
322        button_data
323    }
324
325    /// A reference of the [`AxisData`] corresponding to the `action`.
326    ///
327    /// # Caution
328    ///
329    /// To access the [`AxisData`] regardless of whether the `action` has been triggered,
330    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
331    ///
332    /// # Returns
333    ///
334    /// - `Some(AxisData)` if it exists.
335    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
336    #[inline]
337    #[must_use]
338    #[track_caller]
339    pub fn axis_data(&self, action: &A) -> Option<&AxisData> {
340        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
341
342        match self.action_data(action) {
343            Some(action_data) => match action_data.kind_data {
344                ActionKindData::Axis(ref axis_data) => Some(axis_data),
345                _ => None,
346            },
347            None => None,
348        }
349    }
350
351    /// A mutable reference of the [`AxisData`] corresponding to the `action`.
352    ///
353    /// # Caution
354    ///
355    /// To insert a default [`AxisData`] if it doesn't exist,
356    /// use [`axis_data_mut_or_default`](Self::axis_data_mut_or_default) method.
357    ///
358    /// # Returns
359    ///
360    /// - `Some(AxisData)` if it exists.
361    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
362    #[inline]
363    #[must_use]
364    pub fn axis_data_mut(&mut self, action: &A) -> Option<&mut AxisData> {
365        match self.action_data_mut(action) {
366            Some(action_data) => match &mut action_data.kind_data {
367                ActionKindData::Axis(ref mut axis_data) => Some(axis_data),
368                _ => None,
369            },
370            None => None,
371        }
372    }
373
374    /// A mutable reference of the [`AxisData`] corresponding to the `action`, initializing it if needed..
375    ///
376    /// If the `action` has no data yet (because the `action` has not been triggered),
377    /// this method will create and insert a default [`AxisData`] for you,
378    /// avoiding potential errors from unwrapping [`None`].
379    ///
380    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
381    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
382    #[inline]
383    #[must_use]
384    #[track_caller]
385    pub fn axis_data_mut_or_default(&mut self, action: &A) -> &mut AxisData {
386        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
387
388        let action_data = self.action_data_mut_or_default(action);
389        let ActionKindData::Axis(ref mut axis_data) = action_data.kind_data else {
390            panic!("{action:?} is not an Axis");
391        };
392        axis_data
393    }
394
395    /// A reference of the [`DualAxisData`] corresponding to the `action`.
396    ///
397    /// # Caution
398    ///
399    /// To access the [`DualAxisData`] regardless of whether the `action` has been triggered,
400    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
401    ///
402    /// # Returns
403    ///
404    /// - `Some(DualAxisData)` if it exists.
405    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
406    #[inline]
407    #[must_use]
408    #[track_caller]
409    pub fn dual_axis_data(&self, action: &A) -> Option<&DualAxisData> {
410        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
411
412        match self.action_data(action) {
413            Some(action_data) => match action_data.kind_data {
414                ActionKindData::DualAxis(ref dual_axis_data) => Some(dual_axis_data),
415                _ => None,
416            },
417            None => None,
418        }
419    }
420
421    /// A mutable reference of the [`DualAxisData`] corresponding to the `action`.
422    ///
423    /// # Caution
424    ///
425    /// To insert a default [`DualAxisData`] if it doesn't exist,
426    /// use [`dual_axis_data_mut_or_default`](Self::dual_axis_data_mut_or_default) method.
427    ///
428    /// # Returns
429    ///
430    /// - `Some(DualAxisData)` if it exists.
431    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
432    #[inline]
433    #[must_use]
434    #[track_caller]
435    pub fn dual_axis_data_mut(&mut self, action: &A) -> Option<&mut DualAxisData> {
436        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
437
438        match self.action_data_mut(action) {
439            Some(action_data) => match &mut action_data.kind_data {
440                ActionKindData::DualAxis(ref mut dual_axis_data) => Some(dual_axis_data),
441                _ => None,
442            },
443            None => None,
444        }
445    }
446
447    /// A mutable reference of the [`DualAxisData`] corresponding to the `action` initializing it if needed.
448    ///
449    /// If the `action` has no data yet (because the `action` has not been triggered),
450    /// this method will create and insert a default [`DualAxisData`] for you,
451    /// avoiding potential errors from unwrapping [`None`].
452    ///
453    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
454    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
455    #[inline]
456    #[must_use]
457    #[track_caller]
458    pub fn dual_axis_data_mut_or_default(&mut self, action: &A) -> &mut DualAxisData {
459        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
460
461        let action_data = self.action_data_mut_or_default(action);
462        let ActionKindData::DualAxis(ref mut dual_axis_data) = action_data.kind_data else {
463            panic!("{action:?} is not a DualAxis");
464        };
465        dual_axis_data
466    }
467
468    /// A reference of the [`TripleAxisData`] corresponding to the `action`.
469    ///
470    /// # Caution
471    ///
472    /// To access the [`TripleAxisData`] regardless of whether the `action` has been triggered,
473    /// use [`unwrap_or_default`](Option::unwrap_or_default) on the returned [`Option`].
474    ///
475    /// # Returns
476    ///
477    /// - `Some(TripleAxisData)` if it exists.
478    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
479    #[inline]
480    #[must_use]
481    #[track_caller]
482    pub fn triple_axis_data(&self, action: &A) -> Option<&TripleAxisData> {
483        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
484
485        match self.action_data(action) {
486            Some(action_data) => match action_data.kind_data {
487                ActionKindData::TripleAxis(ref triple_axis_data) => Some(triple_axis_data),
488                _ => None,
489            },
490            None => None,
491        }
492    }
493
494    /// A mutable reference of the [`TripleAxisData`] corresponding to the `action`.
495    ///
496    /// # Caution
497    ///
498    /// To insert a default [`TripleAxisData`] if it doesn't exist,
499    /// use [`triple_axis_data_mut_or_default`](Self::dual_axis_data_mut_or_default) method.
500    ///
501    /// # Returns
502    ///
503    /// - `Some(ButtonData)` if it exists.
504    /// - `None` if the `action` has never been triggered (pressed, clicked, etc.).
505    #[inline]
506    #[must_use]
507    #[track_caller]
508    pub fn triple_axis_data_mut(&mut self, action: &A) -> Option<&mut TripleAxisData> {
509        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
510
511        match self.action_data_mut(action) {
512            Some(action_data) => match &mut action_data.kind_data {
513                ActionKindData::TripleAxis(ref mut triple_axis_data) => Some(triple_axis_data),
514                _ => None,
515            },
516            None => None,
517        }
518    }
519
520    /// A mutable reference of the [`TripleAxisData`] corresponding to the `action` initializing it if needed.
521    ///
522    /// If the `action` has no data yet (because the `action` has not been triggered),
523    /// this method will create and insert a default [`TripleAxisData`] for you,
524    /// avoiding potential errors from unwrapping [`None`].
525    ///
526    /// Generally, it'll be clearer to call `pressed` or so on directly on the [`ActionState`].
527    /// However, accessing the raw data directly allows you to examine detailed metadata holistically.
528    #[inline]
529    #[must_use]
530    #[track_caller]
531    pub fn triple_axis_data_mut_or_default(&mut self, action: &A) -> &mut TripleAxisData {
532        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
533
534        let action_data = self.action_data_mut_or_default(action);
535        let ActionKindData::TripleAxis(ref mut triple_axis_data) = action_data.kind_data else {
536            panic!("{action:?} is not a TripleAxis");
537        };
538        triple_axis_data
539    }
540
541    /// Get the value associated with the corresponding buttonlike `action` if present.
542    ///
543    /// # Warnings
544    ///
545    /// This value may not be bounded as you might expect.
546    /// Consider clamping this to account for multiple triggering inputs,
547    /// typically using the [`clamped_button_value`](Self::clamped_button_value) method instead.
548    #[inline]
549    #[must_use]
550    #[track_caller]
551    pub fn button_value(&self, action: &A) -> f32 {
552        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
553
554        if self.action_disabled(action) {
555            return 0.0;
556        }
557
558        let action_data = self.button_data(action);
559        action_data.map_or(0.0, |action_data| action_data.value)
560    }
561
562    /// Sets the value of the buttonlike `action` to the provided `value`.
563    ///
564    /// Also updates the state of the button based on the `value`:
565    /// - If `value > 0.0`, the button will be pressed.
566    /// - If `value <= 0.0`, the button will be released.
567    #[track_caller]
568    pub fn set_button_value(&mut self, action: &A, value: f32) {
569        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
570
571        let button_data = self.button_data_mut_or_default(action);
572        button_data.value = value;
573
574        if value > 0.0 {
575            #[cfg(feature = "timing")]
576            if button_data.state.released() {
577                button_data.timing.flip();
578            }
579
580            button_data.state.press();
581        } else {
582            #[cfg(feature = "timing")]
583            if button_data.state.pressed() {
584                button_data.timing.flip();
585            }
586
587            button_data.state.release();
588        }
589    }
590
591    /// Get the value associated with the corresponding `action`, clamped to `[0.0, 1.0]`.
592    ///
593    /// # Warning
594    ///
595    /// This value will be 0. by default,
596    /// even if the action is not a buttonlike action.
597    pub fn clamped_button_value(&self, action: &A) -> f32 {
598        self.button_value(action).clamp(0., 1.)
599    }
600
601    /// Get the value associated with the corresponding axislike `action` if present.
602    ///
603    /// # Warnings
604    ///
605    /// This value may not be bounded as you might expect.
606    /// Consider clamping this to account for multiple triggering inputs,
607    /// typically using the [`clamped_value`](Self::clamped_value) method instead.
608    #[inline]
609    #[must_use]
610    #[track_caller]
611    pub fn value(&self, action: &A) -> f32 {
612        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
613
614        if self.action_disabled(action) {
615            return 0.0;
616        }
617
618        let action_data = self.axis_data(action);
619        action_data.map_or(0.0, |action_data| action_data.value)
620    }
621
622    /// Sets the value of the axislike `action` to the provided `value`.
623    #[track_caller]
624    pub fn set_value(&mut self, action: &A, value: f32) {
625        debug_assert_eq!(action.input_control_kind(), InputControlKind::Axis);
626
627        let axis_data = self.axis_data_mut_or_default(action);
628        axis_data.value = value;
629    }
630
631    /// Get the value associated with the corresponding `action`, clamped to `[-1.0, 1.0]`.
632    ///
633    /// # Warning
634    ///
635    /// This value will be 0. by default,
636    /// even if the action is not an axislike action.
637    pub fn clamped_value(&self, action: &A) -> f32 {
638        self.value(action).clamp(-1., 1.)
639    }
640
641    /// Get the [`Vec2`] from the binding that triggered the corresponding `action`.
642    ///
643    /// Only events that represent dual-axis control provide a [`Vec2`],
644    /// and this will return [`None`] for other events.
645    ///
646    /// If multiple inputs with an axis pair trigger the same game action at the same time, the
647    /// value of each axis pair will be added together.
648    ///
649    /// # Warning
650    ///
651    /// This value will be [`Vec2::ZERO`] by default,
652    /// even if the action is not a dual-axislike action.
653    ///
654    /// These values may not be bounded as you might expect.
655    /// Consider clamping this to account for multiple triggering inputs,
656    /// typically using the [`clamped_axis_pair`](Self::clamped_axis_pair) method instead.
657    #[must_use]
658    #[track_caller]
659    pub fn axis_pair(&self, action: &A) -> Vec2 {
660        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
661
662        if self.action_disabled(action) {
663            return Vec2::ZERO;
664        }
665
666        let action_data = self.dual_axis_data(action);
667        action_data.map_or(Vec2::ZERO, |action_data| action_data.pair)
668    }
669
670    /// Sets the [`Vec2`] of the `action` to the provided `pair`.
671    #[track_caller]
672    pub fn set_axis_pair(&mut self, action: &A, pair: Vec2) {
673        debug_assert_eq!(action.input_control_kind(), InputControlKind::DualAxis);
674
675        let dual_axis_data = self.dual_axis_data_mut_or_default(action);
676        dual_axis_data.pair = pair;
677    }
678
679    /// Get the [`Vec2`] associated with the corresponding `action`, clamped to `[-1.0, 1.0]`.
680    ///  
681    /// # Warning
682    ///
683    /// This value will be [`Vec2::ZERO`] by default,
684    /// even if the action is not a dual-axislike action.
685    pub fn clamped_axis_pair(&self, action: &A) -> Vec2 {
686        let pair = self.axis_pair(action);
687        pair.clamp(Vec2::NEG_ONE, Vec2::ONE)
688    }
689
690    /// Get the [`Vec3`] from the binding that triggered the corresponding `action`.
691    ///
692    /// Only events that represent triple-axis control provide a [`Vec3`],
693    /// and this will return [`None`] for other events.
694    ///
695    /// If multiple inputs with an axis triple trigger the same game action at the same time, the
696    /// value of each axis triple will be added together.
697    ///
698    /// # Warning
699    ///
700    /// This value will be [`Vec3::ZERO`] by default,
701    /// even if the action is not a triple-axislike action.
702    ///
703    /// These values may not be bounded as you might expect.
704    /// Consider clamping this to account for multiple triggering inputs,
705    /// typically using the [`clamped_axis_triple`](Self::clamped_axis_triple) method instead.
706    #[must_use]
707    #[track_caller]
708    pub fn axis_triple(&self, action: &A) -> Vec3 {
709        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
710
711        if self.action_disabled(action) {
712            return Vec3::ZERO;
713        }
714
715        let action_data = self.triple_axis_data(action);
716        action_data.map_or(Vec3::ZERO, |action_data| action_data.triple)
717    }
718
719    /// Sets the [`Vec2`] of the `action` to the provided `pair`.
720    #[track_caller]
721    pub fn set_axis_triple(&mut self, action: &A, triple: Vec3) {
722        debug_assert_eq!(action.input_control_kind(), InputControlKind::TripleAxis);
723
724        let triple_axis_data = self.triple_axis_data_mut_or_default(action);
725        triple_axis_data.triple = triple;
726    }
727
728    /// Get the [`Vec3`] associated with the corresponding `action`, clamped to the cube of values bounded by -1 and 1 on all axes.
729    ///
730    /// # Warning
731    ///
732    /// This value will be [`Vec3::ZERO`] by default,
733    /// even if the action is not a dual-axislike action.
734    pub fn clamped_axis_triple(&self, action: &A) -> Vec3 {
735        let triple = self.axis_triple(action);
736        triple.clamp(Vec3::NEG_ONE, Vec3::ONE)
737    }
738
739    /// Manually sets the [`ButtonData`] of the corresponding `action`
740    ///
741    /// You should almost always use more direct methods, as they are simpler and less error-prone.
742    ///
743    /// However, this method can be useful for testing,
744    /// or when transferring [`ButtonData`] between action states.
745    ///
746    /// # Example
747    /// ```rust
748    /// use bevy::prelude::Reflect;
749    /// use leafwing_input_manager::prelude::*;
750    ///
751    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
752    /// enum AbilitySlot {
753    ///     Slot1,
754    ///     Slot2,
755    /// }
756    ///
757    /// #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
758    /// enum Action {
759    ///     Run,
760    ///     Jump,
761    /// }
762    ///
763    /// let mut ability_slot_state = ActionState::<AbilitySlot>::default();
764    /// let mut action_state = ActionState::<Action>::default();
765    ///
766    /// // Extract the state from the ability slot
767    /// let slot_1_state = ability_slot_state.button_data(&AbilitySlot::Slot1);
768    ///
769    /// // And transfer it to the actual ability that we care about
770    /// // without losing timing information
771    /// if let Some(state) = slot_1_state {
772    ///    action_state.set_button_data(Action::Run, state.clone());
773    /// }
774    /// ```
775    #[inline]
776    #[track_caller]
777    pub fn set_button_data(&mut self, action: A, data: ButtonData) {
778        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
779
780        let button_data = self.button_data_mut_or_default(&action);
781        *button_data = data;
782    }
783
784    /// Press the `action`
785    ///
786    /// No initial instant or reasons why the button was pressed will be recorded.
787    /// Instead, this is set through [`ActionState::tick()`]
788    #[inline]
789    #[track_caller]
790    pub fn press(&mut self, action: &A) {
791        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
792
793        let action_data = self.button_data_mut_or_default(action);
794
795        #[cfg(feature = "timing")]
796        if action_data.state.released() {
797            action_data.timing.flip();
798        }
799
800        action_data.state.press();
801        action_data.value = 1.0;
802    }
803
804    /// Release the `action`
805    ///
806    /// No initial instant will be recorded.
807    /// Instead, this is set through [`ActionState::tick()`]
808    #[inline]
809    pub fn release(&mut self, action: &A) {
810        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
811
812        let action_data = self.button_data_mut_or_default(action);
813
814        #[cfg(feature = "timing")]
815        if action_data.state.pressed() {
816            action_data.timing.flip();
817        }
818
819        action_data.state.release();
820        action_data.value = 0.0;
821    }
822
823    /// Resets an action to its default state.
824    ///
825    /// Buttons will be released, and axes will be set to 0.
826    pub fn reset(&mut self, action: &A) {
827        match action.input_control_kind() {
828            InputControlKind::Button => self.release(action),
829            InputControlKind::Axis => {
830                self.set_value(action, 0.0);
831            }
832            InputControlKind::DualAxis => {
833                self.set_axis_pair(action, Vec2::ZERO);
834            }
835            InputControlKind::TripleAxis => {
836                self.set_axis_triple(action, Vec3::ZERO);
837            }
838        }
839    }
840
841    /// Releases all [`Buttonlike`](crate::user_input::Buttonlike) actions,
842    /// sets all [`Axislike`](crate::user_input::Axislike) actions to 0,
843    /// sets all [`DualAxislike`](crate::user_input::DualAxislike) actions to [`Vec2::ZERO`],
844    /// and sets all [`TripleAxislike`](crate::user_input::TripleAxislike) actions to [`Vec3::ZERO`].
845    pub fn reset_all(&mut self) {
846        // Collect out to avoid angering the borrow checker
847        let all_actions = self.action_data.keys().cloned().collect::<Vec<A>>();
848        for action in all_actions.into_iter() {
849            self.reset(&action);
850        }
851    }
852
853    /// Is the entire [`ActionState`] currently disabled?
854    pub fn disabled(&self) -> bool {
855        self.disabled
856    }
857
858    /// Is this `action` currently disabled?
859    #[inline]
860    #[must_use]
861    pub fn action_disabled(&self, action: &A) -> bool {
862        if self.disabled {
863            return true;
864        }
865
866        match self.action_data(action) {
867            Some(action_data) => action_data.disabled,
868            None => false,
869        }
870    }
871
872    /// Disables the entire [`ActionState`].
873    ///
874    /// All values will be reset to their default state.
875    #[inline]
876    pub fn disable(&mut self) {
877        self.disabled = true;
878        self.reset_all();
879    }
880
881    /// Disables the `action`.
882    ///
883    /// The action's value will be reset to its default state.
884    #[inline]
885    pub fn disable_action(&mut self, action: &A) {
886        let action_data = self.action_data_mut_or_default(action);
887
888        action_data.disabled = true;
889        self.reset(action);
890    }
891
892    /// Disables all actions
893    #[inline]
894    pub fn disable_all_actions(&mut self) {
895        for action in self.keys() {
896            self.disable_action(&action);
897        }
898    }
899
900    /// Enables the entire [`ActionState`]
901    #[inline]
902    pub fn enable(&mut self) {
903        self.disabled = false;
904    }
905
906    /// Enables the `action`
907    #[inline]
908    pub fn enable_action(&mut self, action: &A) {
909        let action_data = self.action_data_mut_or_default(action);
910
911        action_data.disabled = false;
912    }
913
914    /// Enables all actions
915    #[inline]
916    pub fn enable_all_actions(&mut self) {
917        for action in self.keys() {
918            self.enable_action(&action);
919        }
920    }
921
922    /// Is this `action` currently pressed?
923    ///
924    /// # Warning
925    ///
926    /// This value will be `false` by default,
927    /// even if the action is not a buttonlike action.
928    #[inline]
929    #[must_use]
930    #[track_caller]
931    pub fn pressed(&self, action: &A) -> bool {
932        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
933
934        if self.action_disabled(action) {
935            return false;
936        }
937
938        match self.button_data(action) {
939            Some(button_data) => button_data.pressed(),
940            None => false,
941        }
942    }
943
944    /// Was this `action` pressed since the last time [tick](ActionState::tick) was called?
945    ///
946    /// # Warning
947    ///
948    /// This value will be `false` by default,
949    /// even if the action is not a buttonlike action.
950    #[inline]
951    #[must_use]
952    #[track_caller]
953    pub fn just_pressed(&self, action: &A) -> bool {
954        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
955
956        if self.action_disabled(action) {
957            return false;
958        }
959
960        match self.button_data(action) {
961            Some(button_data) => button_data.just_pressed(),
962            None => false,
963        }
964    }
965
966    /// Is this `action` currently released?
967    ///
968    /// This is always the logical negation of [pressed](ActionState::pressed)
969    ///
970    /// # Warning
971    ///
972    /// This value will be `true` by default,
973    /// even if the action is not a buttonlike action.
974    #[inline]
975    #[must_use]
976    #[track_caller]
977    pub fn released(&self, action: &A) -> bool {
978        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
979
980        if self.action_disabled(action) {
981            return true;
982        }
983
984        match self.button_data(action) {
985            Some(button_data) => button_data.released(),
986            None => true,
987        }
988    }
989
990    /// Was this `action` released since the last time [tick](ActionState::tick) was called?
991    ///
992    /// # Warning
993    ///
994    /// This value will be `false` by default,
995    /// even if the action is not a buttonlike action.
996    #[inline]
997    #[must_use]
998    #[track_caller]
999    pub fn just_released(&self, action: &A) -> bool {
1000        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1001
1002        if self.action_disabled(action) {
1003            return false;
1004        }
1005
1006        match self.button_data(action) {
1007            Some(button_data) => button_data.just_released(),
1008            None => false,
1009        }
1010    }
1011
1012    #[must_use]
1013    /// Which actions are currently pressed?
1014    pub fn get_pressed(&self) -> Vec<A> {
1015        let all_actions = self.action_data.keys().cloned();
1016
1017        all_actions
1018            .into_iter()
1019            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1020            .filter(|action| self.pressed(action))
1021            .collect()
1022    }
1023
1024    #[must_use]
1025    /// Which actions were just pressed?
1026    pub fn get_just_pressed(&self) -> Vec<A> {
1027        let all_actions = self.action_data.keys().cloned();
1028
1029        all_actions
1030            .into_iter()
1031            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1032            .filter(|action| self.just_pressed(action))
1033            .collect()
1034    }
1035
1036    #[must_use]
1037    /// Which actions are currently released?
1038    pub fn get_released(&self) -> Vec<A> {
1039        let all_actions = self.action_data.keys().cloned();
1040
1041        all_actions
1042            .into_iter()
1043            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1044            .filter(|action| self.released(action))
1045            .collect()
1046    }
1047
1048    #[must_use]
1049    /// Which actions were just released?
1050    pub fn get_just_released(&self) -> Vec<A> {
1051        let all_actions = self.action_data.keys().cloned();
1052
1053        all_actions
1054            .into_iter()
1055            .filter(|action| action.input_control_kind() == InputControlKind::Button)
1056            .filter(|action| self.just_released(action))
1057            .collect()
1058    }
1059
1060    /// The [`Instant`] that the action was last pressed or released
1061    ///
1062    ///
1063    ///
1064    /// If the action was pressed or released since the last time [`ActionState::tick`] was called
1065    /// the value will be [`None`].
1066    /// This ensures that all our actions are assigned a timing and duration
1067    /// that corresponds exactly to the start of a frame, rather than relying on idiosyncratic timing.
1068    ///
1069    /// This will also be [`None`] if the action was never pressed or released.
1070    #[cfg(feature = "timing")]
1071    #[must_use]
1072    #[track_caller]
1073    pub fn instant_started(&self, action: &A) -> Option<Instant> {
1074        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1075
1076        let button_data = self.button_data(action)?;
1077        button_data.timing.instant_started
1078    }
1079
1080    /// The [`Duration`] for which the action has been held or released
1081    ///
1082    /// This will be [`Duration::ZERO`] if the action was never pressed or released.
1083    #[cfg(feature = "timing")]
1084    #[must_use]
1085    #[track_caller]
1086    pub fn current_duration(&self, action: &A) -> Duration {
1087        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1088
1089        self.button_data(action)
1090            .map(|data| data.timing.current_duration)
1091            .unwrap_or_default()
1092    }
1093
1094    /// The [`Duration`] for which the action was last held or released
1095    ///
1096    /// This is a snapshot of the [`ActionState::current_duration`] state at the time
1097    /// the action was last pressed or released.
1098    ///
1099    /// This will be [`Duration::ZERO`] if the action was never pressed or released.
1100    #[cfg(feature = "timing")]
1101    #[must_use]
1102    #[track_caller]
1103    pub fn previous_duration(&self, action: &A) -> Duration {
1104        debug_assert_eq!(action.input_control_kind(), InputControlKind::Button);
1105
1106        self.button_data(action)
1107            .map(|data| data.timing.previous_duration)
1108            .unwrap_or_default()
1109    }
1110
1111    /// Applies an [`ActionDiff`] (usually received over the network) to the [`ActionState`].
1112    ///
1113    /// This lets you reconstruct an [`ActionState`] from a stream of [`ActionDiff`]s
1114    pub fn apply_diff(&mut self, action_diff: &ActionDiff<A>) {
1115        match action_diff {
1116            ActionDiff::Pressed { action, value } => {
1117                self.set_button_value(action, *value);
1118            }
1119            ActionDiff::Released { action } => {
1120                self.release(action);
1121            }
1122            ActionDiff::AxisChanged { action, value } => {
1123                self.set_value(action, *value);
1124            }
1125            ActionDiff::DualAxisChanged { action, axis_pair } => {
1126                self.set_axis_pair(action, *axis_pair);
1127            }
1128            ActionDiff::TripleAxisChanged {
1129                action,
1130                axis_triple,
1131            } => {
1132                self.set_axis_triple(action, *axis_triple);
1133            }
1134        };
1135    }
1136
1137    /// Returns an owned list of the [`Actionlike`] keys in this [`ActionState`].
1138    #[inline]
1139    #[must_use]
1140    pub fn keys(&self) -> Vec<A> {
1141        self.action_data.keys().cloned().collect()
1142    }
1143}
1144
1145#[cfg(test)]
1146mod tests {
1147    use crate as leafwing_input_manager;
1148    use crate::action_state::ActionState;
1149    use bevy::prelude::*;
1150    use leafwing_input_manager_macros::Actionlike;
1151
1152    #[cfg(feature = "keyboard")]
1153    #[test]
1154    fn press_lifecycle() {
1155        use std::time::{Duration, Instant};
1156
1157        use crate::input_map::InputMap;
1158        use crate::plugin::CentralInputStorePlugin;
1159        use crate::prelude::updating::CentralInputStore;
1160        use crate::prelude::ClashStrategy;
1161        use crate::user_input::Buttonlike;
1162        use bevy::input::InputPlugin;
1163
1164        let mut app = App::new();
1165        app.add_plugins((InputPlugin, CentralInputStorePlugin));
1166
1167        #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, bevy::prelude::Reflect)]
1168        enum Action {
1169            Run,
1170            Jump,
1171            Hide,
1172        }
1173
1174        // Action state
1175        let mut action_state = ActionState::<Action>::default();
1176        println!(
1177            "Default button data: {:?}",
1178            action_state.button_data(&Action::Run)
1179        );
1180
1181        // Input map
1182        let mut input_map = InputMap::default();
1183        input_map.insert(Action::Run, KeyCode::KeyR);
1184
1185        // Starting state
1186        let input_store = app.world().resource::<CentralInputStore>();
1187        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1188
1189        println!(
1190            "Initialized button data: {:?}",
1191            action_state.button_data(&Action::Run)
1192        );
1193
1194        assert!(!action_state.pressed(&Action::Run));
1195        assert!(!action_state.just_pressed(&Action::Run));
1196        assert!(action_state.released(&Action::Run));
1197        assert!(!action_state.just_released(&Action::Run));
1198
1199        // Pressing
1200        KeyCode::KeyR.press(app.world_mut());
1201        // Process the input events into Input<KeyCode> data
1202        app.update();
1203        let input_store = app.world().resource::<CentralInputStore>();
1204
1205        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1206
1207        assert!(action_state.pressed(&Action::Run));
1208        assert!(action_state.just_pressed(&Action::Run));
1209        assert!(!action_state.released(&Action::Run));
1210        assert!(!action_state.just_released(&Action::Run));
1211
1212        // Waiting
1213        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1214        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1215
1216        assert!(action_state.pressed(&Action::Run));
1217        assert!(!action_state.just_pressed(&Action::Run));
1218        assert!(!action_state.released(&Action::Run));
1219        assert!(!action_state.just_released(&Action::Run));
1220
1221        // Releasing
1222        KeyCode::KeyR.release(app.world_mut());
1223        app.update();
1224        let input_store = app.world().resource::<CentralInputStore>();
1225
1226        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1227
1228        assert!(!action_state.pressed(&Action::Run));
1229        assert!(!action_state.just_pressed(&Action::Run));
1230        assert!(action_state.released(&Action::Run));
1231        assert!(action_state.just_released(&Action::Run));
1232
1233        // Waiting
1234        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1235        action_state.update(input_map.process_actions(None, input_store, ClashStrategy::PressAll));
1236
1237        assert!(!action_state.pressed(&Action::Run));
1238        assert!(!action_state.just_pressed(&Action::Run));
1239        assert!(action_state.released(&Action::Run));
1240        assert!(!action_state.just_released(&Action::Run));
1241    }
1242
1243    #[test]
1244    fn synthetic_press() {
1245        #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
1246        enum Action {
1247            One,
1248            Two,
1249        }
1250
1251        let mut action_state = ActionState::<Action>::default();
1252        action_state.press(&Action::One);
1253        dbg!(&action_state);
1254
1255        assert!(action_state.pressed(&Action::One));
1256        assert!(action_state.just_pressed(&Action::One));
1257        assert!(!action_state.released(&Action::One));
1258        assert!(!action_state.just_released(&Action::One));
1259
1260        assert!(!action_state.pressed(&Action::Two));
1261        assert!(!action_state.just_pressed(&Action::Two));
1262        assert!(action_state.released(&Action::Two));
1263        assert!(!action_state.just_released(&Action::Two));
1264    }
1265
1266    #[cfg(feature = "keyboard")]
1267    #[test]
1268    #[ignore = "Clashing inputs for non-buttonlike inputs is broken."]
1269    fn update_with_clashes_prioritizing_longest() {
1270        use std::time::{Duration, Instant};
1271
1272        use crate::input_map::InputMap;
1273        use crate::plugin::CentralInputStorePlugin;
1274        use crate::prelude::updating::CentralInputStore;
1275        use crate::prelude::ClashStrategy;
1276        use crate::user_input::chord::ButtonlikeChord;
1277        use crate::user_input::Buttonlike;
1278        use bevy::input::InputPlugin;
1279        use bevy::prelude::KeyCode::*;
1280        use bevy::prelude::*;
1281
1282        #[derive(Actionlike, Clone, Copy, PartialEq, Eq, Hash, Debug, Reflect)]
1283        enum Action {
1284            One,
1285            Two,
1286            OneAndTwo,
1287        }
1288
1289        // Input map
1290        let mut input_map = InputMap::default();
1291        input_map.insert(Action::One, Digit1);
1292        input_map.insert(Action::Two, Digit2);
1293        input_map.insert(Action::OneAndTwo, ButtonlikeChord::new([Digit1, Digit2]));
1294
1295        let mut app = App::new();
1296        app.add_plugins(InputPlugin)
1297            .add_plugins(CentralInputStorePlugin);
1298
1299        // Action state
1300        let mut action_state = ActionState::<Action>::default();
1301
1302        // Starting state
1303        let input_store = app.world().resource::<CentralInputStore>();
1304        action_state.update(input_map.process_actions(
1305            None,
1306            input_store,
1307            ClashStrategy::PrioritizeLongest,
1308        ));
1309        assert!(action_state.released(&Action::One));
1310        assert!(action_state.released(&Action::Two));
1311        assert!(action_state.released(&Action::OneAndTwo));
1312
1313        // Pressing One
1314        Digit1.press(app.world_mut());
1315        app.update();
1316        let input_store = app.world().resource::<CentralInputStore>();
1317
1318        action_state.update(input_map.process_actions(
1319            None,
1320            input_store,
1321            ClashStrategy::PrioritizeLongest,
1322        ));
1323
1324        assert!(action_state.pressed(&Action::One));
1325        assert!(action_state.released(&Action::Two));
1326        assert!(action_state.released(&Action::OneAndTwo));
1327
1328        // Waiting
1329        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1330        action_state.update(input_map.process_actions(
1331            None,
1332            input_store,
1333            ClashStrategy::PrioritizeLongest,
1334        ));
1335
1336        assert!(action_state.pressed(&Action::One));
1337        assert!(action_state.released(&Action::Two));
1338        assert!(action_state.released(&Action::OneAndTwo));
1339
1340        // Pressing Two
1341        Digit2.press(app.world_mut());
1342        app.update();
1343        let input_store = app.world().resource::<CentralInputStore>();
1344
1345        action_state.update(input_map.process_actions(
1346            None,
1347            input_store,
1348            ClashStrategy::PrioritizeLongest,
1349        ));
1350
1351        // Now only the longest OneAndTwo has been pressed,
1352        // while both One and Two have been released
1353        assert!(action_state.released(&Action::One));
1354        assert!(action_state.released(&Action::Two));
1355        assert!(action_state.pressed(&Action::OneAndTwo));
1356
1357        // Waiting
1358        action_state.tick(Instant::now(), Instant::now() - Duration::from_micros(1));
1359        action_state.update(input_map.process_actions(
1360            None,
1361            input_store,
1362            ClashStrategy::PrioritizeLongest,
1363        ));
1364
1365        assert!(action_state.released(&Action::One));
1366        assert!(action_state.released(&Action::Two));
1367        assert!(action_state.pressed(&Action::OneAndTwo));
1368    }
1369}