Separate gamepad state code from gamepad event code and other customizations (#700)
Separated gamepad event and gamepad state code and made gamepad input more customizable
This commit is contained in:
		
							parent
							
								
									0f43fb066f
								
							
						
					
					
						commit
						d01ba9e4fc
					
				@ -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"
 | 
			
		||||
 | 
			
		||||
@ -2,88 +2,52 @@ 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,
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            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, _) => {
 | 
			
		||||
                if let Some(button_type) = convert_button(gilrs_button) {
 | 
			
		||||
                    inputs.release(GamepadButton(
 | 
			
		||||
                        convert_gamepad_id(gilrs_event.id),
 | 
			
		||||
                        button_type,
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
                    GamepadEventType::Disconnected,
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
            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,
 | 
			
		||||
                    );
 | 
			
		||||
                    event.send(GamepadEvent(
 | 
			
		||||
                        convert_gamepad_id(gilrs_event.id),
 | 
			
		||||
                        GamepadEventType::ButtonChanged(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),
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            _ => (),
 | 
			
		||||
@ -91,88 +55,3 @@ pub fn gilrs_update_system(_world: &mut World, resources: &mut Resources) {
 | 
			
		||||
    }
 | 
			
		||||
    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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,22 @@
 | 
			
		||||
use crate::{Axis, Input};
 | 
			
		||||
use bevy_app::{EventReader, Events};
 | 
			
		||||
use bevy_ecs::{Local, Res, ResMut};
 | 
			
		||||
use bevy_utils::HashMap;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub struct Gamepad(pub usize);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub enum GamepadEventType {
 | 
			
		||||
    Connected,
 | 
			
		||||
    Disconnected,
 | 
			
		||||
    ButtonChanged(GamepadButtonType, f32),
 | 
			
		||||
    AxisChanged(GamepadAxisType, f32),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub struct GamepadEvent(pub Gamepad, pub GamepadEventType);
 | 
			
		||||
 | 
			
		||||
@ -57,3 +64,230 @@ pub enum GamepadAxisType {
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
pub struct GamepadAxis(pub Gamepad, pub GamepadAxisType);
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
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 GamepadSetting {
 | 
			
		||||
    pub fn get_button_setting(&self, button: GamepadButton) -> &ButtonSetting {
 | 
			
		||||
        self.button_settings
 | 
			
		||||
            .get(&button)
 | 
			
		||||
            .unwrap_or(&self.default_button_setting)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_axis_setting(&self, axis: GamepadAxis) -> &AxisSetting {
 | 
			
		||||
        self.axis_settings
 | 
			
		||||
            .get(&axis)
 | 
			
		||||
            .unwrap_or(&self.default_axis_setting)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_button_axis_setting(&self, button: GamepadButton) -> &ButtonAxisSetting {
 | 
			
		||||
        self.button_axis_settings
 | 
			
		||||
            .get(&button)
 | 
			
		||||
            .unwrap_or(&self.default_button_axis_setting)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct ButtonSetting {
 | 
			
		||||
    pub press: f32,
 | 
			
		||||
    pub release: f32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for ButtonSetting {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        ButtonSetting {
 | 
			
		||||
            press: 0.75,
 | 
			
		||||
            release: 0.65,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ButtonSetting {
 | 
			
		||||
    fn is_pressed(&self, value: f32) -> bool {
 | 
			
		||||
        value >= self.press
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn is_released(&self, value: f32) -> bool {
 | 
			
		||||
        value <= self.release
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
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 AxisSetting {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        AxisSetting {
 | 
			
		||||
            positive_high: 0.95,
 | 
			
		||||
            positive_low: 0.05,
 | 
			
		||||
            negative_high: -0.95,
 | 
			
		||||
            negative_low: -0.05,
 | 
			
		||||
            threshold: 0.01,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
                return old_value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if new_value <= self.positive_low && new_value >= self.negative_low {
 | 
			
		||||
            return 0.0;
 | 
			
		||||
        }
 | 
			
		||||
        if new_value >= self.positive_high {
 | 
			
		||||
            return 1.0;
 | 
			
		||||
        }
 | 
			
		||||
        if new_value <= self.negative_high {
 | 
			
		||||
            return -1.0;
 | 
			
		||||
        }
 | 
			
		||||
        new_value
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct ButtonAxisSetting {
 | 
			
		||||
    pub high: f32,
 | 
			
		||||
    pub low: f32,
 | 
			
		||||
    pub threshold: f32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for ButtonAxisSetting {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        ButtonAxisSetting {
 | 
			
		||||
            high: 0.95,
 | 
			
		||||
            low: 0.05,
 | 
			
		||||
            threshold: 0.01,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
                return old_value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if new_value <= self.low {
 | 
			
		||||
            return 0.0;
 | 
			
		||||
        }
 | 
			
		||||
        if new_value >= self.high {
 | 
			
		||||
            return 1.0;
 | 
			
		||||
        }
 | 
			
		||||
        new_value
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct GamepadEventState {
 | 
			
		||||
    gamepad_event_reader: EventReader<GamepadEvent>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn gamepad_event_system(
 | 
			
		||||
    mut state: Local<GamepadEventState>,
 | 
			
		||||
    mut button_input: ResMut<Input<GamepadButton>>,
 | 
			
		||||
    mut axis: ResMut<Axis<GamepadAxis>>,
 | 
			
		||||
    mut button_axis: ResMut<Axis<GamepadButton>>,
 | 
			
		||||
    events: Res<Events<GamepadEvent>>,
 | 
			
		||||
    settings: Res<GamepadSetting>,
 | 
			
		||||
) {
 | 
			
		||||
    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_input.reset(gamepad_button);
 | 
			
		||||
                    button_axis.set(gamepad_button, 0.0);
 | 
			
		||||
                }
 | 
			
		||||
                for axis_type in ALL_AXIS_TYPES.iter() {
 | 
			
		||||
                    axis.set(GamepadAxis(*gamepad, *axis_type), 0.0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEventType::Disconnected => {
 | 
			
		||||
                for button_type in ALL_BUTTON_TYPES.iter() {
 | 
			
		||||
                    let gamepad_button = GamepadButton(*gamepad, *button_type);
 | 
			
		||||
                    button_input.reset(gamepad_button);
 | 
			
		||||
                    button_axis.remove(gamepad_button);
 | 
			
		||||
                }
 | 
			
		||||
                for axis_type in ALL_AXIS_TYPES.iter() {
 | 
			
		||||
                    axis.remove(GamepadAxis(*gamepad, *axis_type));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEventType::AxisChanged(axis_type, value) => {
 | 
			
		||||
                let gamepad_axis = GamepadAxis(*gamepad, *axis_type);
 | 
			
		||||
                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 = settings
 | 
			
		||||
                    .get_button_axis_setting(gamepad_button)
 | 
			
		||||
                    .filter(*value, button_axis.get(gamepad_button));
 | 
			
		||||
                button_axis.set(gamepad_button, filtered_value);
 | 
			
		||||
 | 
			
		||||
                let button_property = settings.get_button_setting(gamepad_button);
 | 
			
		||||
                if button_input.pressed(gamepad_button) {
 | 
			
		||||
                    if button_property.is_released(*value) {
 | 
			
		||||
                        button_input.release(gamepad_button);
 | 
			
		||||
                    }
 | 
			
		||||
                } else if button_property.is_pressed(*value) {
 | 
			
		||||
                    button_input.press(gamepad_button);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ALL_BUTTON_TYPES: [GamepadButtonType; 19] = [
 | 
			
		||||
    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,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const ALL_AXIS_TYPES: [GamepadAxisType; 8] = [
 | 
			
		||||
    GamepadAxisType::LeftStickX,
 | 
			
		||||
    GamepadAxisType::LeftStickY,
 | 
			
		||||
    GamepadAxisType::LeftZ,
 | 
			
		||||
    GamepadAxisType::RightStickX,
 | 
			
		||||
    GamepadAxisType::RightStickY,
 | 
			
		||||
    GamepadAxisType::RightZ,
 | 
			
		||||
    GamepadAxisType::DPadX,
 | 
			
		||||
    GamepadAxisType::DPadY,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@ -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::{GamepadAxis, GamepadButton, GamepadEvent};
 | 
			
		||||
use gamepad::{gamepad_event_system, GamepadAxis, GamepadButton, GamepadEvent, GamepadSetting};
 | 
			
		||||
 | 
			
		||||
/// Adds keyboard and mouse input to an App
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
@ -50,9 +50,15 @@ impl Plugin for InputPlugin {
 | 
			
		||||
                mouse_button_input_system.system(),
 | 
			
		||||
            )
 | 
			
		||||
            .add_event::<GamepadEvent>()
 | 
			
		||||
            .init_resource::<GamepadSetting>()
 | 
			
		||||
            .init_resource::<Input<GamepadButton>>()
 | 
			
		||||
            .init_resource::<Axis<GamepadAxis>>()
 | 
			
		||||
            .init_resource::<Axis<GamepadButton>>()
 | 
			
		||||
            .add_startup_system_to_stage(
 | 
			
		||||
                bevy_app::startup_stage::POST_STARTUP,
 | 
			
		||||
                gamepad_event_system.system(),
 | 
			
		||||
            )
 | 
			
		||||
            .add_system_to_stage(bevy_app::stage::EVENT_UPDATE, gamepad_event_system.system())
 | 
			
		||||
            .add_event::<TouchInput>()
 | 
			
		||||
            .init_resource::<Touches>()
 | 
			
		||||
            .add_system_to_stage(
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,14 @@
 | 
			
		||||
use bevy::prelude::*;
 | 
			
		||||
use bevy_input::gamepad::{Gamepad, GamepadButton, GamepadEvent, GamepadEventType};
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
use bevy_utils::HashSet;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    App::build()
 | 
			
		||||
        .add_default_plugins()
 | 
			
		||||
        .init_resource::<GamepadLobby>()
 | 
			
		||||
        .add_startup_system(connection_system.system())
 | 
			
		||||
        .add_system(connection_system.system())
 | 
			
		||||
        .add_system(button_system.system())
 | 
			
		||||
        .add_system(axis_system.system())
 | 
			
		||||
        .init_resource::<GamepadLobby>()
 | 
			
		||||
        .add_system(gamepad_system.system())
 | 
			
		||||
        .run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -24,85 +23,49 @@ fn connection_system(mut lobby: ResMut<GamepadLobby>, gamepad_event: Res<Events<
 | 
			
		||||
        match &event {
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::Connected) => {
 | 
			
		||||
                lobby.gamepads.insert(*gamepad);
 | 
			
		||||
                println!("Connected {:?}", gamepad);
 | 
			
		||||
                println!("{:?} Connected", gamepad);
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::Disconnected) => {
 | 
			
		||||
                lobby.gamepads.remove(gamepad);
 | 
			
		||||
                println!("Disconnected {:?}", gamepad);
 | 
			
		||||
                println!("{:?} Disconnected", gamepad);
 | 
			
		||||
            }
 | 
			
		||||
            _ => (),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn button_system(
 | 
			
		||||
fn gamepad_system(
 | 
			
		||||
    lobby: Res<GamepadLobby>,
 | 
			
		||||
    inputs: Res<Input<GamepadButton>>,
 | 
			
		||||
    button_inputs: Res<Input<GamepadButton>>,
 | 
			
		||||
    button_axes: Res<Axis<GamepadButton>>,
 | 
			
		||||
    axes: Res<Axis<GamepadAxis>>,
 | 
			
		||||
) {
 | 
			
		||||
    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() {
 | 
			
		||||
            if inputs.just_pressed(GamepadButton(*gamepad, *button_type)) {
 | 
			
		||||
                println!("Pressed {:?}", GamepadButton(*gamepad, *button_type));
 | 
			
		||||
            } else if inputs.just_released(GamepadButton(*gamepad, *button_type)) {
 | 
			
		||||
                println!("Released {:?}", GamepadButton(*gamepad, *button_type));
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(value) = button_axes.get(&GamepadButton(*gamepad, *button_type)) {
 | 
			
		||||
                if value_check(value) {
 | 
			
		||||
                    println!(
 | 
			
		||||
                        "Button as Axis {:?} is {}",
 | 
			
		||||
                        GamepadButton(*gamepad, *button_type),
 | 
			
		||||
                        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
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn axis_system(lobby: Res<GamepadLobby>, axes: Res<Axis<GamepadAxis>>) {
 | 
			
		||||
    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() {
 | 
			
		||||
            if let Some(value) = axes.get(&GamepadAxis(*gamepad, *axis_type)) {
 | 
			
		||||
                if value_check(value) {
 | 
			
		||||
                    println!("Axis {:?} is {}", GamepadAxis(*gamepad, *axis_type), value);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn value_check(value: f32) -> bool {
 | 
			
		||||
    let value = value.abs();
 | 
			
		||||
    value > 0.1f32 && value < 0.9f32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								examples/input/gamepad_input_event.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								examples/input/gamepad_input_event.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
use bevy::prelude::*;
 | 
			
		||||
use bevy_input::gamepad::{GamepadEvent, GamepadEventType};
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    App::build()
 | 
			
		||||
        .add_default_plugins()
 | 
			
		||||
        .add_startup_system(gamepad_raw_events.system())
 | 
			
		||||
        .add_system(gamepad_raw_events.system())
 | 
			
		||||
        .run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
struct State {
 | 
			
		||||
    gamepad_event_reader: EventReader<GamepadEvent>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn gamepad_raw_events(mut state: Local<State>, gamepad_event: Res<Events<GamepadEvent>>) {
 | 
			
		||||
    for event in state.gamepad_event_reader.iter(&gamepad_event) {
 | 
			
		||||
        match &event {
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::Connected) => {
 | 
			
		||||
                println!("{:?} Connected", gamepad);
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::Disconnected) => {
 | 
			
		||||
                println!("{:?} Disconnected", gamepad);
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::ButtonChanged(button_type, value)) => {
 | 
			
		||||
                println!("{:?} of {:?} is changed to {}", button_type, gamepad, value);
 | 
			
		||||
            }
 | 
			
		||||
            GamepadEvent(gamepad, GamepadEventType::AxisChanged(axis_type, value)) => {
 | 
			
		||||
                println!("{:?} of {:?} is changed to {}", axis_type, gamepad, value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user