Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Add Gamepads resource #3257

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion crates/bevy_input/src/gamepad.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
use crate::{Axis, Input};
use bevy_app::{EventReader, EventWriter};
use bevy_ecs::system::{Res, ResMut};
use bevy_utils::HashMap;
use bevy_utils::{tracing::info, HashMap, HashSet};

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct Gamepad(pub usize);

#[derive(Default)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
/// Container of unique connected [Gamepad]s
///
/// [Gamepad]s are registered and deregistered in [gamepad_connection_system]
pub struct GamepadLobby {
CrazyRoka marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that GamepadLobby isn't the best name for this. Lets use the more descriptive ActiveGamepads unless someone can think of something better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe just Gamepads

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I like Gamepads more because it is terser

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to Gamepads

pub gamepads: HashSet<Gamepad>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an implementation detail that we shouldn't expose directly to users (who could accidentally remove "active" gamepad and break guarantees that this list contains "active" gamepads). Instead, lets make this private and implement a method like GamepadLobby::contains(index: usize)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh actually we should probably accept the Gamepad type for consistency with other apis, but I think we should consider making the index private to encourage people to treat Gamepad as an opaque type that must be queried for. And if we don't want that behavior (and want user-specified ids to be a part of our api), then we should consider removing the Gamepad wrapper type.

Also, lets add GamepadLobby::iter() so users can iterate active gamepads.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Made this field private
  • Added contains(gamepad: Gamepad) method
  • Added iter() method
  • Replaced usages with these methods
  • Added register and deregister private methods

}
CrazyRoka marked this conversation as resolved.
Show resolved Hide resolved

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub enum GamepadEventType {
Expand Down Expand Up @@ -201,6 +210,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 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);
}
_ => (),
}
}
}

pub fn gamepad_event_system(
mut button_input: ResMut<Input<GamepadButton>>,
mut axis: ResMut<Axis<GamepadAxis>>,
Expand Down
12 changes: 9 additions & 3 deletions crates/bevy_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub mod prelude {
pub use crate::{
gamepad::{
Gamepad, GamepadAxis, GamepadAxisType, GamepadButton, GamepadButtonType, GamepadEvent,
GamepadEventType,
GamepadEventType, GamepadLobby,
},
keyboard::KeyCode,
mouse::MouseButton,
Expand All @@ -27,11 +27,12 @@ pub mod prelude {
use bevy_app::prelude::*;
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel};
use prelude::GamepadLobby;
use touch::{touch_screen_input_system, TouchInput, Touches};

use gamepad::{
gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadEventRaw,
GamepadSettings,
gamepad_connection_system, gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent,
GamepadEventRaw, GamepadSettings,
};

/// Adds keyboard and mouse input to an App
Expand Down Expand Up @@ -72,6 +73,11 @@ impl Plugin for InputPlugin {
gamepad_event_system.label(InputSystem),
)
// touch
.init_resource::<GamepadLobby>()
.add_system_to_stage(
CoreStage::PreUpdate,
gamepad_connection_system.label(InputSystem),
)
CrazyRoka marked this conversation as resolved.
Show resolved Hide resolved
.add_event::<TouchInput>()
.init_resource::<Touches>()
.add_system_to_stage(
Expand Down
32 changes: 1 addition & 31 deletions examples/input/gamepad_input.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,12 @@
use bevy::{
input::gamepad::{Gamepad, GamepadButton, GamepadEvent, GamepadEventType},
prelude::*,
utils::HashSet,
};
use bevy::{input::gamepad::GamepadButton, prelude::*};

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<GamepadLobby>()
.add_system_to_stage(CoreStage::PreUpdate, connection_system)
.add_system(gamepad_system)
.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(
lobby: Res<GamepadLobby>,
button_inputs: Res<Input<GamepadButton>>,
Expand Down