leafwing_input_manager/action_state/
mod.rs

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