From 7fe3d34d79bc6c5407662bb756d46d72f58afa4e Mon Sep 17 00:00:00 2001 From: Till Date: Wed, 31 Jul 2019 19:13:59 +0200 Subject: [PATCH] controller input --- Cargo.toml | 3 +- config/input.toml | 6 ++- src/input.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 3 ++ 4 files changed, 116 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71ef8a6..c2f8451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,5 @@ image = "0.22.0" collada = "0.11.0" serde = "1.0.97" serde_derive = "1.0.97" -toml = "0.5.1" \ No newline at end of file +toml = "0.5.1" +gilrs = "0.7.1" diff --git a/config/input.toml b/config/input.toml index e815e48..6f5590d 100644 --- a/config/input.toml +++ b/config/input.toml @@ -29,7 +29,7 @@ scan_code = 32 [[button]] name = "test" -scan_code = 20 +controller_button = "West" ctrl = true [[axis]] @@ -46,6 +46,10 @@ name = "move_sideways" positive_button = "d" negative_button = "a" +[[axis]] +name = "move_sideways" +controller_axis = "LeftStickX" + [[axis]] name = "look_horizontal" mouse_axis = "x" diff --git a/src/input.rs b/src/input.rs index 6dd22ff..96a04cc 100644 --- a/src/input.rs +++ b/src/input.rs @@ -2,11 +2,15 @@ use winit::{ScanCode, ModifiersState, MouseButton, ElementState, MouseScrollDelt use std::collections::{HashMap, HashSet}; use std::fs; +use std::iter::FromIterator; use toml; use serde_derive::{Serialize, Deserialize}; -use std::iter::FromIterator; + +use gilrs; +use gilrs::{Gilrs, EventType}; + use crate::config::LogConfig; #[derive(Debug, Clone)] @@ -42,6 +46,7 @@ struct InputConfigButton { name: String, scan_code: Option, mouse: Option, + controller_button: Option, ctrl: Option, shift: Option, alt: Option, @@ -54,6 +59,7 @@ struct InputConfigAxis { positive_button: Option, negative_button: Option, mouse_axis: Option, + controller_axis: Option, ctrl: Option, shift: Option, alt: Option, @@ -72,6 +78,7 @@ pub struct InputState<'a> { analog_wheel_state: f32, config: InputConfigConfig, log_config: &'a LogConfig, + controller_input: Gilrs, } impl <'a> InputState<'a> { @@ -81,7 +88,8 @@ impl <'a> InputState<'a> { let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(), input_events: HashSet::new(), pressed_scan_codes: HashSet::new(), pressed_mouse_buttons: HashSet::new(), analog_wheel_state: 0.0, - config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, log_config }; + config: config.config, mouse_delta_x: 0.0, mouse_delta_y: 0.0, log_config, + controller_input: Gilrs::new().unwrap() }; config.button.iter().for_each(|bn| { let modifiers = ModifiersState { @@ -102,6 +110,10 @@ impl <'a> InputState<'a> { "wheeldown" => DigitalInput::Wheel(WheelInput { direction: WheelInputDirection::Down, modifiers }), other => DigitalInput::Mouse(MouseInput { button: MouseButton::Other(other.parse().expect(&format!("Unknown button: {:?}", other))), modifiers }), } + } else if let Some(controller_button) = &bn.controller_button { + DigitalInput::Controller(ControllerInput { + button: string_to_button(controller_button.as_str()).expect(&format!("Unknown controller button: {}", controller_button.as_str())) + }) } else { panic!("No mouse or keyboard input for button {:?}", bn.name); }; @@ -139,7 +151,10 @@ impl <'a> InputState<'a> { other => panic!("Axis {:?} has unknown mouse axis name {:?}!", axis_name, other), } }, - other => panic!("Axis {:?} needs either positive_button and negative_button or mouse_wheel must be set to true!", other.name) + InputConfigAxis { controller_axis: Some(controller_axis_name), .. } => { + AxisInput::Controller(AnalogControllerInput { axis: string_to_axis(controller_axis_name).expect(&format!("Unknown controller axis: {}", controller_axis_name)) }) + }, + other => panic!("Axis {:?} needs either positive_button and negative_button or mouse_wheel or controller_axis must be set to true!", other.name) }; if let Some(virtual_axis) = state.virtual_axes.get_mut(&axis.name) { @@ -269,8 +284,13 @@ impl <'a> InputState<'a> { AxisInput::Digital(positive_button, negative_button) => { self.virtual_button_to_float(positive_button) - self.virtual_button_to_float(negative_button) }, + AxisInput::Controller(controller_input) => { + self.controller_input.gamepads() + .map(|(_id, gamepad)| gamepad.value(controller_input.axis)) + .fold(0.0, fold_axis_value) + } } - }).fold(0.0, |fold, it| if f32::abs(it) > f32::abs(fold) { it } else { fold }) + }).fold(0.0, fold_axis_value) } else { assert!(false, format!("Axis {:?} not found!", axis_code)); 0.0 @@ -289,6 +309,9 @@ impl <'a> InputState<'a> { }, DigitalInput::Wheel(wheel_input) => { self.input_events.contains(&DigitalInputEvent::Pressed(DigitalInput::Wheel(wheel_input.clone()))) + }, + DigitalInput::Controller(controller_input) => { + self.controller_input.gamepads().any(|(_id, gamepad)| gamepad.is_pressed(controller_input.button)) } } } @@ -358,6 +381,25 @@ impl <'a> InputState<'a> { }; } + pub fn frame_start(self: &mut Self) { + while let Some(event) = self.controller_input.next_event() { + match event.event { + EventType::ButtonPressed(button, _) => { + self.input_events.insert(DigitalInputEvent::Pressed(DigitalInput::Controller(ControllerInput { button }))); + }, + EventType::ButtonRepeated(_, _) => {}, + EventType::ButtonReleased(button, _) => { + self.input_events.insert(DigitalInputEvent::Released(DigitalInput::Controller(ControllerInput { button }))); + }, + EventType::ButtonChanged(_, _, _) => {}, + EventType::AxisChanged(_, _, _) => {}, + EventType::Connected => {}, + EventType::Disconnected => {}, + EventType::Dropped => {}, + } + } + } + pub fn frame_end(self: &mut Self) { self.analog_wheel_state = 0.0; self.mouse_delta_x = 0.0; @@ -379,6 +421,7 @@ pub enum AxisInput { Wheel(ModifiersState), MouseMove(MouseMoveDirection, ModifiersState), Digital(VirtualButton, VirtualButton), + Controller(AnalogControllerInput), } #[derive(Debug, Eq, PartialEq, Hash, Clone)] @@ -386,6 +429,7 @@ pub enum DigitalInput { Keyboard(KeyboardInput), Wheel(WheelInput), Mouse(MouseInput), + Controller(ControllerInput), } #[derive(Debug, Eq, PartialEq, Hash, Clone)] @@ -406,6 +450,11 @@ pub struct WheelInput { modifiers: ModifiersState, } +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub struct ControllerInput { + button: gilrs::Button, +} + #[derive(Debug, Eq, PartialEq, Hash, Clone)] pub enum WheelInputDirection { Up, @@ -422,4 +471,57 @@ pub enum MouseMoveDirection { pub struct AnalogWheelInput { value: f32, modifiers: ModifiersState, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct AnalogControllerInput { + axis: gilrs::Axis, +} + +fn fold_axis_value(fold: f32, it: f32) -> f32 { + if f32::abs(it) > f32::abs(fold) { it } else { fold } +} + +fn string_to_button(button_name: &str) -> Option { + match button_name { + "South" => Some(gilrs::Button::South), + "East" => Some(gilrs::Button::East), + "North" => Some(gilrs::Button::North), + "West" => Some(gilrs::Button::West), + "C" => Some(gilrs::Button::C), + "Z" => Some(gilrs::Button::Z), + // Triggers + "LeftTrigger" => Some(gilrs::Button::LeftTrigger), + "LeftTrigger2" => Some(gilrs::Button::LeftTrigger2), + "RightTrigger" => Some(gilrs::Button::RightTrigger), + "RightTrigger2" => Some(gilrs::Button::RightTrigger2), + // Menu Pad + "Select" => Some(gilrs::Button::Select), + "Start" => Some(gilrs::Button::Start), + "Mode" => Some(gilrs::Button::Mode), + // Sticks + "LeftThumb" => Some(gilrs::Button::LeftThumb), + "RightThumb" => Some(gilrs::Button::RightThumb), + // D-Pad + "DPadUp" => Some(gilrs::Button::DPadUp), + "DPadDown" => Some(gilrs::Button::DPadDown), + "DPadLeft" => Some(gilrs::Button::DPadLeft), + "DPadRight" => Some(gilrs::Button::DPadRight), + + _ => None, + } +} + +fn string_to_axis(axis_name: &str) -> Option { + match axis_name { + "LeftStickX" => Some(gilrs::Axis::LeftStickX), + "LeftStickY" => Some(gilrs::Axis::LeftStickY), + "LeftZ" => Some(gilrs::Axis::LeftZ), + "RightStickX" => Some(gilrs::Axis::RightStickX), + "RightStickY" => Some(gilrs::Axis::RightStickY), + "RightZ" => Some(gilrs::Axis::RightZ), + "DPadX" => Some(gilrs::Axis::DPadX), + "DPadY" => Some(gilrs::Axis::DPadY), + _ => None, + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ac1b3eb..01b3046 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,8 @@ impl TestGame<'_> { } fn update(self: &mut Self, renderer: &mut VulkanRenderer) { + self.input.frame_start(); + let new_time = renderer.game_data.start_time.elapsed().unwrap().as_millis() as f32 / 1000.0; let frame_time = new_time - renderer.game_data.push_constants.time; renderer.game_data.push_constants.time = new_time; @@ -51,6 +53,7 @@ impl TestGame<'_> { } if self.input.button_just_pressed("test") { + println!("test"); self.cubes.push(renderer.add_game_object(GameObject::new(self.cube_mesh.unwrap()))); }