Skip to content

Commit

Permalink
Simplify gamepad_input example and refactor bevy_input::gamepad
Browse files Browse the repository at this point in the history
  • Loading branch information
simpuid committed Oct 21, 2020
1 parent 5363b09 commit 853af82
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 132 deletions.
5 changes: 1 addition & 4 deletions crates/bevy_gilrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ impl Plugin for GilrsPlugin {
{
Ok(gilrs) => {
app.add_thread_local_resource(gilrs)
.add_startup_system_to_stage(
bevy_app::startup_stage::STARTUP,
gilrs_event_startup_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
88 changes: 44 additions & 44 deletions crates/bevy_input/src/gamepad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,51 +66,51 @@ pub enum GamepadAxisType {
pub struct GamepadAxis(pub Gamepad, pub GamepadAxisType);

#[derive(Default, Debug)]
pub struct GamepadProperty {
pub default_button_property: ButtonProperty,
pub default_axis_property: AxisProperty,
pub default_button_axis_property: ButtonAxisProperty,
pub button_properties: HashMap<GamepadButton, ButtonProperty>,
pub axis_properties: HashMap<GamepadAxis, AxisProperty>,
pub button_axis_properties: HashMap<GamepadButton, ButtonAxisProperty>,
pub struct GamepadSetting {
pub default_button_setting: ButtonSetting,
pub default_axis_setting: AxisSetting,
pub default_button_axis_setting: ButtonAxisSetting,
pub button_settings: HashMap<GamepadButton, ButtonSetting>,
pub axis_settings: HashMap<GamepadAxis, AxisSetting>,
pub button_axis_settings: HashMap<GamepadButton, ButtonAxisSetting>,
}

impl GamepadProperty {
pub fn get_button_properties(&self, button: GamepadButton) -> &ButtonProperty {
self.button_properties
impl GamepadSetting {
pub fn get_button_setting(&self, button: GamepadButton) -> &ButtonSetting {
self.button_settings
.get(&button)
.unwrap_or(&self.default_button_property)
.unwrap_or(&self.default_button_setting)
}

pub fn get_axis_properties(&self, axis: GamepadAxis) -> &AxisProperty {
self.axis_properties
pub fn get_axis_setting(&self, axis: GamepadAxis) -> &AxisSetting {
self.axis_settings
.get(&axis)
.unwrap_or(&self.default_axis_property)
.unwrap_or(&self.default_axis_setting)
}

pub fn get_button_axis_properties(&self, button: GamepadButton) -> &ButtonAxisProperty {
self.button_axis_properties
pub fn get_button_axis_setting(&self, button: GamepadButton) -> &ButtonAxisSetting {
self.button_axis_settings
.get(&button)
.unwrap_or(&self.default_button_axis_property)
.unwrap_or(&self.default_button_axis_setting)
}
}

#[derive(Debug, Clone)]
pub struct ButtonProperty {
pub struct ButtonSetting {
pub press: f32,
pub release: f32,
}

impl Default for ButtonProperty {
impl Default for ButtonSetting {
fn default() -> Self {
ButtonProperty {
ButtonSetting {
press: 0.75,
release: 0.65,
}
}
}

impl ButtonProperty {
impl ButtonSetting {
fn is_pressed(&self, value: f32) -> bool {
value >= self.press
}
Expand All @@ -121,17 +121,17 @@ impl ButtonProperty {
}

#[derive(Debug, Clone)]
pub struct AxisProperty {
pub struct AxisSetting {
pub positive_high: f32,
pub positive_low: f32,
pub negative_high: f32,
pub negative_low: f32,
pub threshold: f32,
}

impl Default for AxisProperty {
impl Default for AxisSetting {
fn default() -> Self {
AxisProperty {
AxisSetting {
positive_high: 0.95,
positive_low: 0.05,
negative_high: -0.95,
Expand All @@ -141,7 +141,7 @@ impl Default for AxisProperty {
}
}

impl AxisProperty {
impl AxisSetting {
fn filter(&self, new_value: f32, old_value: Option<f32>) -> f32 {
if let Some(old_value) = old_value {
if (new_value - old_value).abs() <= self.threshold {
Expand All @@ -162,23 +162,23 @@ impl AxisProperty {
}

#[derive(Debug, Clone)]
pub struct ButtonAxisProperty {
pub struct ButtonAxisSetting {
pub high: f32,
pub low: f32,
pub threshold: f32,
}

impl Default for ButtonAxisProperty {
impl Default for ButtonAxisSetting {
fn default() -> Self {
ButtonAxisProperty {
ButtonAxisSetting {
high: 0.95,
low: 0.05,
threshold: 0.01,
}
}
}

impl ButtonAxisProperty {
impl ButtonAxisSetting {
fn filter(&self, new_value: f32, old_value: Option<f32>) -> f32 {
if let Some(old_value) = old_value {
if (new_value - old_value).abs() <= self.threshold {
Expand All @@ -202,20 +202,20 @@ pub struct GamepadEventState {

pub fn gamepad_event_system(
mut state: Local<GamepadEventState>,
mut button: ResMut<Input<GamepadButton>>,
mut button_input: ResMut<Input<GamepadButton>>,
mut axis: ResMut<Axis<GamepadAxis>>,
mut button_axis: ResMut<Axis<GamepadButton>>,
event: Res<Events<GamepadEvent>>,
properties: Res<GamepadProperty>,
events: Res<Events<GamepadEvent>>,
settings: Res<GamepadSetting>,
) {
button.update();
for event in state.gamepad_event_reader.iter(&event) {
button_input.update();
for event in state.gamepad_event_reader.iter(&events) {
let (gamepad, event) = (&event.0, &event.1);
match event {
GamepadEventType::Connected => {
for button_type in ALL_BUTTON_TYPES.iter() {
let gamepad_button = GamepadButton(*gamepad, *button_type);
button.reset(gamepad_button);
button_input.reset(gamepad_button);
button_axis.set(gamepad_button, 0.0);
}
for axis_type in ALL_AXIS_TYPES.iter() {
Expand All @@ -225,7 +225,7 @@ pub fn gamepad_event_system(
GamepadEventType::Disconnected => {
for button_type in ALL_BUTTON_TYPES.iter() {
let gamepad_button = GamepadButton(*gamepad, *button_type);
button.reset(gamepad_button);
button_input.reset(gamepad_button);
button_axis.remove(gamepad_button);
}
for axis_type in ALL_AXIS_TYPES.iter() {
Expand All @@ -234,25 +234,25 @@ pub fn gamepad_event_system(
}
GamepadEventType::AxisChanged(axis_type, value) => {
let gamepad_axis = GamepadAxis(*gamepad, *axis_type);
let value = properties
.get_axis_properties(gamepad_axis)
let value = settings
.get_axis_setting(gamepad_axis)
.filter(*value, axis.get(gamepad_axis));
axis.set(gamepad_axis, value);
}
GamepadEventType::ButtonChanged(button_type, value) => {
let gamepad_button = GamepadButton(*gamepad, *button_type);
let filtered_value = properties
.get_button_axis_properties(gamepad_button)
let filtered_value = settings
.get_button_axis_setting(gamepad_button)
.filter(*value, button_axis.get(gamepad_button));
button_axis.set(gamepad_button, filtered_value);

let button_property = properties.get_button_properties(gamepad_button);
if button.pressed(gamepad_button) {
let button_property = settings.get_button_setting(gamepad_button);
if button_input.pressed(gamepad_button) {
if button_property.is_released(*value) {
button.release(gamepad_button);
button_input.release(gamepad_button);
}
} else if button_property.is_pressed(*value) {
button.press(gamepad_button);
button_input.press(gamepad_button);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotio
use touch::{touch_screen_input_system, TouchInput, Touches};

use bevy_ecs::IntoQuerySystem;
use gamepad::{gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadProperty};
use gamepad::{gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadSetting};

/// Adds keyboard and mouse input to an App
#[derive(Default)]
Expand All @@ -50,7 +50,7 @@ impl Plugin for InputPlugin {
mouse_button_input_system.system(),
)
.add_event::<GamepadEvent>()
.init_resource::<GamepadProperty>()
.init_resource::<GamepadSetting>()
.init_resource::<Input<GamepadButton>>()
.init_resource::<Axis<GamepadAxis>>()
.init_resource::<Axis<GamepadButton>>()
Expand All @@ -59,7 +59,6 @@ impl Plugin for InputPlugin {
gamepad_event_system.system(),
)
.add_system_to_stage(bevy_app::stage::EVENT_UPDATE, gamepad_event_system.system())
.init_resource::<Axis<GamepadButton>>()
.add_event::<TouchInput>()
.init_resource::<Touches>()
.add_system_to_stage(
Expand Down
110 changes: 29 additions & 81 deletions examples/input/gamepad_input.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
use bevy::prelude::*;
use bevy_input::gamepad::{Gamepad, GamepadButton, GamepadEvent, GamepadEventType};
use bevy_utils::{HashMap, HashSet};
use bevy_utils::HashSet;

fn main() {
App::build()
.add_default_plugins()
.init_resource::<GamepadLobby>()
.init_resource::<GamepadData>()
.add_startup_system(connection_system.system())
.add_system(connection_system.system())
.add_system(button_system.system())
.add_system(axis_system.system())
.add_system(gamepad_system.system())
.run();
}

Expand All @@ -20,12 +18,6 @@ struct GamepadLobby {
gamepad_event_reader: EventReader<GamepadEvent>,
}

#[derive(Default)]
struct GamepadData {
axis: HashMap<GamepadAxis, f32>,
button: HashMap<GamepadButton, f32>,
}

fn connection_system(mut lobby: ResMut<GamepadLobby>, gamepad_event: Res<Events<GamepadEvent>>) {
for event in lobby.gamepad_event_reader.iter(&gamepad_event) {
match &event {
Expand All @@ -42,82 +34,38 @@ fn connection_system(mut lobby: ResMut<GamepadLobby>, gamepad_event: Res<Events<
}
}

fn button_system(
fn gamepad_system(
lobby: Res<GamepadLobby>,
inputs: Res<Input<GamepadButton>>,
button_inputs: Res<Input<GamepadButton>>,
button_axes: Res<Axis<GamepadButton>>,
mut data: ResMut<GamepadData>,
) {
let button_types = [
GamepadButtonType::South,
GamepadButtonType::East,
GamepadButtonType::North,
GamepadButtonType::West,
GamepadButtonType::C,
GamepadButtonType::Z,
GamepadButtonType::LeftTrigger,
GamepadButtonType::LeftTrigger2,
GamepadButtonType::RightTrigger,
GamepadButtonType::RightTrigger2,
GamepadButtonType::Select,
GamepadButtonType::Start,
GamepadButtonType::Mode,
GamepadButtonType::LeftThumb,
GamepadButtonType::RightThumb,
GamepadButtonType::DPadUp,
GamepadButtonType::DPadDown,
GamepadButtonType::DPadLeft,
GamepadButtonType::DPadRight,
];
for gamepad in lobby.gamepads.iter() {
for button_type in button_types.iter() {
let gamepad_button = GamepadButton(*gamepad, *button_type);
if inputs.just_pressed(gamepad_button) {
println!("{:?} Pressed", gamepad_button);
} else if inputs.just_released(GamepadButton(*gamepad, *button_type)) {
println!("{:?} Released", gamepad_button);
}
if let Some(value) = button_axes.get(gamepad_button) {
if !approx_eq(
data.button.get(&gamepad_button).copied().unwrap_or(0.0),
value,
) {
data.button.insert(gamepad_button, value);
println!("{:?} is {}", gamepad_button, value);
}
}
}
}
}

fn axis_system(
lobby: Res<GamepadLobby>,
axes: Res<Axis<GamepadAxis>>,
mut data: ResMut<GamepadData>,
) {
let axis_types = [
GamepadAxisType::LeftStickX,
GamepadAxisType::LeftStickY,
GamepadAxisType::LeftZ,
GamepadAxisType::RightStickX,
GamepadAxisType::RightStickY,
GamepadAxisType::RightZ,
GamepadAxisType::DPadX,
GamepadAxisType::DPadY,
];
for gamepad in lobby.gamepads.iter() {
for axis_type in axis_types.iter() {
let gamepad_axis = GamepadAxis(*gamepad, *axis_type);
if let Some(value) = axes.get(gamepad_axis) {
if !approx_eq(data.axis.get(&gamepad_axis).copied().unwrap_or(0.0), value) {
data.axis.insert(gamepad_axis, value);
println!("{:?} is {}", gamepad_axis, value);
}
}
let south_button = GamepadButton(*gamepad, GamepadButtonType::South);
if button_inputs.just_pressed(south_button) {
println!(
"{:?} of {:?} is just pressed",
GamepadButtonType::South,
gamepad
);
} else if button_inputs.just_released(south_button) {
println!(
"{:?} of {:?} is just released",
GamepadButtonType::South,
gamepad
);
}
}
}

fn approx_eq(a: f32, b: f32) -> bool {
(a - b).abs() < f32::EPSILON
println!(
"For {:?}: {:?} is {:.4}, {:?} is {:.4}",
gamepad,
GamepadButtonType::RightTrigger2,
button_axes
.get(GamepadButton(*gamepad, GamepadButtonType::RightTrigger2))
.unwrap_or(0.0),
GamepadAxisType::LeftStickX,
axes.get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickX))
.unwrap_or(0.0)
)
}
}

0 comments on commit 853af82

Please sign in to comment.