1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! input-actions is a Rust crate heavily inspired by Unity library [Rewired](https://assetstore.unity.com/packages/tools/utilities/rewired-21676) ([Website](https://guavaman.com/projects/rewired/)).
//!
//! This crate utilizes "gilrs" (which uses "rusty-xinput") to handle gamepad input,
//! and both of these crates expose potentially spammy levels of logging when devices are connected.
//! It is recommended you ignore or limit the logging levels of "gilrs" and "rusty_xinput" log targets/modules.
//! This is being tracked by https://gitlab.com/gilrs-project/gilrs/-/issues/105.
//!
//! # Setup
//! input-actions uses a "set it and forget it" approach to system management.
//! As long as the system stays active for the lifecycle of the application,
//! and its [`update`](System::update) is called at regular intervals,
//! the rest is pretty hands-off.
//! 
//! ```rust
//! let mut input_sys = System::new();
//! input_sys
//! 	// There is only 1 player/user to send inputs for.
//! 	.add_users(1)
//! 	// These action names are complete up to you.
//! 	// It is recommended that you store the strings as static properties
//! 	// so they can be referenced throughout the consuming crate.
//! 	.add_action("button1", Action::new(Kind::Button))
//! 	.add_action("button2", Action::new(Kind::Button))
//! 	.add_action("axis1", Action::new(Kind::Axis))
//! 	.add_action("axis2", Action::new(Kind::Axis))
//! 	// This specifies that there is 1 layout (the default layout, which is equivalent to `None`).
//! 	.add_layout(LayoutId::default())
//! 	// This adds bindings for each action for a given layout.
//! 	// The group of bindings per layout is called an "action set".
//! 	.add_action_set(
//! 		// This specifies the name of the set. `ActionSetId::default()` is equivalent to `None`.
//! 		ActionSetId::default(),
//! 		ActionSet::default().with(
//! 			// This action set contains 1 layout, the default layout added to the system above.
//! 			LayoutId::default(),
//! 			ActionMap::default()
//! 				.bind(
//! 					"button1",
//! 					vec![
//! 						binding::Source::Keyboard(source::Key::Return).bound(),
//! 						binding::Source::Keyboard(source::Key::NumpadEnter).bound(),
//! 						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
//! 							binding::Source::Button(source::Button::VirtualConfirm
//! 						)).bound(),
//! 					],
//! 				)
//! 				.bind(
//! 					"button2",
//! 					vec![
//! 						binding::Source::Keyboard(source::Key::Escape).bound(),
//! 						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
//! 							binding::Source::Button(source::Button::VirtualDeny)
//! 						).bound(),
//! 					],
//! 				)
//! 				.bind(
//! 					"axis1",
//! 					vec![
//! 						binding::Source::Keyboard(source::Key::W).with_modifier(1.0),
//! 						binding::Source::Keyboard(source::Key::S).with_modifier(-1.0),
//! 						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
//! 							binding::Source::Axis(source::Axis::LThumbstickX)
//! 						).bound(),
//! 					],
//! 				)
//! 				.bind(
//! 					"axis2",
//! 					vec![
//! 						binding::Source::Keyboard(source::Key::A).with_modifier(-1.0),
//! 						binding::Source::Keyboard(source::Key::D).with_modifier(1.0),
//! 						binding::Source::Gamepad(GamepadKind::DualAxisGamepad,
//! 							binding::Source::Axis(source::Axis::LThumbstickY)
//! 						).bound(),
//! 					],
//! 				)
//! 		),
//! 	)
//! 	// In order to use action set bindings, the user needs the action set enabled.
//! 	// This call says "all users should have this action set enabled",
//! 	// though it is equivalent to `mark_action_set_enabled` since there is only 1 user in this example.
//! 	.enable_action_set_for_all(ActionSetId::default());
//! ```
//! 
//! From there it is up to you to determine when and how to send the system updates
//! so it knows what actions are in what state.
//! 
//! You should call [`System::update`](System::update) during your update loop
//! (which will update the state of all actions for all users). This is primarily for
//! gamepad input polling and updating actions that need simulation.
//! 
//! The input-actions system also needs to know about mouse and keyboard input,
//! which can be supplied by any external source. If you are using [winit](https://crates.io/crates/winit),
//! you can enable the `winit` feature,
//! `input-actions = { version = "...", features = ["winit"] }`
//! and use the code below to sent window-based gameplay events:
//! ```rust
//! event_loop.run(move |event, _, _| {
//! 	if let Ok((source, input_event)) = input::winit::parse_winit_event(&event) {
//! 		input_sys.send_event(source, input_event);
//! 	}
//! }
//! ```
//! 
//! The input-actions system also supports logging via the `log` feature:
//! `input-actions = { version = "...", features = ["log"] }`
//! 

#[cfg(feature = "log")]
extern crate log;

/// Submodule for handling integration with `winit` when the feature is enabled.
#[cfg(feature = "winit")]
pub mod winit;

pub static LOG: &'static str = "input-actions";
pub static DEPENDENCY_LOG_TARGETS: [&'static str; 2] = ["gilrs", "rusty_xinput"];

/// Configuration and state data for handling an action set by consuemrs of input-actions.
pub mod action;

/// Data for telling input-actions how a device input is mapped to an action.
pub mod binding;

/// Data pertaining to physical devices (like mice, keyboards, and gamepads) which send input to input-actions.
pub mod device;

/// Enumerations for differentiating between device inputs (buttons, axes, keys, mouse buttons).
pub mod source;

/// Data sent to input-actions when device inputs are detected.
pub mod event;

mod system;
pub use system::*;

mod user;
pub(crate) use user::*;