Encapsulate keyboard handling

This commit is contained in:
numzero 2024-09-23 19:31:53 +03:00
parent 69e711811b
commit df2134a8a5

View File

@ -1,4 +1,4 @@
use std::{collections::HashSet, time::Instant}; use std::time::Instant;
use glam::{mat4, vec2, vec3, vec4, Mat4, Vec3}; use glam::{mat4, vec2, vec3, vec4, Mat4, Vec3};
use glium::{ use glium::{
@ -11,7 +11,6 @@ use glium::{
DrawParameters, Program, Surface, VertexBuffer, DrawParameters, Program, Surface, VertexBuffer,
}; };
use winit::{ use winit::{
event::ElementState,
event_loop::EventLoop, event_loop::EventLoop,
keyboard::{KeyCode, PhysicalKey}, keyboard::{KeyCode, PhysicalKey},
}; };
@ -102,6 +101,42 @@ mod camctl {
} }
} }
mod keyctl {
use std::{collections::HashSet, iter::Sum};
use winit::{event::ElementState, keyboard::PhysicalKey};
pub struct Keyboard {
pressed: HashSet<PhysicalKey>,
}
impl Keyboard {
pub fn new() -> Self {
Keyboard {
pressed: Default::default(),
}
}
pub fn is_pressed(&self, key: PhysicalKey) -> bool {
self.pressed.contains(&key)
}
pub fn set_key_state(&mut self, key: PhysicalKey, state: ElementState) {
match state {
ElementState::Pressed => self.pressed.insert(key),
ElementState::Released => self.pressed.remove(&key),
};
}
pub fn control<T: Copy + Sum>(&self, keymap: &[(PhysicalKey, T)]) -> T {
keymap
.iter()
.copied()
.filter_map(|(key, ctl)| self.is_pressed(key).then_some(ctl))
.sum()
}
}
}
static KEYS_MOVE: &'static [(PhysicalKey, Vec3)] = &[ static KEYS_MOVE: &'static [(PhysicalKey, Vec3)] = &[
(PhysicalKey::Code(KeyCode::KeyW), vec3(1., 0., 0.)), (PhysicalKey::Code(KeyCode::KeyW), vec3(1., 0., 0.)),
(PhysicalKey::Code(KeyCode::KeyS), vec3(-1., 0., 0.)), (PhysicalKey::Code(KeyCode::KeyS), vec3(-1., 0., 0.)),
@ -128,14 +163,13 @@ fn main() {
.with_title("Refraction: Wireframe") .with_title("Refraction: Wireframe")
.build(&event_loop); .build(&event_loop);
let mut keys_pressed = HashSet::<PhysicalKey>::new();
let vs_src = include_str!("ray.v.glsl"); let vs_src = include_str!("ray.v.glsl");
let fs_src = include_str!("ray.f.glsl"); let fs_src = include_str!("ray.f.glsl");
let program = Program::from_source(&display, vs_src, fs_src, None).unwrap(); let program = Program::from_source(&display, vs_src, fs_src, None).unwrap();
let scene = prepare_scene(&display); let scene = prepare_scene(&display);
let mut kbd = keyctl::Keyboard::new();
let mut cam = camctl::CameraLocation::new(); let mut cam = camctl::CameraLocation::new();
let mut t1 = Instant::now(); let mut t1 = Instant::now();
@ -150,16 +184,8 @@ fn main() {
t1 = t2; t1 = t2;
dt.as_secs_f32() dt.as_secs_f32()
}; };
let v: Vec3 = KEYS_MOVE cam.move_rel(100. * dt * kbd.control(&KEYS_MOVE));
.iter() cam.rotate_rel_ypr(2. * dt * kbd.control(&KEYS_ROTATE));
.filter_map(|(key, dir)| keys_pressed.contains(key).then_some(dir))
.sum();
let vroll: Vec3 = KEYS_ROTATE
.iter()
.filter_map(|(key, dir)| keys_pressed.contains(key).then_some(dir))
.sum();
cam.move_rel(100. * dt * v);
cam.rotate_rel_ypr(2. * dt * vroll);
let size = window.inner_size(); let size = window.inner_size();
let size = vec2(size.width as f32, size.height as f32).normalize() let size = vec2(size.width as f32, size.height as f32).normalize()
@ -212,10 +238,7 @@ fn main() {
event, event,
is_synthetic: _, is_synthetic: _,
} => { } => {
match event.state { kbd.set_key_state(event.physical_key, event.state);
ElementState::Pressed => keys_pressed.insert(event.physical_key),
ElementState::Released => keys_pressed.remove(&event.physical_key),
};
} }
WindowEvent::Resized(window_size) => { WindowEvent::Resized(window_size) => {