bevy/examples/input
s-puig e788e3bc83
Implement gamepads as entities (#12770)
# Objective

- Significantly improve the ergonomics of gamepads and allow new
features

Gamepads are a bit unergonomic to work with, they use resources but
unlike other inputs, they are not limited to a single gamepad, to get
around this it uses an identifier (Gamepad) to interact with anything
causing all sorts of issues.

1. There are too many: Gamepads, GamepadSettings, GamepadInfo,
ButtonInput<T>, 2 Axis<T>.
2. ButtonInput/Axis generic methods become really inconvenient to use
e.g. any_pressed()
3. GamepadButton/Axis structs are unnecessary boilerplate:

```rust
for gamepad in gamepads.iter() {
        if button_inputs.just_pressed(GamepadButton::new(gamepad, GamepadButtonType::South)) {
            info!("{:?} just pressed South", gamepad);
        } else if button_inputs.just_released(GamepadButton::new(gamepad, GamepadButtonType::South))
        {
            info!("{:?} just released South", gamepad);
        }
}
```
4. Projects often need to create resources to store the selected gamepad
and have to manually check if their gamepad is still valid anyways.

- Previously attempted by #3419 and #12674


## Solution

- Implement gamepads as entities.

Using entities solves all the problems above and opens new
possibilities.

1. Reduce boilerplate and allows iteration

```rust
let is_pressed = gamepads_buttons.iter().any(|buttons| buttons.pressed(GamepadButtonType::South))
```
2. ButtonInput/Axis generic methods become ergonomic again 
```rust
gamepad_buttons.any_just_pressed([GamepadButtonType::Start, GamepadButtonType::Select])
```
3. Reduces the number of public components significantly (Gamepad,
GamepadSettings, GamepadButtons, GamepadAxes)
4. Components are highly convenient. Gamepad optional features could now
be expressed naturally (`Option<Rumble> or Option<Gyro>`), allows devs
to attach their own components and filter them, so code like this
becomes possible:
```rust
fn move_player<const T: usize>(
    player: Query<&Transform, With<Player<T>>>,
    gamepads_buttons: Query<&GamepadButtons, With<Player<T>>>,
) {
    if let Ok(gamepad_buttons) = gamepads_buttons.get_single() {
        if gamepad_buttons.pressed(GamepadButtonType::South) {
            // move player
        }
    }
}
```
---

## Follow-up

- [ ] Run conditions?
- [ ] Rumble component

# Changelog

## Added

TODO

## Changed

TODO

## Removed

TODO


## Migration Guide

TODO

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-09-27 20:07:20 +00:00
..
char_input_events.rs Fix inconsistency in KeyboardInput examples to match migration guide (#14185) 2024-07-15 15:03:48 +00:00
gamepad_input.rs Implement gamepads as entities (#12770) 2024-09-27 20:07:20 +00:00
gamepad_input_events.rs Implement gamepads as entities (#12770) 2024-09-27 20:07:20 +00:00
gamepad_rumble.rs Implement gamepads as entities (#12770) 2024-09-27 20:07:20 +00:00
keyboard_input.rs Update winit dependency to 0.29 (#10702) 2023-12-21 07:40:47 +00:00
keyboard_input_events.rs Refactor EventReader::iter to read (#9631) 2023-08-30 14:20:03 +00:00
keyboard_modifiers.rs Update winit dependency to 0.29 (#10702) 2023-12-21 07:40:47 +00:00
mouse_grab.rs Add custom cursors (#14284) 2024-08-12 15:49:03 +00:00
mouse_input.rs Mouse input accumulation (#14044) 2024-07-01 14:27:21 +00:00
mouse_input_events.rs rename touchpad to gesture, and add new gestures (#13660) 2024-06-04 12:44:25 +00:00
text_input.rs Cosmetic improvements for text_input example (#15016) 2024-09-02 22:49:12 +00:00
touch_input.rs Non-breaking change* from UK spellings to US (#8291) 2023-04-08 16:22:46 +00:00
touch_input_events.rs Refactor EventReader::iter to read (#9631) 2023-08-30 14:20:03 +00:00