parse input from file

This commit is contained in:
2019-07-27 05:46:42 +02:00
parent de5fa84ac7
commit 39b136d799
5 changed files with 151 additions and 32 deletions

View File

@@ -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
View 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

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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)