leafwing_input_manager/user_input/
testing_utils.rs

1//! Utilities for testing user input.
2
3use bevy::{
4    app::App,
5    ecs::system::SystemState,
6    math::Vec2,
7    prelude::{Entity, Gamepad, Query, With, World},
8};
9
10use super::{updating::CentralInputStore, Axislike, Buttonlike, DualAxislike};
11
12#[cfg(feature = "gamepad")]
13use crate::user_input::gamepad::find_gamepad;
14
15#[cfg(not(feature = "gamepad"))]
16fn find_gamepad(_: Option<Query<Entity, With<Gamepad>>>) -> Entity {
17    Entity::PLACEHOLDER
18}
19
20/// A trait used to quickly fetch the value of a given [`UserInput`](crate::user_input::UserInput).
21///
22/// This can be useful for testing purposes.
23pub trait FetchUserInput {
24    /// Returns `true` if the given [`Buttonlike`] input is currently pressed.
25    fn read_pressed(&mut self, input: impl Buttonlike) -> bool;
26
27    /// Returns the value of the given [`Buttonlike`] input.
28    fn read_button_value(&mut self, input: impl Buttonlike) -> f32;
29
30    /// Returns the value of the given [`Axislike`] input.
31    fn read_axis_value(&mut self, input: impl Axislike) -> f32;
32
33    /// Returns the value of the given [`DualAxislike`] input.
34    fn read_dual_axis_values(&mut self, input: impl DualAxislike) -> Vec2;
35}
36
37impl FetchUserInput for World {
38    fn read_pressed(&mut self, input: impl Buttonlike) -> bool {
39        let mut query_state = SystemState::<Query<Entity, With<Gamepad>>>::new(self);
40        let query = query_state.get(self);
41        let gamepad = find_gamepad(Some(query));
42        let input_store = self.resource::<CentralInputStore>();
43
44        input.pressed(input_store, gamepad)
45    }
46
47    fn read_button_value(&mut self, input: impl Buttonlike) -> f32 {
48        let mut query_state = SystemState::<Query<Entity, With<Gamepad>>>::new(self);
49        let query = query_state.get(self);
50        let gamepad = find_gamepad(Some(query));
51        let input_store = self.resource::<CentralInputStore>();
52
53        input.value(input_store, gamepad)
54    }
55
56    fn read_axis_value(&mut self, input: impl Axislike) -> f32 {
57        let mut query_state = SystemState::<Query<Entity, With<Gamepad>>>::new(self);
58        let query = query_state.get(self);
59        let gamepad = find_gamepad(Some(query));
60        let input_store = self.resource::<CentralInputStore>();
61
62        input.value(input_store, gamepad)
63    }
64
65    fn read_dual_axis_values(&mut self, input: impl DualAxislike) -> Vec2 {
66        let mut query_state = SystemState::<Query<Entity, With<Gamepad>>>::new(self);
67        let query = query_state.get(self);
68        let gamepad = find_gamepad(Some(query));
69        let input_store = self.resource::<CentralInputStore>();
70
71        input.axis_pair(input_store, gamepad)
72    }
73}
74
75impl FetchUserInput for App {
76    fn read_pressed(&mut self, input: impl Buttonlike) -> bool {
77        self.world_mut().read_pressed(input)
78    }
79
80    fn read_button_value(&mut self, input: impl Buttonlike) -> f32 {
81        self.world_mut().read_button_value(input)
82    }
83
84    fn read_axis_value(&mut self, input: impl Axislike) -> f32 {
85        self.world_mut().read_axis_value(input)
86    }
87
88    fn read_dual_axis_values(&mut self, input: impl DualAxislike) -> Vec2 {
89        self.world_mut().read_dual_axis_values(input)
90    }
91}