1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent},
keyboard::{KeyCode, PhysicalKey},
};
/// A container for Window-based keyboard input events.
///
/// NOTE: Keys pressed and released during a single update (is that possible, really?) will show
/// as both released and pressed.
#[derive(Clone, Debug, Default)]
pub struct KeyBuf {
chars: Vec<char>,
held: Vec<KeyCode>,
pressed: Vec<KeyCode>,
released: Vec<KeyCode>,
}
impl KeyBuf {
/// Returns `true` if any keys have been pressed for multiple frames.
pub fn any_held(&self) -> bool {
!self.held.is_empty()
}
/// Returns `true` if any keys have been pressed since the last frame.
pub fn any_pressed(&self) -> bool {
!self.pressed.is_empty()
}
/// Returns `true` if any keys have been released since the last frame.
pub fn any_released(&self) -> bool {
!self.released.is_empty()
}
/// Returns an iterator of characters typed since the last frame.
pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars.iter().copied()
}
/// Call this before handling events.
pub fn update(&mut self) {
self.chars.clear();
self.pressed.clear();
self.released.clear();
}
/// Handles a single event.
pub fn handle_event(&mut self, event: &Event<()>) -> bool {
match event {
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
event:
KeyEvent {
physical_key: PhysicalKey::Code(key),
state,
text,
..
},
..
},
..
} => {
match state {
ElementState::Pressed => {
if let Err(idx) = self.pressed.binary_search(key) {
self.pressed.insert(idx, *key);
}
if let Err(idx) = self.held.binary_search(key) {
self.held.insert(idx, *key);
}
}
ElementState::Released => {
if let Ok(idx) = self.held.binary_search(key) {
self.held.remove(idx);
}
if let Err(idx) = self.released.binary_search(key) {
self.released.insert(idx, *key);
}
}
}
if let Some(text) = text {
self.chars.extend(text.as_str().chars());
}
true
}
_ => false,
}
}
/// Returns `true` if the given key has been pressed since the last frame or held for multiple
/// frames.
pub fn is_down(&self, key: KeyCode) -> bool {
self.is_held(key) || self.is_pressed(key)
}
/// Returns `true` if the given key has been pressed for multiple frames.
pub fn is_held(&self, key: KeyCode) -> bool {
self.held.binary_search(&key).is_ok()
}
/// Returns `true` if the given key has been pressed since the last frame.
pub fn is_pressed(&self, key: KeyCode) -> bool {
self.pressed.binary_search(&key).is_ok()
}
/// Returns `true` if the given key has been released since the last frame.
pub fn is_released(&self, key: KeyCode) -> bool {
self.released.binary_search(&key).is_ok()
}
/// Returns an iterator of keys pressed for multiple frames.
pub fn held(&self) -> impl Iterator<Item = KeyCode> + '_ {
self.held.iter().copied()
}
/// Returns an iterator of keys pressed since the last frame.
pub fn pressed(&self) -> impl Iterator<Item = KeyCode> + '_ {
self.pressed.iter().copied()
}
/// Returns an iterator of keys released since the last frame.
pub fn released(&self) -> impl Iterator<Item = KeyCode> + '_ {
self.released.iter().copied()
}
}