use glam::{IVec2, Vec2}; use winit::{ event::{KeyEvent, MouseButton, WindowEvent}, keyboard::{KeyCode, PhysicalKey}, }; use crate::{camera::Camera, sim::cell_manager::manager::CellManager}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Input { // movement Jump = 0, Left, Down, Right, // camera FreeCamera, CameraUp, CameraLeft, CameraDown, CameraRight, // sim management Pause, Step, ClearGrid, ClearEntities, ClearParticles, // game controls? Grenade, Tnt, // placeholder actions Action1, Action2, Action3, Action4, Action5, Action6, } const INPUT_VAR_LEN: usize = 22; const KEYMAP: [(KeyCode, Input); INPUT_VAR_LEN] = [ (KeyCode::Space, Input::Jump), (KeyCode::KeyA, Input::Left), (KeyCode::KeyS, Input::Down), (KeyCode::KeyD, Input::Right), (KeyCode::KeyZ, Input::FreeCamera), (KeyCode::ArrowUp, Input::CameraUp), (KeyCode::ArrowLeft, Input::CameraLeft), (KeyCode::ArrowDown, Input::CameraDown), (KeyCode::ArrowRight, Input::CameraRight), (KeyCode::KeyU, Input::Pause), (KeyCode::KeyX, Input::Step), (KeyCode::KeyC, Input::ClearGrid), (KeyCode::KeyV, Input::ClearEntities), (KeyCode::KeyP, Input::ClearParticles), (KeyCode::KeyG, Input::Grenade), (KeyCode::KeyT, Input::Tnt), (KeyCode::Digit1, Input::Action1), (KeyCode::Digit2, Input::Action2), (KeyCode::Digit3, Input::Action3), (KeyCode::Digit4, Input::Action4), (KeyCode::Digit5, Input::Action5), (KeyCode::Digit6, Input::Action6), ]; pub struct InputManager { pub screen_mouse_pos: Vec2, pub world_mouse_pos: Vec2, pub chunk_mouse_pos: IVec2, pub local_mouse_pos: IVec2, pub lmb_pressed: bool, pub lmb_held: bool, pub rmb_pressed: bool, pub rmb_held: bool, pressed: [bool; INPUT_VAR_LEN], held: [bool; INPUT_VAR_LEN], } impl InputManager { pub fn reset_for_frame(&mut self) { self.pressed = [false; INPUT_VAR_LEN]; self.lmb_pressed = false; self.rmb_pressed = false; } pub fn apply_event(&mut self, event: &WindowEvent, camera: &Camera) { match event { WindowEvent::KeyboardInput { event: KeyEvent { physical_key: PhysicalKey::Code(code), repeat: false, state, .. }, .. } => { if let Some(&(_, input)) = KEYMAP.iter().find(|m| m.0 == *code) { if state.is_pressed() { self.held[input as usize] = true; self.pressed[input as usize] = true; } else { self.held[input as usize] = false; } } } WindowEvent::CursorMoved { position, .. } => { let wp = camera .screen_position_to_world(Vec2::new(position.x as f32, position.y as f32)); let ((cx, cy), (lx, ly)) = CellManager::split_game_position(wp.x.round() as i32, wp.y.round() as i32); self.screen_mouse_pos = Vec2::new(position.x as f32, position.y as f32); self.world_mouse_pos = wp; self.chunk_mouse_pos = IVec2::new(cx, cy); self.local_mouse_pos = IVec2::new(lx as i32, ly as i32); } WindowEvent::MouseInput { state, button, .. } => { if *button == MouseButton::Left { if state.is_pressed() { self.lmb_pressed = true; self.lmb_held = true; } else { self.lmb_held = false; } } else if *button == MouseButton::Right { if state.is_pressed() { self.rmb_pressed = true; self.rmb_held = true; } else { self.rmb_held = false; } } } _ => {} } } pub fn pressed(&self, input: Input) -> bool { if input as usize >= INPUT_VAR_LEN { false } else { self.pressed[input as usize] } } pub fn held(&self, input: Input) -> bool { if input as usize >= INPUT_VAR_LEN { false } else { self.held[input as usize] } } pub fn new() -> Self { InputManager { screen_mouse_pos: Vec2::ZERO, world_mouse_pos: Vec2::ZERO, chunk_mouse_pos: IVec2::ZERO, local_mouse_pos: IVec2::ZERO, lmb_pressed: false, lmb_held: false, rmb_pressed: false, rmb_held: false, pressed: [false; INPUT_VAR_LEN], held: [false; INPUT_VAR_LEN], } } }