Add raidillon_input and FPSCameraController
This commit is contained in:
parent
d0440f3da3
commit
97195fbd05
7 changed files with 268 additions and 0 deletions
8
raidillon_input/Cargo.toml
Normal file
8
raidillon_input/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "raidillon_input"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
winit = "0.30"
|
||||
glam = "0.30.4"
|
||||
73
raidillon_input/src/camera.rs
Normal file
73
raidillon_input/src/camera.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
use glam::Vec3;
|
||||
use std::hash::Hash;
|
||||
|
||||
use super::Input;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FPSCameraController {
|
||||
pub position: Vec3,
|
||||
yaw: f32,
|
||||
pitch: f32,
|
||||
pub speed: f32,
|
||||
pub sensitivity: f32,
|
||||
}
|
||||
|
||||
impl FPSCameraController {
|
||||
pub fn new(position: Vec3) -> Self {
|
||||
Self {
|
||||
position,
|
||||
yaw: -90.0,
|
||||
pitch: 0.0,
|
||||
speed: 3.0,
|
||||
sensitivity: 0.1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update<A>(&mut self,
|
||||
input: &Input<A>,
|
||||
dt: f32,
|
||||
mouse_enabled: bool,
|
||||
actions: (A, A, A, A))
|
||||
where
|
||||
A: Copy + Eq + Hash,
|
||||
{
|
||||
let (forward, backward, left, right) = actions;
|
||||
|
||||
// Mouse look
|
||||
if mouse_enabled {
|
||||
let (dx, dy) = input.mouse_delta();
|
||||
self.yaw += dx as f32 * self.sensitivity;
|
||||
self.pitch -= dy as f32 * self.sensitivity;
|
||||
self.pitch = self.pitch.clamp(-89.0, 89.0);
|
||||
}
|
||||
|
||||
// Movement
|
||||
let front = self.front();
|
||||
let right_vec = front.cross(Vec3::Y).normalize();
|
||||
let frame_speed = self.speed * dt;
|
||||
|
||||
if input.action_held(forward) {
|
||||
self.position += front * frame_speed;
|
||||
}
|
||||
if input.action_held(backward) {
|
||||
self.position -= front * frame_speed;
|
||||
}
|
||||
if input.action_held(left) {
|
||||
self.position -= right_vec * frame_speed;
|
||||
}
|
||||
if input.action_held(right) {
|
||||
self.position += right_vec * frame_speed;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn front(&self) -> Vec3 {
|
||||
let yaw_rad = self.yaw.to_radians();
|
||||
let pitch_rad = self.pitch.to_radians();
|
||||
Vec3::new(
|
||||
yaw_rad.cos() * pitch_rad.cos(),
|
||||
pitch_rad.sin(),
|
||||
yaw_rad.sin() * pitch_rad.cos(),
|
||||
)
|
||||
.normalize()
|
||||
}
|
||||
}
|
||||
107
raidillon_input/src/lib.rs
Normal file
107
raidillon_input/src/lib.rs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::hash::Hash;
|
||||
|
||||
use winit::event::{DeviceEvent, ElementState, Event, WindowEvent};
|
||||
use winit::keyboard::{KeyCode, PhysicalKey};
|
||||
|
||||
pub mod camera;
|
||||
pub use camera::FPSCameraController;
|
||||
|
||||
pub struct Input<A: Copy + Eq + Hash> {
|
||||
pressed_keys: HashSet<KeyCode>,
|
||||
pressed_once: HashSet<KeyCode>,
|
||||
|
||||
keymap: HashMap<KeyCode, A>,
|
||||
pressed_actions: HashSet<A>,
|
||||
pressed_actions_once: HashSet<A>,
|
||||
|
||||
mouse_delta: (f64, f64),
|
||||
}
|
||||
|
||||
impl<A: Copy + Eq + Hash> Input<A> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pressed_keys: HashSet::new(),
|
||||
pressed_once: HashSet::new(),
|
||||
keymap: HashMap::new(),
|
||||
pressed_actions: HashSet::new(),
|
||||
pressed_actions_once: HashSet::new(),
|
||||
mouse_delta: (0.0, 0.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_key(&mut self, key: KeyCode, action: A) {
|
||||
self.keymap.insert(key, action);
|
||||
}
|
||||
|
||||
pub fn clear_keymap(&mut self) {
|
||||
self.keymap.clear();
|
||||
self.pressed_actions.clear();
|
||||
self.pressed_actions_once.clear();
|
||||
}
|
||||
|
||||
pub fn handle_event<T>(&mut self, event: &Event<T>) {
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
let key_code = match event.physical_key {
|
||||
PhysicalKey::Code(code) => code,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
match event.state {
|
||||
ElementState::Pressed => {
|
||||
self.pressed_keys.insert(key_code);
|
||||
self.pressed_once.insert(key_code);
|
||||
|
||||
if let Some(&action) = self.keymap.get(&key_code) {
|
||||
self.pressed_actions.insert(action);
|
||||
self.pressed_actions_once.insert(action);
|
||||
}
|
||||
}
|
||||
ElementState::Released => {
|
||||
self.pressed_keys.remove(&key_code);
|
||||
|
||||
if let Some(&action) = self.keymap.get(&key_code) {
|
||||
self.pressed_actions.remove(&action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Event::DeviceEvent { event, .. } => match event {
|
||||
DeviceEvent::MouseMotion { delta } => {
|
||||
self.mouse_delta.0 += delta.0;
|
||||
self.mouse_delta.1 += delta.1;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_held(&self, key: KeyCode) -> bool {
|
||||
self.pressed_keys.contains(&key)
|
||||
}
|
||||
pub fn key_pressed(&self, key: KeyCode) -> bool {
|
||||
self.pressed_once.contains(&key)
|
||||
}
|
||||
|
||||
pub fn action_held(&self, action: A) -> bool {
|
||||
self.pressed_actions.contains(&action)
|
||||
}
|
||||
pub fn action_pressed(&self, action: A) -> bool {
|
||||
self.pressed_actions_once.contains(&action)
|
||||
}
|
||||
|
||||
pub fn mouse_delta(&self) -> (f64, f64) {
|
||||
self.mouse_delta
|
||||
}
|
||||
|
||||
pub fn end_frame(&mut self) {
|
||||
self.mouse_delta = (0.0, 0.0);
|
||||
self.pressed_once.clear();
|
||||
self.pressed_actions_once.clear();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue