Add Gamepads resource (#3257)
# Objective Fixes #3245 ## Solution - Move GamepadLobby to lib - Add connection_system to InputPlugin - Updated gamepad_input example Co-authored-by: CrazyRoka <rokarostuk@gmail.com> Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
ca80fe65ed
commit
01e2141ce3
@ -1,12 +1,42 @@
|
|||||||
use crate::{Axis, Input};
|
use crate::{Axis, Input};
|
||||||
use bevy_app::{EventReader, EventWriter};
|
use bevy_app::{EventReader, EventWriter};
|
||||||
use bevy_ecs::system::{Res, ResMut};
|
use bevy_ecs::system::{Res, ResMut};
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::{tracing::info, HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Gamepad(pub usize);
|
pub struct Gamepad(pub usize);
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
/// Container of unique connected [Gamepad]s
|
||||||
|
///
|
||||||
|
/// [Gamepad]s are registered and deregistered in [gamepad_connection_system]
|
||||||
|
pub struct Gamepads {
|
||||||
|
gamepads: HashSet<Gamepad>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gamepads {
|
||||||
|
/// Returns true if the [Gamepads] contains a [Gamepad].
|
||||||
|
pub fn contains(&self, gamepad: &Gamepad) -> bool {
|
||||||
|
self.gamepads.contains(gamepad)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterates over registered [Gamepad]s
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &Gamepad> + '_ {
|
||||||
|
self.gamepads.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers [Gamepad].
|
||||||
|
fn register(&mut self, gamepad: Gamepad) {
|
||||||
|
self.gamepads.insert(gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deregisters [Gamepad.
|
||||||
|
fn deregister(&mut self, gamepad: &Gamepad) {
|
||||||
|
self.gamepads.remove(gamepad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum GamepadEventType {
|
pub enum GamepadEventType {
|
||||||
@ -204,6 +234,28 @@ impl ButtonAxisSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Monitors gamepad connection and disconnection events, updating the [GamepadLobby] resource accordingly
|
||||||
|
///
|
||||||
|
/// By default, runs during `CoreStage::PreUpdate` when added via [InputPlugin].
|
||||||
|
pub fn gamepad_connection_system(
|
||||||
|
mut gamepads: ResMut<Gamepads>,
|
||||||
|
mut gamepad_event: EventReader<GamepadEvent>,
|
||||||
|
) {
|
||||||
|
for event in gamepad_event.iter() {
|
||||||
|
match &event {
|
||||||
|
GamepadEvent(gamepad, GamepadEventType::Connected) => {
|
||||||
|
gamepads.register(*gamepad);
|
||||||
|
info!("{:?} Connected", gamepad);
|
||||||
|
}
|
||||||
|
GamepadEvent(gamepad, GamepadEventType::Disconnected) => {
|
||||||
|
gamepads.deregister(gamepad);
|
||||||
|
info!("{:?} Disconnected", gamepad);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gamepad_event_system(
|
pub fn gamepad_event_system(
|
||||||
mut button_input: ResMut<Input<GamepadButton>>,
|
mut button_input: ResMut<Input<GamepadButton>>,
|
||||||
mut axis: ResMut<Axis<GamepadAxis>>,
|
mut axis: ResMut<Axis<GamepadAxis>>,
|
||||||
|
@ -15,7 +15,7 @@ pub mod prelude {
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
gamepad::{
|
gamepad::{
|
||||||
Gamepad, GamepadAxis, GamepadAxisType, GamepadButton, GamepadButtonType, GamepadEvent,
|
Gamepad, GamepadAxis, GamepadAxisType, GamepadButton, GamepadButtonType, GamepadEvent,
|
||||||
GamepadEventType,
|
GamepadEventType, Gamepads,
|
||||||
},
|
},
|
||||||
keyboard::KeyCode,
|
keyboard::KeyCode,
|
||||||
mouse::MouseButton,
|
mouse::MouseButton,
|
||||||
@ -27,11 +27,12 @@ pub mod prelude {
|
|||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
||||||
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel};
|
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel};
|
||||||
|
use prelude::Gamepads;
|
||||||
use touch::{touch_screen_input_system, TouchInput, Touches};
|
use touch::{touch_screen_input_system, TouchInput, Touches};
|
||||||
|
|
||||||
use gamepad::{
|
use gamepad::{
|
||||||
gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadEventRaw,
|
gamepad_connection_system, gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent,
|
||||||
GamepadSettings,
|
GamepadEventRaw, GamepadSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Adds keyboard and mouse input to an App
|
/// Adds keyboard and mouse input to an App
|
||||||
@ -64,6 +65,7 @@ impl Plugin for InputPlugin {
|
|||||||
.add_event::<GamepadEvent>()
|
.add_event::<GamepadEvent>()
|
||||||
.add_event::<GamepadEventRaw>()
|
.add_event::<GamepadEventRaw>()
|
||||||
.init_resource::<GamepadSettings>()
|
.init_resource::<GamepadSettings>()
|
||||||
|
.init_resource::<Gamepads>()
|
||||||
.init_resource::<Input<GamepadButton>>()
|
.init_resource::<Input<GamepadButton>>()
|
||||||
.init_resource::<Axis<GamepadAxis>>()
|
.init_resource::<Axis<GamepadAxis>>()
|
||||||
.init_resource::<Axis<GamepadButton>>()
|
.init_resource::<Axis<GamepadButton>>()
|
||||||
@ -71,6 +73,10 @@ impl Plugin for InputPlugin {
|
|||||||
CoreStage::PreUpdate,
|
CoreStage::PreUpdate,
|
||||||
gamepad_event_system.label(InputSystem),
|
gamepad_event_system.label(InputSystem),
|
||||||
)
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PreUpdate,
|
||||||
|
gamepad_connection_system.label(InputSystem),
|
||||||
|
)
|
||||||
// touch
|
// touch
|
||||||
.add_event::<TouchInput>()
|
.add_event::<TouchInput>()
|
||||||
.init_resource::<Touches>()
|
.init_resource::<Touches>()
|
||||||
|
@ -1,49 +1,19 @@
|
|||||||
use bevy::{
|
use bevy::{input::gamepad::GamepadButton, prelude::*};
|
||||||
input::gamepad::{Gamepad, GamepadButton, GamepadEvent, GamepadEventType},
|
|
||||||
prelude::*,
|
|
||||||
utils::HashSet,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
.init_resource::<GamepadLobby>()
|
|
||||||
.add_system_to_stage(CoreStage::PreUpdate, connection_system)
|
|
||||||
.add_system(gamepad_system)
|
.add_system(gamepad_system)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct GamepadLobby {
|
|
||||||
gamepads: HashSet<Gamepad>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn connection_system(
|
|
||||||
mut lobby: ResMut<GamepadLobby>,
|
|
||||||
mut gamepad_event: EventReader<GamepadEvent>,
|
|
||||||
) {
|
|
||||||
for event in gamepad_event.iter() {
|
|
||||||
match &event {
|
|
||||||
GamepadEvent(gamepad, GamepadEventType::Connected) => {
|
|
||||||
lobby.gamepads.insert(*gamepad);
|
|
||||||
info!("{:?} Connected", gamepad);
|
|
||||||
}
|
|
||||||
GamepadEvent(gamepad, GamepadEventType::Disconnected) => {
|
|
||||||
lobby.gamepads.remove(gamepad);
|
|
||||||
info!("{:?} Disconnected", gamepad);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gamepad_system(
|
fn gamepad_system(
|
||||||
lobby: Res<GamepadLobby>,
|
gamepads: Res<Gamepads>,
|
||||||
button_inputs: Res<Input<GamepadButton>>,
|
button_inputs: Res<Input<GamepadButton>>,
|
||||||
button_axes: Res<Axis<GamepadButton>>,
|
button_axes: Res<Axis<GamepadButton>>,
|
||||||
axes: Res<Axis<GamepadAxis>>,
|
axes: Res<Axis<GamepadAxis>>,
|
||||||
) {
|
) {
|
||||||
for gamepad in lobby.gamepads.iter().cloned() {
|
for gamepad in gamepads.iter().cloned() {
|
||||||
if button_inputs.just_pressed(GamepadButton(gamepad, GamepadButtonType::South)) {
|
if button_inputs.just_pressed(GamepadButton(gamepad, GamepadButtonType::South)) {
|
||||||
info!("{:?} just pressed South", gamepad);
|
info!("{:?} just pressed South", gamepad);
|
||||||
} else if button_inputs.just_released(GamepadButton(gamepad, GamepadButtonType::South)) {
|
} else if button_inputs.just_released(GamepadButton(gamepad, GamepadButtonType::South)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user