parse input from file
This commit is contained in:
@@ -13,4 +13,7 @@ shaderc = "0.5.0"
|
||||
cgmath = "0.17"
|
||||
winit = "0.19"
|
||||
image = "0.22.0"
|
||||
tobj = "0.1.8"
|
||||
tobj = "0.1.8"
|
||||
serde = "1.0.97"
|
||||
serde_derive = "1.0.97"
|
||||
toml = "0.5.1"
|
||||
13
config/input.toml
Normal file
13
config/input.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[[button]]
|
||||
name = "QUIT"
|
||||
scancode = 1
|
||||
|
||||
[[button]]
|
||||
name = "RELOAD_SHADERS"
|
||||
scancode = 19
|
||||
ctrl = true
|
||||
|
||||
[[axis]]
|
||||
name = "FORWARD"
|
||||
scancode_positive = 17
|
||||
scancode_negative = 31
|
||||
@@ -3,5 +3,5 @@
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
f_color = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
135
src/input.rs
135
src/input.rs
@@ -1,5 +1,10 @@
|
||||
use winit::{ScanCode, ModifiersState, MouseButton, ElementState};
|
||||
use std::collections::{HashMap};
|
||||
use std::fs;
|
||||
|
||||
use toml;
|
||||
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
|
||||
pub struct VirtualButton {
|
||||
pub digital_inputs: Vec<DigitalInput>
|
||||
@@ -15,9 +20,75 @@ pub struct InputState {
|
||||
pressed_digital: HashMap<DigitalInput, (bool, bool)>
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct InputConfig {
|
||||
button: Vec<InputConfigButton>,
|
||||
axis: Vec<InputConfigAxis>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct InputConfigButton {
|
||||
name: String,
|
||||
scancode: u32,
|
||||
ctrl: Option<bool>
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct InputConfigAxis {
|
||||
name: String,
|
||||
scancode_positive: u32,
|
||||
ctrl_positive: Option<bool>,
|
||||
scancode_negative: u32,
|
||||
ctrl_negative: Option<bool>
|
||||
}
|
||||
|
||||
type InputHashmapEntry<'a> = (&'a DigitalInput, (bool, bool));
|
||||
impl InputState {
|
||||
pub fn new() -> InputState {
|
||||
InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(), pressed_digital: HashMap::new() }
|
||||
pub fn new(toml_path: &str) -> InputState {
|
||||
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(), pressed_digital: HashMap::new() };
|
||||
|
||||
let config: InputConfig = toml::from_slice(&fs::read(toml_path).expect("Failed to read input config!")).expect("Failed to parse input config!");
|
||||
|
||||
let buttons = config.button.iter().for_each(|bn| {
|
||||
let modifiers = ModifiersState {
|
||||
shift: false,
|
||||
ctrl: bn.ctrl.is_some(),
|
||||
alt: false,
|
||||
logo: false
|
||||
};
|
||||
let input = DigitalInput::Keyboard(KeyboardInput { scancode: bn.scancode, modifiers });
|
||||
if let Some(virtual_button) = state.virtual_buttons.get_mut(&bn.name) {
|
||||
virtual_button.digital_inputs.push(input);
|
||||
} else {
|
||||
state.virtual_buttons.insert(bn.name.clone(), VirtualButton { digital_inputs: vec![input] });
|
||||
}
|
||||
});
|
||||
|
||||
let axes = config.axis.iter().for_each(|a| {
|
||||
let modifiers_positive = ModifiersState {
|
||||
shift: false,
|
||||
ctrl: a.ctrl_positive.is_some(),
|
||||
alt: false,
|
||||
logo: false
|
||||
};
|
||||
let modifiers_negative = ModifiersState {
|
||||
shift: false,
|
||||
ctrl: a.ctrl_negative.is_some(),
|
||||
alt: false,
|
||||
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 })
|
||||
);
|
||||
if let Some(virtual_axis) = state.virtual_axes.get_mut(&a.name) {
|
||||
virtual_axis.analog_inputs.push(axis);
|
||||
} else {
|
||||
state.virtual_axes.insert(a.name.clone(), VirtualAxis { analog_inputs: vec![axis] });
|
||||
}
|
||||
});
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
pub fn button_down(self: &Self, button_code: &str) -> bool {
|
||||
@@ -28,12 +99,51 @@ impl InputState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn button_just_pressed(self: &Self, input: VirtualButton) -> bool {
|
||||
false
|
||||
pub fn button_just_pressed(self: &Self, button_code: &str) -> bool {
|
||||
if let Some(input) = self.virtual_buttons.get(button_code) {
|
||||
self.pressed_digital.iter()
|
||||
.filter(|(_, (pressed, _))| *pressed)
|
||||
.any(|(registered_input, _)| input.digital_inputs.iter().any(|digital_input| digital_input == registered_input))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn button_just_released(self: &Self, input: VirtualButton) -> bool {
|
||||
false
|
||||
pub fn button_just_released(self: &Self, button_code: &str) -> bool {
|
||||
if let Some(input) = self.virtual_buttons.get(button_code) {
|
||||
self.pressed_digital.iter()
|
||||
.filter(|(_, (_, released))| *released)
|
||||
.any(|(registered_input, _)| input.digital_inputs.iter().any(|digital_input| digital_input == registered_input))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_axis(self: &Self, axis_code: &str) -> f32 {
|
||||
if let Some(axis) = self.virtual_axes.get(axis_code) {
|
||||
axis.analog_inputs.iter().fold(0.0, |fold, item| {
|
||||
let val = match item {
|
||||
AxisInput::Analog(_) => 0.0,
|
||||
AxisInput::Digital(positive_button, negative_button) => self.button_to_float(positive_button) - self.button_to_float(negative_button),
|
||||
};
|
||||
if f32::abs(val) > fold {
|
||||
val
|
||||
} else {
|
||||
fold
|
||||
}
|
||||
})
|
||||
} else {
|
||||
assert!(false, format!("Axis {:?} not found!", axis_code));
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn button_to_float(self: &Self, input: &DigitalInput) -> f32 {
|
||||
if self.pressed_digital.iter().any(|(registered_input, _)| input == registered_input) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_keyboard_event(self: &mut Self, state: ElementState, scancode: ScanCode, modifiers: ModifiersState) {
|
||||
@@ -49,7 +159,7 @@ impl InputState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish_update(self: &mut Self) {
|
||||
pub fn frame_end(self: &mut Self) {
|
||||
self.pressed_digital.iter_mut().for_each(|(_, (recent_press, _))| {
|
||||
if *recent_press { *recent_press = false }
|
||||
});
|
||||
@@ -68,17 +178,6 @@ pub enum DigitalInput {
|
||||
Mouse(MouseInput)
|
||||
}
|
||||
|
||||
impl DigitalInput {
|
||||
pub fn simple_key(scancode: ScanCode) -> DigitalInput {
|
||||
DigitalInput::Keyboard(KeyboardInput { scancode, modifiers: ModifiersState {
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
alt: false,
|
||||
logo: false
|
||||
} })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
pub struct KeyboardInput {
|
||||
scancode: ScanCode,
|
||||
|
||||
28
src/main.rs
28
src/main.rs
@@ -7,7 +7,7 @@ use crate::input::{InputState, VirtualButton, DigitalInput, VirtualAxis, AxisInp
|
||||
mod vulkan;
|
||||
mod input;
|
||||
|
||||
const PRINT_KEYBOARD_INPUT: bool = false;
|
||||
const PRINT_KEYBOARD_INPUT: bool = true;
|
||||
|
||||
struct TestGame {
|
||||
input: InputState,
|
||||
@@ -16,6 +16,18 @@ struct TestGame {
|
||||
|
||||
impl Game for TestGame {
|
||||
fn update(self: &mut Self, game_data: &mut GameData) {
|
||||
// User interaction
|
||||
if self.input.button_down("QUIT") {
|
||||
game_data.shutdown = true;
|
||||
}
|
||||
|
||||
if self.input.button_just_pressed("RELOAD_SHADERS") {
|
||||
game_data.recreate_pipeline = true;
|
||||
}
|
||||
|
||||
self.cam_pos.x += self.input.get_axis("FORWARD");
|
||||
|
||||
// Move game objects
|
||||
game_data.push_constants.time = game_data.start_time.elapsed().unwrap().as_millis() as f32 / 1000.0;
|
||||
|
||||
let model = Matrix4::from_angle_z(Rad::from(Deg(game_data.push_constants.time * 100.0)));
|
||||
@@ -40,6 +52,8 @@ impl Game for TestGame {
|
||||
game_data.push_constants.projection = proj.into();
|
||||
game_data.line_push_constants.view = view.into();
|
||||
game_data.line_push_constants.projection = proj.into();
|
||||
|
||||
self.input.frame_end();
|
||||
}
|
||||
|
||||
fn on_window_event(self: &mut Self, game_data: &mut GameData, event: &Event) {
|
||||
@@ -59,13 +73,6 @@ impl Game for TestGame {
|
||||
}
|
||||
|
||||
self.input.on_keyboard_event(input.state, input.scancode, input.modifiers);
|
||||
|
||||
if input.state == ElementState::Released && input.modifiers.ctrl && input.scancode == 19 {
|
||||
game_data.recreate_pipeline = true;
|
||||
}
|
||||
if self.input.button_down("QUIT") {
|
||||
game_data.shutdown = true;
|
||||
}
|
||||
},
|
||||
// Event::WindowEvent { event: WindowEvent::MouseInput { device_id, state, button, modifiers }, .. } => {
|
||||
//
|
||||
@@ -77,13 +84,10 @@ impl Game for TestGame {
|
||||
|
||||
fn main() {
|
||||
let mut game = TestGame {
|
||||
input: InputState::new(),
|
||||
input: InputState::new("config/input.toml"),
|
||||
cam_pos: Point3::new(2.0, 2.0, 2.0)
|
||||
};
|
||||
|
||||
game.input.virtual_buttons.insert("QUIT".to_string(), VirtualButton { digital_inputs: vec![DigitalInput::simple_key(1)] });
|
||||
game.input.virtual_axes.insert("FORWARD_CAM_AXIS".to_string(), VirtualAxis { analog_inputs: vec![AxisInput::Digital(DigitalInput::simple_key(87), DigitalInput::simple_key(83))] });
|
||||
|
||||
vulkan::init(
|
||||
"models/iski51.obj",
|
||||
(-10..10)
|
||||
|
||||
Reference in New Issue
Block a user