summaryrefslogtreecommitdiff
path: root/src/input.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/input.rs')
-rw-r--r--src/input.rs159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/input.rs b/src/input.rs
new file mode 100644
index 0000000..dd49cd0
--- /dev/null
+++ b/src/input.rs
@@ -0,0 +1,159 @@
+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
+ Up,
+ Left,
+ Down,
+ Right,
+
+ // sim management
+ Pause,
+ Step,
+ ClearGrid,
+ ClearEntities,
+ ClearParticles,
+
+ // placeholder actions
+ Action1,
+ Action2,
+ Action3,
+ Action4,
+ Action5,
+ Action6,
+}
+
+const INPUT_VAR_LEN: usize = 17;
+
+const KEYMAP: [(KeyCode, Input); 15] = [
+ (KeyCode::KeyW, Input::Up),
+ (KeyCode::KeyA, Input::Left),
+ (KeyCode::KeyS, Input::Down),
+ (KeyCode::KeyD, Input::Right),
+ (KeyCode::Space, Input::Pause),
+ (KeyCode::KeyX, Input::Step),
+ (KeyCode::KeyC, Input::ClearGrid),
+ (KeyCode::KeyV, Input::ClearEntities),
+ (KeyCode::KeyP, Input::ClearParticles),
+ (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_x, wp_y) =
+ camera.screen_position_to_world(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 = Vec2::new(wp_x, wp_y);
+ 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],
+ }
+ }
+}