winit_input_map/
lib.rs

1#![cfg_attr(test, feature(test))]
2//! Define actions and their list of input binds. and then see if its `pressing`, `pressed` or
3//! `released`. This library handles variable pressure through the `value` function as well as
4//! multiple variable pressure inputs for things like 1d axis (through `axis`) and 2d vectors 
5//! (through `dir` and `dir_max_len_1`). This makes it easy to have things like 3d camera controls
6//! applied for both mouse movement and the gamepads right stick.
7//!
8//! The binds are structured by a list of `(Action, bind, bind, ..)`. An action is pressed if any
9//! of its binds are pressed. Binds are described as either `[InputCode, InputCode, ..]` or
10//! InputCode. A bind is pressed if all its InputCodes are pressed.
11//!
12//! The input map also can get the `mouse_pos`, what was `recently_pressed` (used for rebinding
13//! things) and the `text_typed` (useful for typing) to make sure it is fully featured.
14//! For better user control there are the `mouse_scale` and `scroll_scale` variables to make
15//! sensitivity align with eveything else 0-1 range and a `press_sensitivity` to control when an
16//! action counts as being pressed. Finaly, theres an `input_map!` macro to reduce boilerplate and
17//! increase readability.
18//! ```no_run
19//! use winit::{
20//!     window::*, application::*, keyboard::*,
21//!     event_loop::*, event::*
22//! };
23//! use gilrs::Gilrs;
24//! use winit_input_map::*;
25//!
26//! #[derive(Hash, PartialEq, Eq, Clone, Copy)]
27//! enum Actions{ Foo }
28//! use Actions::*;
29//!
30//! let input = { use base_input_codes::*; input_map!(
31//!     (Foo, KeyCode::Space, [GamepadInput::South, RightTrigger])
32//! ) };
33//! let ev = EventLoop::new().unwrap();
34//! let gilrs = Gilrs::new().unwrap();
35//! ev.run_app(&mut App { window: None, input, gilrs }).unwrap();
36//!
37//! struct App {
38//!     window: Option<Window>,
39//!     input: InputMap<Actions>,
40//!     gilrs: Gilrs
41//! }
42//! impl ApplicationHandler for App {
43//!     fn resumed(&mut self, event_loop: &ActiveEventLoop) {
44//!         let window_settings = Window::default_attributes();
45//!         let window = event_loop.create_window(window_settings);
46//!         self.window = Some(window.unwrap());
47//!     }
48//!     fn window_event(
49//!         &mut self, event_loop: &ActiveEventLoop, _: WindowId,
50//!         event: WindowEvent
51//!     ) {
52//!         self.input.update_with_window_event(&event);
53//!         if let WindowEvent::CloseRequested = &event
54//!         { event_loop.exit() }
55//!     }
56//!     fn device_event(
57//!         &mut self, _: &ActiveEventLoop, id: DeviceId,
58//!         event: DeviceEvent
59//!     ) {
60//!         self.input.update_with_device_event(id, &event);
61//!     }
62//!     fn about_to_wait(&mut self, _: &ActiveEventLoop) {
63//!         self.input.update_with_gilrs(&mut self.gilrs);
64//!         
65//!         // your code here!
66//!         if self.input.pressed(Foo) { println!("bar") }
67//!
68//!         self.input.init();
69//!     }
70//! }
71//! ```
72mod input;
73mod input_code;
74pub use crate::input::*;
75pub use crate::input_code::*;
76
77/// Outputs an input with the inputed binds.
78///
79/// The input is structured by a list of `(Action, bind, bind, ..)`. An action is pressed if any of
80/// its binds are pressed.
81///
82/// Binds are described as either `[InputCode, InputCode, ..]` or InputCode. A bind is pressed if all
83/// its InputCodes are pressed.
84/// ```
85/// use winit_input_map::*;
86/// use Action::*;
87/// #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
88/// enum Action {
89///     Select, Undo, Redo, Confirm
90/// }
91/// let input = { use base_input_codes::*; input_map!(
92///     (Select, MouseButton::Left, ShiftLeft, ShiftRight),
93///     (Action::Undo,  [KeyZ, ControlLeft], [KeyZ, ControlRight]),
94///     (Redo,  [KeyR, ControlLeft], [KeyR, ControlRight]),
95///     (Confirm, MouseButton::Left, Enter)
96/// ) };
97/// ```
98#[macro_export]
99macro_rules! input_map {
100    () => { $crate::InputMap::empty() };
101    ( $( $t: tt )* ) => {
102        $crate::InputMap::new(
103            &$crate::binds!($($t)*)
104        )
105    };
106}
107/// Outputs binds in the expected format for `add_binds`, `set_binds` and `InputMap::new` though in
108/// the latter case `input_map!` should be used to skip the middle man.
109///
110/// The input is structured by a list of `(Action, bind, bind, ..)`. An action is pressed if any of
111/// its binds are pressed.
112///
113/// Binds are described as either `[InputCode, InputCode, ..]` or InputCode. A bind is pressed if all
114/// its InputCodes are pressed.
115/// ```
116/// use winit_input_map::*;
117/// use Action::*;
118/// #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
119/// enum Action {
120///     Select, Undo, Redo, Confirm
121/// }
122/// let mut input = input_map!((Select, base_input_codes::ShiftLeft));
123///
124/// let binds = { use base_input_codes::*; binds!(
125///     (Select, MouseButton::Left, ShiftRight),
126///     (Action::Undo,  [KeyZ, ControlLeft], [KeyZ, ControlRight], KeyCode::Undo),
127///     (Redo,  [KeyR, ControlLeft], [KeyR, ControlRight]),
128///     (Confirm, MouseButton::Left, Enter)
129/// ) };
130///
131/// input.add_binds(&binds);
132/// ```
133#[macro_export]
134macro_rules! binds {
135    ( $( ( $x: expr, $( $tail: tt )* ) ),* ) => { {
136        vec![ $(
137                ($x, $crate::binds_muncher!(vec![]; $( $tail )*))
138        ),* ]
139    } };
140}
141
142#[test]
143fn bind_muncher() {
144    use base_input_codes::*;
145    assert_eq!(
146        vec![vec![InputCode::from(KeyZ)], vec![MouseButton::Left.into(), ShiftLeft.into()], vec![KeyZ.into(), KeyI.into(), KeyF.into()]],
147        *binds_muncher!(vec![]; KeyZ, [MouseButton::Left, ShiftLeft], [KeyZ, KeyI, KeyF])
148    );
149}
150#[macro_export]
151macro_rules! binds_muncher {
152    ( @vec $v: expr; ) => { $v };
153    ( $v: expr; [ $( $x: expr ),* ] ) => { {
154        let mut v: Vec<Vec<InputCode>> = $v;
155        v.push(vec![$( InputCode::from($x) ),*]);
156        v
157    } };
158    ( $v: expr; $x: expr ) => { {
159        let mut v: Vec<Vec<InputCode>> = $v;
160        v.push(vec![InputCode::from($x)]);
161        v
162    } };
163    ( $v: expr; [ $( $x: expr ),* ], $( $tail: tt )* ) => { {
164        let mut v: Vec<Vec<InputCode>> = $v;
165        v.push(vec![$( InputCode::from($x) ),*]);
166        $crate::binds_muncher!(v; $($tail)*)
167    } };
168    ( $v: expr; $x: expr, $( $tail: tt )* ) => { {
169        let mut v: Vec<Vec<InputCode>> = $v;
170        v.push(vec![InputCode::from($x)]);
171        $crate::binds_muncher!(v; $($tail)*)
172    } };
173}