wormhole/
input.rs

1// Input System - Tracks keyboard and mouse state
2
3use std::collections::HashSet;
4use winit::keyboard::{KeyCode, PhysicalKey};
5use winit::event::MouseButton;
6
7pub struct InputState {
8    // Keyboard state
9    keys_pressed: HashSet<KeyCode>,
10    keys_just_pressed: HashSet<KeyCode>,
11    keys_just_released: HashSet<KeyCode>,
12    
13    // Mouse state
14    mouse_position: (f32, f32),
15    mouse_delta: (f32, f32),  // Change in mouse position this frame
16    mouse_buttons_pressed: HashSet<MouseButton>,
17    mouse_buttons_just_pressed: HashSet<MouseButton>,
18    mouse_buttons_just_released: HashSet<MouseButton>,
19    mouse_scroll_delta: (f32, f32),
20    
21    // Frame tracking
22    frame_ended: bool,
23}
24
25impl InputState {
26    pub fn new() -> Self {
27        Self {
28            keys_pressed: HashSet::new(),
29            keys_just_pressed: HashSet::new(),
30            keys_just_released: HashSet::new(),
31            mouse_position: (0.0, 0.0),
32            mouse_delta: (0.0, 0.0),
33            mouse_buttons_pressed: HashSet::new(),
34            mouse_buttons_just_pressed: HashSet::new(),
35            mouse_buttons_just_released: HashSet::new(),
36            mouse_scroll_delta: (0.0, 0.0),
37            frame_ended: false,
38        }
39    }
40
41    /// Call at the start of each frame to clear "just pressed/released" states
42    pub fn begin_frame(&mut self) {
43        self.keys_just_pressed.clear();
44        self.keys_just_released.clear();
45        self.mouse_buttons_just_pressed.clear();
46        self.mouse_buttons_just_released.clear();
47        self.mouse_scroll_delta = (0.0, 0.0);
48        self.mouse_delta = (0.0, 0.0);  // Clear mouse delta at start of frame
49        self.frame_ended = false;
50    }
51
52    /// Call at the end of each frame
53    pub fn end_frame(&mut self) {
54        self.frame_ended = true;
55    }
56
57    /// Handle key pressed event
58    pub fn on_key_pressed(&mut self, key_code: KeyCode) {
59        if self.keys_pressed.insert(key_code) {
60            // Only add to just_pressed if it wasn't already pressed
61            self.keys_just_pressed.insert(key_code);
62        }
63    }
64
65    /// Handle key released event
66    pub fn on_key_released(&mut self, key_code: KeyCode) {
67        if self.keys_pressed.remove(&key_code) {
68            self.keys_just_released.insert(key_code);
69        }
70    }
71
72    /// Handle mouse button pressed
73    pub fn on_mouse_button_pressed(&mut self, button: MouseButton) {
74        if self.mouse_buttons_pressed.insert(button) {
75            self.mouse_buttons_just_pressed.insert(button);
76        }
77    }
78
79    /// Handle mouse button released
80    pub fn on_mouse_button_released(&mut self, button: MouseButton) {
81        if self.mouse_buttons_pressed.remove(&button) {
82            self.mouse_buttons_just_released.insert(button);
83        }
84    }
85
86    /// Handle mouse cursor moved
87    pub fn on_cursor_moved(&mut self, x: f32, y: f32) {
88        // Calculate delta from current position (which is last frame's position)
89        self.mouse_delta = (x - self.mouse_position.0, y - self.mouse_position.1);
90        self.mouse_position = (x, y);
91    }
92
93    /// Handle mouse wheel/scroll
94    pub fn on_mouse_wheel(&mut self, delta_x: f32, delta_y: f32) {
95        self.mouse_scroll_delta = (delta_x, delta_y);
96    }
97
98    // Query functions
99    
100    /// Check if a key is currently pressed
101    pub fn is_key_pressed(&self, key_code: KeyCode) -> bool {
102        self.keys_pressed.contains(&key_code)
103    }
104
105    /// Check if a key was just pressed this frame
106    pub fn is_key_just_pressed(&self, key_code: KeyCode) -> bool {
107        self.keys_just_pressed.contains(&key_code)
108    }
109
110    /// Check if a key was just released this frame
111    pub fn is_key_just_released(&self, key_code: KeyCode) -> bool {
112        self.keys_just_released.contains(&key_code)
113    }
114
115    /// Get mouse position
116    pub fn mouse_position(&self) -> (f32, f32) {
117        self.mouse_position
118    }
119
120    /// Get mouse delta (change in position this frame)
121    pub fn mouse_delta(&self) -> (f32, f32) {
122        self.mouse_delta
123    }
124
125    /// Check if a mouse button is currently pressed
126    pub fn is_mouse_button_pressed(&self, button: MouseButton) -> bool {
127        self.mouse_buttons_pressed.contains(&button)
128    }
129
130    /// Check if a mouse button was just pressed this frame
131    pub fn is_mouse_button_just_pressed(&self, button: MouseButton) -> bool {
132        self.mouse_buttons_just_pressed.contains(&button)
133    }
134
135    /// Get mouse scroll delta for this frame
136    pub fn mouse_scroll(&self) -> (f32, f32) {
137        self.mouse_scroll_delta
138    }
139}
140
141/// Convert winit KeyCode to a simple u32 for FFI
142/// This uses the scancode as a simple identifier
143pub fn key_code_to_u32(key_code: KeyCode) -> u32 {
144    // Use the key's discriminant as a simple identifier
145    // This is a simplified approach - in production you might want a more robust mapping
146    match key_code {
147        KeyCode::ArrowUp => 1,
148        KeyCode::ArrowDown => 2,
149        KeyCode::ArrowLeft => 3,
150        KeyCode::ArrowRight => 4,
151        KeyCode::Space => 5,
152        KeyCode::Enter => 6,
153        KeyCode::Escape => 7,
154        KeyCode::KeyW => 8,
155        KeyCode::KeyA => 9,
156        KeyCode::KeyS => 10,
157        KeyCode::KeyD => 11,
158        _ => 0, // Unknown key
159    }
160}
161
162/// Convert u32 back to KeyCode for FFI queries
163pub fn u32_to_key_code(code: u32) -> Option<KeyCode> {
164    match code {
165        1 => Some(KeyCode::ArrowUp),
166        2 => Some(KeyCode::ArrowDown),
167        3 => Some(KeyCode::ArrowLeft),
168        4 => Some(KeyCode::ArrowRight),
169        5 => Some(KeyCode::Space),
170        6 => Some(KeyCode::Enter),
171        7 => Some(KeyCode::Escape),
172        8 => Some(KeyCode::KeyW),
173        9 => Some(KeyCode::KeyA),
174        10 => Some(KeyCode::KeyS),
175        11 => Some(KeyCode::KeyD),
176        _ => None,
177    }
178}