mouse input
This commit is contained in:
@@ -1,13 +1,18 @@
|
|||||||
[[button]]
|
[[button]]
|
||||||
name = "QUIT"
|
name = "QUIT"
|
||||||
scancode = 1
|
scan_code = 1
|
||||||
|
|
||||||
|
[[button]]
|
||||||
|
name = "QUIT"
|
||||||
|
mouse = "Left"
|
||||||
|
shift = true
|
||||||
|
|
||||||
[[button]]
|
[[button]]
|
||||||
name = "RELOAD_SHADERS"
|
name = "RELOAD_SHADERS"
|
||||||
scancode = 19
|
scan_code = 19
|
||||||
ctrl = true
|
ctrl = true
|
||||||
|
|
||||||
[[axis]]
|
[[axis]]
|
||||||
name = "FORWARD"
|
name = "FORWARD"
|
||||||
scancode_positive = 17
|
scan_code_positive = 17
|
||||||
scancode_negative = 31
|
scan_code_negative = 31
|
||||||
@@ -1 +1 @@
|
|||||||
input = false
|
input = true
|
||||||
96
src/input.rs
96
src/input.rs
@@ -6,6 +6,7 @@ use std::fs;
|
|||||||
use toml;
|
use toml;
|
||||||
|
|
||||||
use serde_derive::{Serialize, Deserialize};
|
use serde_derive::{Serialize, Deserialize};
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
pub struct VirtualButton {
|
pub struct VirtualButton {
|
||||||
pub digital_inputs: Vec<DigitalInput>
|
pub digital_inputs: Vec<DigitalInput>
|
||||||
@@ -19,7 +20,8 @@ pub struct InputState {
|
|||||||
pub virtual_buttons: HashMap<String, VirtualButton>,
|
pub virtual_buttons: HashMap<String, VirtualButton>,
|
||||||
pub virtual_axes: HashMap<String, VirtualAxis>,
|
pub virtual_axes: HashMap<String, VirtualAxis>,
|
||||||
input_events: HashSet<DigitalInputEvent>,
|
input_events: HashSet<DigitalInputEvent>,
|
||||||
pressed_buttons: HashSet<ScanCode>
|
pressed_scan_codes: HashSet<ScanCode>,
|
||||||
|
pressed_mouse_buttons: HashSet<MouseButton>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
@@ -37,34 +39,51 @@ struct InputConfig {
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct InputConfigButton {
|
struct InputConfigButton {
|
||||||
name: String,
|
name: String,
|
||||||
scancode: u32,
|
scan_code: Option<u32>,
|
||||||
ctrl: Option<bool>
|
mouse: Option<String>,
|
||||||
|
ctrl: Option<bool>,
|
||||||
|
shift: Option<bool>,
|
||||||
|
alt: Option<bool>,
|
||||||
|
logo: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct InputConfigAxis {
|
struct InputConfigAxis {
|
||||||
name: String,
|
name: String,
|
||||||
scancode_positive: u32,
|
scan_code_positive: u32,
|
||||||
ctrl_positive: Option<bool>,
|
ctrl_positive: Option<bool>,
|
||||||
scancode_negative: u32,
|
scan_code_negative: u32,
|
||||||
ctrl_negative: Option<bool>
|
ctrl_negative: Option<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputState {
|
impl InputState {
|
||||||
pub fn new(toml_path: &str) -> InputState {
|
pub fn new(toml_path: &str) -> InputState {
|
||||||
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(),
|
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!");
|
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| {
|
config.button.iter().for_each(|bn| {
|
||||||
let modifiers = ModifiersState {
|
let modifiers = ModifiersState {
|
||||||
shift: false,
|
shift: bn.shift.is_some(),
|
||||||
ctrl: bn.ctrl.is_some(),
|
ctrl: bn.ctrl.is_some(),
|
||||||
alt: false,
|
alt: bn.alt.is_some(),
|
||||||
logo: false
|
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) {
|
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
|
||||||
virtual_button.digital_inputs.push(input);
|
virtual_button.digital_inputs.push(input);
|
||||||
} else {
|
} else {
|
||||||
@@ -86,8 +105,8 @@ impl InputState {
|
|||||||
logo: false
|
logo: false
|
||||||
};
|
};
|
||||||
let axis = AxisInput::Digital(
|
let axis = AxisInput::Digital(
|
||||||
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_positive, modifiers: modifiers_positive }),
|
DigitalInput::Keyboard(KeyboardInput { scan_code: a.scan_code_positive, modifiers: modifiers_positive }),
|
||||||
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_negative, modifiers: modifiers_negative })
|
DigitalInput::Keyboard(KeyboardInput { scan_code: a.scan_code_negative, modifiers: modifiers_negative })
|
||||||
);
|
);
|
||||||
if let Some(virtual_axis) = state.virtual_axes.get_mut(&a.name) {
|
if let Some(virtual_axis) = state.virtual_axes.get_mut(&a.name) {
|
||||||
virtual_axis.axis_inputs.push(axis);
|
virtual_axis.axis_inputs.push(axis);
|
||||||
@@ -168,35 +187,52 @@ impl InputState {
|
|||||||
|
|
||||||
pub fn digital_input_pressed(self: &Self, digital_input: &DigitalInput) -> bool {
|
pub fn digital_input_pressed(self: &Self, digital_input: &DigitalInput) -> bool {
|
||||||
match digital_input {
|
match digital_input {
|
||||||
DigitalInput::Keyboard(keyboard_input) =>
|
DigitalInput::Keyboard(keyboard_input) => {
|
||||||
self.pressed_buttons.contains(&keyboard_input.scancode)
|
self.pressed_scan_codes.contains(&keyboard_input.scan_code)
|
||||||
&& self.modifiers_are_pressed(keyboard_input.modifiers),
|
&& self.modifiers_are_pressed(keyboard_input.modifiers)
|
||||||
DigitalInput::Mouse(_) => false
|
},
|
||||||
|
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 {
|
fn modifiers_are_pressed(self: &Self, modifiers: ModifiersState) -> bool {
|
||||||
(!modifiers.ctrl || self.pressed_buttons.contains(&29))
|
(!modifiers.ctrl || self.pressed_scan_codes.contains(&29))
|
||||||
&& (!modifiers.shift || self.pressed_buttons.contains(&42) || self.pressed_buttons.contains(&54))
|
&& (!modifiers.shift || self.pressed_scan_codes.contains(&42) || self.pressed_scan_codes.contains(&54))
|
||||||
&& (!modifiers.alt || self.pressed_buttons.contains(&56))
|
&& (!modifiers.alt || self.pressed_scan_codes.contains(&56))
|
||||||
&& (!modifiers.logo || self.pressed_buttons.contains(&91) || self.pressed_buttons.contains(&92))
|
&& (!modifiers.logo || self.pressed_scan_codes.contains(&91) || self.pressed_scan_codes.contains(&92))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn digital_input_to_float(self: &Self, input: &DigitalInput) -> f32 {
|
fn digital_input_to_float(self: &Self, input: &DigitalInput) -> f32 {
|
||||||
if self.digital_input_pressed(input) { 1.0 } else { 0.0 }
|
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) {
|
pub fn on_keyboard_event(self: &mut Self, state: ElementState, scan_code: ScanCode, modifiers: ModifiersState) {
|
||||||
let input = DigitalInput::Keyboard(KeyboardInput { scancode, modifiers });
|
let input = DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers });
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
ElementState::Pressed => {
|
ElementState::Pressed => {
|
||||||
self.input_events.insert(DigitalInputEvent::Pressed(input));
|
self.input_events.insert(DigitalInputEvent::Pressed(input));
|
||||||
self.pressed_buttons.insert(scancode);
|
self.pressed_scan_codes.insert(scan_code);
|
||||||
},
|
},
|
||||||
ElementState::Released => {
|
ElementState::Released => {
|
||||||
self.input_events.insert(DigitalInputEvent::Released(input));
|
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 {
|
pub enum AxisInput {
|
||||||
Analog(AnalogInput),
|
Analog(AnalogInput),
|
||||||
Digital(DigitalInput, DigitalInput),
|
Digital(DigitalInput, DigitalInput),
|
||||||
@@ -219,7 +263,7 @@ pub enum DigitalInput {
|
|||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||||
pub struct KeyboardInput {
|
pub struct KeyboardInput {
|
||||||
scancode: ScanCode,
|
scan_code: ScanCode,
|
||||||
modifiers: ModifiersState
|
modifiers: ModifiersState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/main.rs
28
src/main.rs
@@ -1,12 +1,11 @@
|
|||||||
use winit::{Event, WindowEvent};
|
use winit::{Event, WindowEvent};
|
||||||
use std::iter::FromIterator;
|
|
||||||
use cgmath::{Matrix4, Rad, Point3, Vector3, Deg};
|
use cgmath::{Matrix4, Rad, Point3, Vector3, Deg};
|
||||||
|
|
||||||
mod vulkan;
|
mod vulkan;
|
||||||
use crate::vulkan::{GameData, Game, LinePoint};
|
use crate::vulkan::{GameData, Game, LinePoint};
|
||||||
|
|
||||||
mod input;
|
mod input;
|
||||||
use crate::input::{InputState};
|
use crate::input::{InputState, mods_to_string};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
use crate::config::LogConfig;
|
use crate::config::LogConfig;
|
||||||
@@ -63,23 +62,28 @@ impl Game for TestGame {
|
|||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
|
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
|
||||||
if self.log_config.input {
|
if self.log_config.input {
|
||||||
let mods = String::from_iter(
|
let mods = mods_to_string(&input.modifiers);
|
||||||
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));
|
|
||||||
if mods.len() > 0 {
|
if mods.len() > 0 {
|
||||||
println!("Keyboard {:?} input {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode)
|
println!("Keyboard {:?} {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode)
|
||||||
} else {
|
} 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);
|
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);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user