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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*!
Preset bindings for common input binding patterns.
Consider a common pattern of moving a character using keyboard keys and a gamepad stick.
With the help of [modifiers](crate::modifier) you can achieve this as follows:
```
use bevy::prelude::*;
use bevy_enhanced_input::prelude::*;
#[derive(Component)]
struct Player;
#[derive(InputAction)]
#[action_output(Vec2)]
struct Movement;
let mut world = World::new();
world.spawn((
Player,
actions!(Player[
(
Action::<Movement>::new(),
// Modifier components at the action level.
DeadZone::default(), // Applies non-uniform normalization.
SmoothNudge::default(), // Smoothes movement.
bindings![
// Keyboard keys captured as `bool`, but the output of `Movement` is defined as `Vec2`,
// so you need to assign keys to axes using swizzle to reorder them and negation.
(KeyCode::KeyW, SwizzleAxis::YXZ),
(KeyCode::KeyA, Negate::all()),
(KeyCode::KeyS, Negate::all(), SwizzleAxis::YXZ),
KeyCode::KeyD,
// In Bevy sticks split by axes and captured as 1-dimensional inputs,
// so Y stick needs to be sweezled into Y axis.
GamepadAxis::LeftStickX,
(GamepadAxis::LeftStickY, SwizzleAxis::YXZ),
]
),
]),
));
```
However, this is quite onerous! It would be inconvenient to bind WASD keys and analog sticks manually, like in the example above,
every time. You can use [`Cardinal`](crate::Cardinal) and [`Axial`](crate::Axial) presets to simplify the example above.
```
use bevy::prelude::*;
use bevy_enhanced_input::prelude::*;
let mut world = World::new();
#[derive(Component)]
struct Player;
#[derive(InputAction)]
#[action_output(Vec2)]
struct Movement;
world.spawn((
Player,
actions!(Player[
(
Action::<Movement>::new(),
DeadZone::default(),
SmoothNudge::default(),
Bindings::spawn((
Cardinal::wasd_keys(),
Axial::left_stick(),
)),
),
]),
));
```
# Implementation details
Each of the preset types defined in this module generates a list of binding entities with the appropriate components
attached to them.
To achieve this, each preset type implements the [`SpawnableList`](bevy::ecs::spawn::SpawnableList) trait.
Similar to other [`SpawnableList`](bevy::ecs::spawn::SpawnableList)s in Bevy, like [`SpawnWith`](bevy::ecs::spawn::SpawnWith)
or [`SpawnIter`](bevy::ecs::spawn::SpawnIter), you need to call [`Bindings::spawn`](bevy::prelude::SpawnRelated)
from the [`SpawnRelated`](bevy::prelude::SpawnRelated) trait to generate the binding entities.
You cannot use the [`bindings!`](crate::prelude::bindings) macro.
# Examples
Adding additional bindings:
```
# use bevy::prelude::*;
# use bevy_enhanced_input::prelude::*;
Bindings::spawn((
Cardinal::wasd_keys(),
Axial::left_stick(),
// Additional bindings needs to use `Binding::from` wrapped
// into `Spawn`, which is what `bindings!` macro does.
Spawn((Binding::from(KeyCode::ArrowUp), SwizzleAxis::YXZ))
));
```
Initializing fields:
```
# use bevy::prelude::*;
# use bevy_enhanced_input::prelude::*;
Bindings::spawn((
Bidirectional {
// Struct fields are bundles, so you can also attach modifiers to individual fields.
positive: (Binding::from(KeyCode::NumpadAdd), Scale::splat(2.0)),
negative: Binding::from(KeyCode::NumpadSubtract),
},
Axial::left_stick().with((Scale::splat(1.0), SmoothNudge::default())), // Attach components to each field.
));
```
Loading from settings:
```
# use bevy::prelude::*;
# use bevy_enhanced_input::prelude::*;
// Could be loaded from a file.
// `Binding::None` represents unbound inputs.
let settings = InputSettings {
forward: [Binding::from(KeyCode::KeyW), Binding::None],
right: [Binding::from(KeyCode::KeyA), Binding::None],
backward: [Binding::from(KeyCode::KeyS), Binding::None],
left: [Binding::from(KeyCode::KeyD), Binding::None],
};
Bindings::spawn((
Cardinal {
north: settings.forward[0],
east: settings.right[0],
south: settings.backward[0],
west: settings.left[0],
},
Cardinal {
north: settings.forward[1],
east: settings.right[1],
south: settings.backward[1],
west: settings.left[1],
},
));
/// Bindings for actions.
///
/// Represented as arrays because in games you usually
/// have 2 or 3 bindings for a single action.
///
/// Usually stored as a resource.
#[derive(Resource)]
struct InputSettings {
forward: [Binding; 2],
right: [Binding; 2],
backward: [Binding; 2],
left: [Binding; 2],
}
```
*/
/// Helper trait for attaching a bundle to a preset.
///
/// See the module documentation for a usage example.