mouse input

This commit is contained in:
2019-07-27 17:21:03 +02:00
parent ee01892a22
commit 6f2b9d1b71
4 changed files with 96 additions and 43 deletions

View File

@@ -1,13 +1,18 @@
[[button]]
name = "QUIT"
scancode = 1
scan_code = 1
[[button]]
name = "QUIT"
mouse = "Left"
shift = true
[[button]]
name = "RELOAD_SHADERS"
scancode = 19
scan_code = 19
ctrl = true
[[axis]]
name = "FORWARD"
scancode_positive = 17
scancode_negative = 31
scan_code_positive = 17
scan_code_negative = 31

View File

@@ -1 +1 @@
input = false
input = true

View File

@@ -6,6 +6,7 @@ use std::fs;
use toml;
use serde_derive::{Serialize, Deserialize};
use std::iter::FromIterator;
pub struct VirtualButton {
pub digital_inputs: Vec<DigitalInput>
@@ -19,7 +20,8 @@ pub struct InputState {
pub virtual_buttons: HashMap<String, VirtualButton>,
pub virtual_axes: HashMap<String, VirtualAxis>,
input_events: HashSet<DigitalInputEvent>,
pressed_buttons: HashSet<ScanCode>
pressed_scan_codes: HashSet<ScanCode>,
pressed_mouse_buttons: HashSet<MouseButton>
}
#[derive(Debug, PartialEq, Eq, Hash)]
@@ -37,34 +39,51 @@ struct InputConfig {
#[derive(Debug, Serialize, Deserialize)]
struct InputConfigButton {
name: String,
scancode: u32,
ctrl: Option<bool>
scan_code: Option<u32>,
mouse: Option<String>,
ctrl: Option<bool>,
shift: Option<bool>,
alt: Option<bool>,
logo: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
struct InputConfigAxis {
name: String,
scancode_positive: u32,
scan_code_positive: u32,
ctrl_positive: Option<bool>,
scancode_negative: u32,
scan_code_negative: u32,
ctrl_negative: Option<bool>
}
impl InputState {
pub fn new(toml_path: &str) -> InputState {
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(),
input_events: HashSet::new(), pressed_buttons: HashSet::new() };
input_events: HashSet::new(), pressed_scan_codes: HashSet::new(), pressed_mouse_buttons: HashSet::new() };
let config: InputConfig = toml::from_slice(&fs::read(toml_path).expect("Failed to read input config!")).expect("Failed to parse input config!");
config.button.iter().for_each(|bn| {
let modifiers = ModifiersState {
shift: false,
shift: bn.shift.is_some(),
ctrl: bn.ctrl.is_some(),
alt: false,
logo: false
alt: bn.alt.is_some(),
logo: bn.logo.is_some()
};
let input = DigitalInput::Keyboard(KeyboardInput { scancode: bn.scancode, modifiers });
let input = if let Some(scan_code) = bn.scan_code {
DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers })
} else if let Some(button_name) = &bn.mouse {
let button = match button_name.to_lowercase().as_str() {
"left" => MouseButton::Left,
"middle" => MouseButton::Middle,
"right" => MouseButton::Right,
other => MouseButton::Other(other.parse().expect(&format!("Unknown button: {:?}", other)))
};
DigitalInput::Mouse(MouseInput { button, modifiers })
} else {
panic!("No mouse or keyboard input for button {:?}", bn.name);
};
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
virtual_button.digital_inputs.push(input);
} else {
@@ -86,8 +105,8 @@ impl InputState {
logo: false
};
let axis = AxisInput::Digital(
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_positive, modifiers: modifiers_positive }),
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_negative, modifiers: modifiers_negative })
DigitalInput::Keyboard(KeyboardInput { scan_code: a.scan_code_positive, modifiers: modifiers_positive }),
DigitalInput::Keyboard(KeyboardInput { scan_code: a.scan_code_negative, modifiers: modifiers_negative })
);
if let Some(virtual_axis) = state.virtual_axes.get_mut(&a.name) {
virtual_axis.axis_inputs.push(axis);
@@ -168,35 +187,52 @@ impl InputState {
pub fn digital_input_pressed(self: &Self, digital_input: &DigitalInput) -> bool {
match digital_input {
DigitalInput::Keyboard(keyboard_input) =>
self.pressed_buttons.contains(&keyboard_input.scancode)
&& self.modifiers_are_pressed(keyboard_input.modifiers),
DigitalInput::Mouse(_) => false
DigitalInput::Keyboard(keyboard_input) => {
self.pressed_scan_codes.contains(&keyboard_input.scan_code)
&& self.modifiers_are_pressed(keyboard_input.modifiers)
},
DigitalInput::Mouse(mouse_input) => {
self.pressed_mouse_buttons.contains(&mouse_input.button)
&& self.modifiers_are_pressed(mouse_input.modifiers)
}
}
}
fn modifiers_are_pressed(self: &Self, modifiers: ModifiersState) -> bool {
(!modifiers.ctrl || self.pressed_buttons.contains(&29))
&& (!modifiers.shift || self.pressed_buttons.contains(&42) || self.pressed_buttons.contains(&54))
&& (!modifiers.alt || self.pressed_buttons.contains(&56))
&& (!modifiers.logo || self.pressed_buttons.contains(&91) || self.pressed_buttons.contains(&92))
(!modifiers.ctrl || self.pressed_scan_codes.contains(&29))
&& (!modifiers.shift || self.pressed_scan_codes.contains(&42) || self.pressed_scan_codes.contains(&54))
&& (!modifiers.alt || self.pressed_scan_codes.contains(&56))
&& (!modifiers.logo || self.pressed_scan_codes.contains(&91) || self.pressed_scan_codes.contains(&92))
}
fn digital_input_to_float(self: &Self, input: &DigitalInput) -> f32 {
if self.digital_input_pressed(input) { 1.0 } else { 0.0 }
}
pub fn on_keyboard_event(self: &mut Self, state: ElementState, scancode: ScanCode, modifiers: ModifiersState) {
let input = DigitalInput::Keyboard(KeyboardInput { scancode, modifiers });
pub fn on_keyboard_event(self: &mut Self, state: ElementState, scan_code: ScanCode, modifiers: ModifiersState) {
let input = DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers });
match state {
ElementState::Pressed => {
self.input_events.insert(DigitalInputEvent::Pressed(input));
self.pressed_buttons.insert(scancode);
self.pressed_scan_codes.insert(scan_code);
},
ElementState::Released => {
self.input_events.insert(DigitalInputEvent::Released(input));
self.pressed_buttons.remove(&scancode);
self.pressed_scan_codes.remove(&scan_code);
},
}
}
pub fn on_mouse_event(self: &mut Self, state: &ElementState, button: &MouseButton, modifiers: &ModifiersState) {
let input = DigitalInput::Mouse(MouseInput { button: button.clone(), modifiers: modifiers.clone() });
match state {
ElementState::Pressed => {
self.input_events.insert(DigitalInputEvent::Pressed(input));
self.pressed_mouse_buttons.insert(button.clone());
},
ElementState::Released => {
self.input_events.insert(DigitalInputEvent::Released(input));
self.pressed_mouse_buttons.remove(button);
},
}
}
@@ -206,6 +242,14 @@ impl InputState {
}
}
pub fn mods_to_string(modifiers: &ModifiersState) -> String {
String::from_iter(
vec!["shift", "ctrl", "alt", "logo"].iter()
.zip(vec![modifiers.shift, modifiers.ctrl, modifiers.alt, modifiers.logo])
.filter(|(&_name, state)| *state)
.map(|(&name, _state)| name))
}
pub enum AxisInput {
Analog(AnalogInput),
Digital(DigitalInput, DigitalInput),
@@ -219,7 +263,7 @@ pub enum DigitalInput {
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct KeyboardInput {
scancode: ScanCode,
scan_code: ScanCode,
modifiers: ModifiersState
}

View File

@@ -1,12 +1,11 @@
use winit::{Event, WindowEvent};
use std::iter::FromIterator;
use cgmath::{Matrix4, Rad, Point3, Vector3, Deg};
mod vulkan;
use crate::vulkan::{GameData, Game, LinePoint};
mod input;
use crate::input::{InputState};
use crate::input::{InputState, mods_to_string};
mod config;
use crate::config::LogConfig;
@@ -63,23 +62,28 @@ impl Game for TestGame {
match event {
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
if self.log_config.input {
let mods = String::from_iter(
vec!["shift", "ctrl", "alt", "logo"].iter()
.zip(vec![input.modifiers.shift, input.modifiers.ctrl, input.modifiers.alt, input.modifiers.logo])
.filter(|(&_name, state)| *state)
.map(|(&name, _state)| name));
let mods = mods_to_string(&input.modifiers);
if mods.len() > 0 {
println!("Keyboard {:?} input {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode)
println!("Keyboard {:?} {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode)
} else {
println!("Keyboard {:?} input {:?} {:?}", device_id, input.state, input.scancode)
println!("Keyboard {:?} {:?} {:?}", device_id, input.state, input.scancode)
}
}
self.input.on_keyboard_event(input.state, input.scancode, input.modifiers);
},
// Event::WindowEvent { event: WindowEvent::MouseInput { device_id, state, button, modifiers }, .. } => {
//
// }
Event::WindowEvent { event: WindowEvent::MouseInput { device_id, state, button, modifiers }, .. } => {
if self.log_config.input {
let mods = mods_to_string(modifiers);
if mods.len() > 0 {
println!("Mouse {:?} {:?} {:?} + {:?}", device_id, state, &mods, button)
} else {
println!("Mouse {:?} {:?} {:?}", device_id, state, button)
}
}
self.input.on_mouse_event(state, button, modifiers);
}
_ => {}
}
}