better inputs, log config
This commit is contained in:
1
config/log.toml
Normal file
1
config/log.toml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
input = false
|
||||||
14
models/iski51.mtl
Normal file
14
models/iski51.mtl
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Blender MTL File: 'iski51.blend'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl FullBody
|
||||||
|
Ns 240.249985
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.086497 0.014334 0.005447
|
||||||
|
Ks 0.433333 0.433333 0.433333
|
||||||
|
Ke 0.0 0.0 0.0
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd D:\\Nextcloud\\Models\\Iski\\substance\\export\\iski-full_FullBody_BaseColor.jpg
|
||||||
|
map_Ns D:\\Nextcloud\\Models\\Iski\\substance\\export\\iski-full_FullBody_Roughness.jpg
|
||||||
289333
models/iski51.obj
Normal file
289333
models/iski51.obj
Normal file
File diff suppressed because it is too large
Load Diff
14
src/config.rs
Normal file
14
src/config.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use serde_derive::{Serialize, Deserialize};
|
||||||
|
use toml;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct LogConfig {
|
||||||
|
pub input: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogConfig {
|
||||||
|
pub fn from_file(path: &str) -> Self {
|
||||||
|
toml::from_slice(&fs::read(path).expect("Failed to read log config!")).expect("Failed to parse log config!")
|
||||||
|
}
|
||||||
|
}
|
||||||
111
src/input.rs
111
src/input.rs
@@ -1,5 +1,6 @@
|
|||||||
use winit::{ScanCode, ModifiersState, MouseButton, ElementState};
|
use winit::{ScanCode, ModifiersState, MouseButton, ElementState};
|
||||||
use std::collections::{HashMap};
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use toml;
|
use toml;
|
||||||
@@ -11,13 +12,20 @@ pub struct VirtualButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct VirtualAxis {
|
pub struct VirtualAxis {
|
||||||
pub analog_inputs: Vec<AxisInput>
|
pub axis_inputs: Vec<AxisInput>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InputState {
|
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>,
|
||||||
pressed_digital: HashMap<DigitalInput, (bool, bool)>
|
input_events: HashSet<DigitalInputEvent>,
|
||||||
|
pressed_buttons: HashSet<ScanCode>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum DigitalInputEvent {
|
||||||
|
Pressed(DigitalInput),
|
||||||
|
Released(DigitalInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@@ -42,14 +50,14 @@ struct InputConfigAxis {
|
|||||||
ctrl_negative: Option<bool>
|
ctrl_negative: Option<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
type InputHashmapEntry<'a> = (&'a DigitalInput, (bool, 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(), pressed_digital: HashMap::new() };
|
let mut state = InputState { virtual_buttons: HashMap::new(), virtual_axes: HashMap::new(),
|
||||||
|
input_events: HashSet::new(), pressed_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!");
|
||||||
|
|
||||||
let buttons = config.button.iter().for_each(|bn| {
|
config.button.iter().for_each(|bn| {
|
||||||
let modifiers = ModifiersState {
|
let modifiers = ModifiersState {
|
||||||
shift: false,
|
shift: false,
|
||||||
ctrl: bn.ctrl.is_some(),
|
ctrl: bn.ctrl.is_some(),
|
||||||
@@ -64,7 +72,7 @@ impl InputState {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let axes = config.axis.iter().for_each(|a| {
|
config.axis.iter().for_each(|a| {
|
||||||
let modifiers_positive = ModifiersState {
|
let modifiers_positive = ModifiersState {
|
||||||
shift: false,
|
shift: false,
|
||||||
ctrl: a.ctrl_positive.is_some(),
|
ctrl: a.ctrl_positive.is_some(),
|
||||||
@@ -82,9 +90,9 @@ impl InputState {
|
|||||||
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_negative, modifiers: modifiers_negative })
|
DigitalInput::Keyboard(KeyboardInput { scancode: a.scancode_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.analog_inputs.push(axis);
|
virtual_axis.axis_inputs.push(axis);
|
||||||
} else {
|
} else {
|
||||||
state.virtual_axes.insert(a.name.clone(), VirtualAxis { analog_inputs: vec![axis] });
|
state.virtual_axes.insert(a.name.clone(), VirtualAxis { axis_inputs: vec![axis] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -92,39 +100,59 @@ impl InputState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn button_down(self: &Self, button_code: &str) -> bool {
|
pub fn button_down(self: &Self, button_code: &str) -> bool {
|
||||||
if let Some(input) = self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
self.pressed_digital.iter().any(|(registered_input, _)| input.digital_inputs.iter().any(|digital_input| digital_input == registered_input))
|
Some(virtual_button) => {
|
||||||
} else {
|
virtual_button.digital_inputs.iter().any(|vi| self.digital_input_pressed(vi))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
assert!(false, format!("Button {:?} not found!", button_code));
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn button_just_pressed(self: &Self, button_code: &str) -> bool {
|
pub fn button_just_pressed(self: &Self, button_code: &str) -> bool {
|
||||||
if let Some(input) = self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
self.pressed_digital.iter()
|
Some(virtual_button) => {
|
||||||
.filter(|(_, (pressed, _))| *pressed)
|
self.input_events.iter().any(|input_event| {
|
||||||
.any(|(registered_input, _)| input.digital_inputs.iter().any(|digital_input| digital_input == registered_input))
|
if let DigitalInputEvent::Pressed(digital_input) = input_event {
|
||||||
|
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
assert!(false, format!("Button {:?} not found!", button_code));
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn button_just_released(self: &Self, button_code: &str) -> bool {
|
pub fn button_just_released(self: &Self, button_code: &str) -> bool {
|
||||||
if let Some(input) = self.virtual_buttons.get(button_code) {
|
match self.virtual_buttons.get(button_code) {
|
||||||
self.pressed_digital.iter()
|
Some(virtual_button) => {
|
||||||
.filter(|(_, (_, released))| *released)
|
self.input_events.iter().any(|input_event| {
|
||||||
.any(|(registered_input, _)| input.digital_inputs.iter().any(|digital_input| digital_input == registered_input))
|
if let DigitalInputEvent::Released(digital_input) = input_event {
|
||||||
|
virtual_button.digital_inputs.iter().any(|virtual_button_input| virtual_button_input == digital_input)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
assert!(false, format!("Button {:?} not found!", button_code));
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_axis(self: &Self, axis_code: &str) -> f32 {
|
pub fn get_axis(self: &Self, axis_code: &str) -> f32 {
|
||||||
if let Some(axis) = self.virtual_axes.get(axis_code) {
|
if let Some(axis) = self.virtual_axes.get(axis_code) {
|
||||||
axis.analog_inputs.iter().fold(0.0, |fold, item| {
|
axis.axis_inputs.iter().fold(0.0, |fold, item| {
|
||||||
let val = match item {
|
let val = match item {
|
||||||
AxisInput::Analog(_) => 0.0,
|
AxisInput::Analog(_) => 0.0, //TODO
|
||||||
AxisInput::Digital(positive_button, negative_button) => self.button_to_float(positive_button) - self.button_to_float(negative_button),
|
AxisInput::Digital(positive_button, negative_button) => self.digital_input_to_float(positive_button) - self.digital_input_to_float(negative_button),
|
||||||
};
|
};
|
||||||
if f32::abs(val) > fold {
|
if f32::abs(val) > fold {
|
||||||
val
|
val
|
||||||
@@ -138,32 +166,43 @@ impl InputState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button_to_float(self: &Self, input: &DigitalInput) -> f32 {
|
pub fn digital_input_pressed(self: &Self, digital_input: &DigitalInput) -> bool {
|
||||||
if self.pressed_digital.iter().any(|(registered_input, _)| input == registered_input) {
|
match digital_input {
|
||||||
1.0
|
DigitalInput::Keyboard(keyboard_input) =>
|
||||||
} else {
|
self.pressed_buttons.contains(&keyboard_input.scancode)
|
||||||
0.0
|
&& self.modifiers_are_pressed(keyboard_input.modifiers),
|
||||||
|
DigitalInput::Mouse(_) => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
pub fn on_keyboard_event(self: &mut Self, state: ElementState, scancode: ScanCode, modifiers: ModifiersState) {
|
||||||
|
let input = DigitalInput::Keyboard(KeyboardInput { scancode, modifiers });
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
ElementState::Pressed => {
|
ElementState::Pressed => {
|
||||||
self.pressed_digital.insert(DigitalInput::Keyboard(KeyboardInput { scancode, modifiers }), (true, false));
|
self.input_events.insert(DigitalInputEvent::Pressed(input));
|
||||||
|
self.pressed_buttons.insert(scancode);
|
||||||
},
|
},
|
||||||
ElementState::Released => {
|
ElementState::Released => {
|
||||||
if let Some((_, recent_release)) = self.pressed_digital.get_mut(&DigitalInput::Keyboard(KeyboardInput { scancode, modifiers })) {
|
self.input_events.insert(DigitalInputEvent::Released(input));
|
||||||
*recent_release = true;
|
self.pressed_buttons.remove(&scancode);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_end(self: &mut Self) {
|
pub fn frame_end(self: &mut Self) {
|
||||||
self.pressed_digital.iter_mut().for_each(|(_, (recent_press, _))| {
|
self.input_events.clear();
|
||||||
if *recent_press { *recent_press = false }
|
|
||||||
});
|
|
||||||
self.pressed_digital.retain(|_, (recent_press, recent_release)| *recent_release == false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
src/main.rs
24
src/main.rs
@@ -1,23 +1,26 @@
|
|||||||
use crate::vulkan::{GameData, Game, LinePoint};
|
use winit::{Event, WindowEvent};
|
||||||
use winit::{Event, WindowEvent, ElementState};
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use cgmath::{Matrix4, Rad, Point3, Vector3, Deg};
|
use cgmath::{Matrix4, Rad, Point3, Vector3, Deg};
|
||||||
use crate::input::{InputState, VirtualButton, DigitalInput, VirtualAxis, AxisInput};
|
|
||||||
|
|
||||||
mod vulkan;
|
mod vulkan;
|
||||||
mod input;
|
use crate::vulkan::{GameData, Game, LinePoint};
|
||||||
|
|
||||||
const PRINT_KEYBOARD_INPUT: bool = true;
|
mod input;
|
||||||
|
use crate::input::{InputState};
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
use crate::config::LogConfig;
|
||||||
|
|
||||||
struct TestGame {
|
struct TestGame {
|
||||||
input: InputState,
|
input: InputState,
|
||||||
cam_pos: Point3<f32>
|
cam_pos: Point3<f32>,
|
||||||
|
log_config: LogConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game for TestGame {
|
impl Game for TestGame {
|
||||||
fn update(self: &mut Self, game_data: &mut GameData) {
|
fn update(self: &mut Self, game_data: &mut GameData) {
|
||||||
// User interaction
|
// User interaction
|
||||||
if self.input.button_down("QUIT") {
|
if self.input.button_just_released("QUIT") {
|
||||||
game_data.shutdown = true;
|
game_data.shutdown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,10 +59,10 @@ impl Game for TestGame {
|
|||||||
self.input.frame_end();
|
self.input.frame_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_window_event(self: &mut Self, game_data: &mut GameData, event: &Event) {
|
fn on_window_event(self: &mut Self, event: &Event) {
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
|
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
|
||||||
if PRINT_KEYBOARD_INPUT {
|
if self.log_config.input {
|
||||||
let mods = String::from_iter(
|
let mods = String::from_iter(
|
||||||
vec!["shift", "ctrl", "alt", "logo"].iter()
|
vec!["shift", "ctrl", "alt", "logo"].iter()
|
||||||
.zip(vec![input.modifiers.shift, input.modifiers.ctrl, input.modifiers.alt, input.modifiers.logo])
|
.zip(vec![input.modifiers.shift, input.modifiers.ctrl, input.modifiers.alt, input.modifiers.logo])
|
||||||
@@ -85,7 +88,8 @@ impl Game for TestGame {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut game = TestGame {
|
let mut game = TestGame {
|
||||||
input: InputState::new("config/input.toml"),
|
input: InputState::new("config/input.toml"),
|
||||||
cam_pos: Point3::new(2.0, 2.0, 2.0)
|
cam_pos: Point3::new(2.0, 2.0, 2.0),
|
||||||
|
log_config: LogConfig::from_file("config/log.toml"),
|
||||||
};
|
};
|
||||||
|
|
||||||
vulkan::init(
|
vulkan::init(
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ pub trait Game {
|
|||||||
fn update(self: &mut Self, game_data: &mut GameData);
|
fn update(self: &mut Self, game_data: &mut GameData);
|
||||||
|
|
||||||
/// Returns true if event should be ignored by the vulkan handler
|
/// Returns true if event should be ignored by the vulkan handler
|
||||||
fn on_window_event(self: &mut Self, game_data: &mut GameData, event: &Event);
|
fn on_window_event(self: &mut Self, event: &Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GameData {
|
pub struct GameData {
|
||||||
@@ -365,7 +365,7 @@ pub fn init(mesh_path: &str, line_vertices: Vec<LinePoint>, game: &mut dyn Game)
|
|||||||
// wait would happen. Blocking may be the desired behavior, but if you don't want to
|
// wait would happen. Blocking may be the desired behavior, but if you don't want to
|
||||||
// block you should spawn a separate thread dedicated to submissions.
|
// block you should spawn a separate thread dedicated to submissions.
|
||||||
events_loop.poll_events(|ev| {
|
events_loop.poll_events(|ev| {
|
||||||
game.on_window_event(&mut data, &ev);
|
game.on_window_event(&ev);
|
||||||
match ev {
|
match ev {
|
||||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => data.shutdown = true,
|
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => data.shutdown = true,
|
||||||
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => recreate_swapchain = true,
|
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => recreate_swapchain = true,
|
||||||
|
|||||||
Reference in New Issue
Block a user