summaryrefslogtreecommitdiff
path: root/engine/src/windowing/keyboard.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-08-14 20:20:41 +0200
committerHampusM <hampus@hampusmat.com>2026-08-15 00:43:37 +0200
commit1ac2ff603b1c843541234648ab801e83b2947444 (patch)
treef8080920cd6c02de07b9f0314e18f473ad620adc /engine/src/windowing/keyboard.rs
parenta61463b205f3c3aaa9174cdae3704a8a53542aea (diff)
perf(engine): store keyboard key states & state updates as bitsHEADmaster
Diffstat (limited to 'engine/src/windowing/keyboard.rs')
-rw-r--r--engine/src/windowing/keyboard.rs75
1 files changed, 42 insertions, 33 deletions
diff --git a/engine/src/windowing/keyboard.rs b/engine/src/windowing/keyboard.rs
index 4515d8a..8e0cfbe 100644
--- a/engine/src/windowing/keyboard.rs
+++ b/engine/src/windowing/keyboard.rs
@@ -1,11 +1,12 @@
-use std::collections::HashMap;
+use util_macros::VariantArr;
use crate::ecs::Sole;
+use crate::util::BitArray;
#[derive(Debug, Default, Sole)]
pub struct Keyboard
{
- map: HashMap<Key, KeyData>,
+ keys: BitArray<{ (Key::KEYS.len() * BITS_PER_KEY).div_ceil(8) }, BITS_PER_KEY>,
text_keys: String,
}
@@ -43,33 +44,49 @@ impl Keyboard
/// different state than they had the previous frame.
pub fn new_key_states(&self) -> impl Iterator<Item = (Key, KeyState)> + use<'_>
{
- self.map.iter().filter_map(|(key, key_data)| {
- if key_data.curr_state == key_data.previous_state {
+ self.keys.iter_occupied().filter_map(|(key_index, bits)| {
+ if bits == KEY_CURR_PRESSED_BITS | KEY_PREV_PRESSED_BITS {
return None;
}
- Some((*key, key_data.curr_state))
+ let key = Key::KEYS[key_index];
+
+ let curr_state = match bits & KEY_CURR_PRESSED_BITS {
+ KEY_CURR_PRESSED_BITS => KeyState::Pressed,
+ 0 => KeyState::Released,
+ _ => unreachable!(),
+ };
+
+ Some((key, curr_state))
})
}
#[must_use]
pub fn get_key_state(&self, key: Key) -> KeyState
{
- let Some(key_data) = self.map.get(&key) else {
- return KeyState::Released;
+ let bits = self.keys.get(key as usize);
+
+ let state = match bits & KEY_CURR_PRESSED_BITS {
+ KEY_CURR_PRESSED_BITS => KeyState::Pressed,
+ 0 => KeyState::Released,
+ _ => unreachable!(),
};
- key_data.curr_state
+ state
}
#[must_use]
pub fn get_prev_key_state(&self, key: Key) -> KeyState
{
- let Some(key_data) = self.map.get(&key) else {
- return KeyState::Released;
+ let bits = self.keys.get(key as usize);
+
+ let state = match bits & KEY_PREV_PRESSED_BITS {
+ KEY_PREV_PRESSED_BITS => KeyState::Pressed,
+ 0 => KeyState::Released,
+ _ => unreachable!(),
};
- key_data.previous_state
+ state
}
pub fn text_keys(&self) -> &str
@@ -79,15 +96,19 @@ impl Keyboard
pub fn set_key_state(&mut self, key: Key, key_state: KeyState)
{
- let key_data = self.map.entry(key).or_default();
-
- key_data.curr_state = key_state;
+ self.keys.set(
+ key as usize,
+ match key_state {
+ KeyState::Pressed => KEY_CURR_PRESSED_BITS,
+ KeyState::Released => 0,
+ },
+ );
}
pub fn make_key_states_previous(&mut self)
{
- for key_data in self.map.values_mut() {
- key_data.previous_state = key_data.curr_state;
+ for byte in self.keys.bytes_mut() {
+ *byte = (*byte >> 1) & 0b01010101 | *byte & 0b10101010;
}
}
@@ -98,7 +119,8 @@ impl Keyboard
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, VariantArr)]
+#[variant_arr(name = KEYS)]
#[non_exhaustive]
pub enum Key
{
@@ -797,20 +819,7 @@ impl From<winit::event::ElementState> for KeyState
}
}
-#[derive(Debug)]
-struct KeyData
-{
- curr_state: KeyState,
- previous_state: KeyState,
-}
+const BITS_PER_KEY: usize = 2;
-impl Default for KeyData
-{
- fn default() -> Self
- {
- KeyData {
- curr_state: KeyState::Released,
- previous_state: KeyState::Released,
- }
- }
-}
+const KEY_CURR_PRESSED_BITS: u8 = 0b10;
+const KEY_PREV_PRESSED_BITS: u8 = 0b01;