Skip to content

Commit

Permalink
Separate gamepad state code from gamepad event code and other customi…
Browse files Browse the repository at this point in the history
…zations (#700)

Separated gamepad event and gamepad state code and made gamepad input more customizable
  • Loading branch information
simpuid authored Oct 21, 2020
1 parent 0f43fb0 commit d01ba9e
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 230 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ path = "examples/input/keyboard_input_events.rs"
name = "gamepad_input"
path = "examples/input/gamepad_input.rs"

[[example]]
name = "gamepad_input_event"
path = "examples/input/gamepad_input_event.rs"

[[example]]
name = "touch_input"
path = "examples/input/touch_input.rs"
Expand Down
171 changes: 25 additions & 146 deletions crates/bevy_gilrs/src/gilrs_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,177 +2,56 @@ use crate::converter::{convert_axis, convert_button, convert_gamepad_id};
use bevy_app::Events;
use bevy_ecs::{Resources, World};
use bevy_input::prelude::*;
use gilrs::{Button, EventType, Gilrs};
use gilrs::{EventType, Gilrs};

pub fn gilrs_startup_system(_world: &mut World, resources: &mut Resources) {
pub fn gilrs_event_startup_system(_world: &mut World, resources: &mut Resources) {
let gilrs = resources.get_thread_local::<Gilrs>().unwrap();
let mut gamepad_event = resources.get_mut::<Events<GamepadEvent>>().unwrap();
let mut inputs = resources.get_mut::<Input<GamepadButton>>().unwrap();
let mut axes = resources.get_mut::<Axis<GamepadAxis>>().unwrap();
let mut button_axes = resources.get_mut::<Axis<GamepadButton>>().unwrap();
gamepad_event.update();
inputs.update();
for (gilrs_id, gilrs_gamepad) in gilrs.gamepads() {
connect_gamepad(
gilrs_gamepad,
convert_gamepad_id(gilrs_id),
&mut gamepad_event,
&mut inputs,
&mut axes,
&mut button_axes,
);
let mut event = resources.get_mut::<Events<GamepadEvent>>().unwrap();
event.update();
for (id, _) in gilrs.gamepads() {
event.send(GamepadEvent(
convert_gamepad_id(id),
GamepadEventType::Connected,
));
}
}

pub fn gilrs_update_system(_world: &mut World, resources: &mut Resources) {
pub fn girls_event_system(_world: &mut World, resources: &mut Resources) {
let mut gilrs = resources.get_thread_local_mut::<Gilrs>().unwrap();
let mut gamepad_event = resources.get_mut::<Events<GamepadEvent>>().unwrap();
let mut inputs = resources.get_mut::<Input<GamepadButton>>().unwrap();
let mut axes = resources.get_mut::<Axis<GamepadAxis>>().unwrap();
let mut button_axes = resources.get_mut::<Axis<GamepadButton>>().unwrap();

gamepad_event.update();
inputs.update();
let mut event = resources.get_mut::<Events<GamepadEvent>>().unwrap();
event.update();
while let Some(gilrs_event) = gilrs.next_event() {
match gilrs_event.event {
EventType::Connected => {
connect_gamepad(
gilrs.gamepad(gilrs_event.id),
event.send(GamepadEvent(
convert_gamepad_id(gilrs_event.id),
&mut gamepad_event,
&mut inputs,
&mut axes,
&mut button_axes,
);
GamepadEventType::Connected,
));
}
EventType::Disconnected => {
disconnect_gamepad(
event.send(GamepadEvent(
convert_gamepad_id(gilrs_event.id),
&mut gamepad_event,
&mut inputs,
&mut axes,
&mut button_axes,
);
GamepadEventType::Disconnected,
));
}
EventType::ButtonPressed(gilrs_button, _) => {
if let Some(button_type) = convert_button(gilrs_button) {
inputs.press(GamepadButton(
convert_gamepad_id(gilrs_event.id),
button_type,
));
}
}
EventType::ButtonReleased(gilrs_button, _) => {
EventType::ButtonChanged(gilrs_button, value, _) => {
if let Some(button_type) = convert_button(gilrs_button) {
inputs.release(GamepadButton(
event.send(GamepadEvent(
convert_gamepad_id(gilrs_event.id),
button_type,
GamepadEventType::ButtonChanged(button_type, value),
));
}
}
EventType::ButtonChanged(gilrs_button, value, _) => {
if let Some(button_type) = convert_button(gilrs_button) {
button_axes.set(
GamepadButton(convert_gamepad_id(gilrs_event.id), button_type),
value,
);
}
}
EventType::AxisChanged(gilrs_axis, value, _) => {
if let Some(axis_type) = convert_axis(gilrs_axis) {
axes.set(
GamepadAxis(convert_gamepad_id(gilrs_event.id), axis_type),
value,
);
event.send(GamepadEvent(
convert_gamepad_id(gilrs_event.id),
GamepadEventType::AxisChanged(axis_type, value),
));
}
}
_ => (),
};
}
gilrs.inc();
}

const ALL_GILRS_BUTTONS: [Button; 19] = [
Button::South,
Button::East,
Button::North,
Button::West,
Button::C,
Button::Z,
Button::LeftTrigger,
Button::LeftTrigger2,
Button::RightTrigger,
Button::RightTrigger2,
Button::Select,
Button::Start,
Button::Mode,
Button::LeftThumb,
Button::RightThumb,
Button::DPadUp,
Button::DPadDown,
Button::DPadLeft,
Button::DPadRight,
];

const ALL_GILRS_AXES: [gilrs::Axis; 8] = [
gilrs::Axis::LeftStickX,
gilrs::Axis::LeftStickY,
gilrs::Axis::LeftZ,
gilrs::Axis::RightStickX,
gilrs::Axis::RightStickY,
gilrs::Axis::RightZ,
gilrs::Axis::DPadX,
gilrs::Axis::DPadY,
];

fn connect_gamepad(
gilrs_gamepad: gilrs::Gamepad,
gamepad: Gamepad,
events: &mut Events<GamepadEvent>,
inputs: &mut Input<GamepadButton>,
axes: &mut Axis<GamepadAxis>,
button_axes: &mut Axis<GamepadButton>,
) {
for gilrs_button in ALL_GILRS_BUTTONS.iter() {
if let Some(button_type) = convert_button(*gilrs_button) {
if let Some(button_data) = gilrs_gamepad.button_data(*gilrs_button) {
let gamepad_button = GamepadButton(gamepad, button_type);
inputs.reset(gamepad_button);
if button_data.is_pressed() {
inputs.press(gamepad_button);
}
button_axes.set(gamepad_button, button_data.value());
}
}
}
for gilrs_axis in ALL_GILRS_AXES.iter() {
if let Some(axis_type) = convert_axis(*gilrs_axis) {
let gamepad_axis = GamepadAxis(gamepad, axis_type);
axes.set(gamepad_axis, gilrs_gamepad.value(*gilrs_axis));
}
}
events.send(GamepadEvent(gamepad, GamepadEventType::Connected));
}

fn disconnect_gamepad(
gamepad: Gamepad,
events: &mut Events<GamepadEvent>,
inputs: &mut Input<GamepadButton>,
axes: &mut Axis<GamepadAxis>,
button_axes: &mut Axis<GamepadButton>,
) {
for gilrs_button in ALL_GILRS_BUTTONS.iter() {
if let Some(button_type) = convert_button(*gilrs_button) {
let gamepad_button = GamepadButton(gamepad, button_type);
inputs.reset(gamepad_button);
button_axes.remove(&gamepad_button);
}
}
for gilrs_axis in ALL_GILRS_AXES.iter() {
if let Some(axis_type) = convert_axis(*gilrs_axis) {
let gamepad_axis = GamepadAxis(gamepad, axis_type);
axes.remove(&gamepad_axis);
}
}
events.send(GamepadEvent(gamepad, GamepadEventType::Disconnected));
}
16 changes: 9 additions & 7 deletions crates/bevy_gilrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@ mod gilrs_system;

use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use gilrs_system::{gilrs_startup_system, gilrs_update_system};
use gilrs::GilrsBuilder;
use gilrs_system::{gilrs_event_startup_system, girls_event_system};

#[derive(Default)]
pub struct GilrsPlugin;

impl Plugin for GilrsPlugin {
fn build(&self, app: &mut AppBuilder) {
match gilrs::Gilrs::new() {
match GilrsBuilder::new()
.with_default_filters(false)
.set_update_state(false)
.build()
{
Ok(gilrs) => {
app.add_thread_local_resource(gilrs)
.add_startup_system(gilrs_startup_system.thread_local_system())
.add_system_to_stage(
stage::EVENT_UPDATE,
gilrs_update_system.thread_local_system(),
);
.add_startup_system(gilrs_event_startup_system.thread_local_system())
.add_system_to_stage(stage::FIRST, girls_event_system.thread_local_system());
}
Err(err) => log::error!("Failed to start Gilrs. {}", err),
}
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_input/src/axis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ where
self.axis_data.insert(axis, value)
}

pub fn get(&self, axis: &T) -> Option<f32> {
self.axis_data.get(axis).copied()
pub fn get(&self, axis: T) -> Option<f32> {
self.axis_data.get(&axis).copied()
}

pub fn remove(&mut self, axis: &T) -> Option<f32> {
self.axis_data.remove(axis)
pub fn remove(&mut self, axis: T) -> Option<f32> {
self.axis_data.remove(&axis)
}
}
Loading

0 comments on commit d01ba9e

Please sign in to comment.