mouse input
This commit is contained in:
96
src/input.rs
96
src/input.rs
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user