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