use bitflags::bitflags;
use crate::Context;
pub use miniquad::KeyCode;
use std::collections::HashSet;
#[derive(Clone, Debug)]
pub struct KeyboardContext {
active_modifiers: KeyMods,
pressed_keys_set: HashSet<KeyCode>,
last_pressed: Option<KeyCode>,
current_pressed: Option<KeyCode>,
}
impl KeyboardContext {
pub(crate) fn new() -> Self {
Self {
active_modifiers: KeyMods::empty(),
pressed_keys_set: HashSet::with_capacity(256),
last_pressed: None,
current_pressed: None,
}
}
pub(crate) fn set_key(&mut self, key: KeyCode, pressed: bool) {
if pressed {
let _ = self.pressed_keys_set.insert(key);
self.last_pressed = self.current_pressed;
self.current_pressed = Some(key);
} else {
let _ = self.pressed_keys_set.remove(&key);
self.current_pressed = None;
}
self.set_key_modifier(key, pressed);
}
fn set_key_modifier(&mut self, key: KeyCode, pressed: bool) {
if pressed {
match key {
KeyCode::LeftShift | KeyCode::RightShift => self.active_modifiers |= KeyMods::SHIFT,
KeyCode::LeftControl | KeyCode::RightControl => {
self.active_modifiers |= KeyMods::CTRL
}
KeyCode::LeftAlt | KeyCode::RightAlt => self.active_modifiers |= KeyMods::ALT,
KeyCode::LeftSuper | KeyCode::RightSuper => self.active_modifiers |= KeyMods::LOGO,
_ => (),
}
} else {
match key {
KeyCode::LeftShift | KeyCode::RightShift => self.active_modifiers -= KeyMods::SHIFT,
KeyCode::LeftControl | KeyCode::RightControl => {
self.active_modifiers -= KeyMods::CTRL
}
KeyCode::LeftAlt | KeyCode::RightAlt => self.active_modifiers -= KeyMods::ALT,
KeyCode::LeftSuper | KeyCode::RightSuper => self.active_modifiers -= KeyMods::LOGO,
_ => (),
}
}
}
pub(crate) fn is_key_pressed(&self, key: KeyCode) -> bool {
self.pressed_keys_set.contains(&key)
}
pub(crate) fn is_key_repeated(&self) -> bool {
if self.last_pressed.is_some() {
self.last_pressed == self.current_pressed
} else {
false
}
}
pub(crate) fn pressed_keys(&self) -> &HashSet<KeyCode> {
&self.pressed_keys_set
}
pub(crate) fn active_mods(&self) -> KeyMods {
self.active_modifiers
}
}
impl Default for KeyboardContext {
fn default() -> Self {
Self::new()
}
}
pub fn is_key_pressed(ctx: &Context, key: KeyCode) -> bool {
ctx.keyboard_context.is_key_pressed(key)
}
pub fn is_key_repeated(ctx: &Context) -> bool {
ctx.keyboard_context.is_key_repeated()
}
pub fn pressed_keys(ctx: &Context) -> &HashSet<KeyCode> {
ctx.keyboard_context.pressed_keys()
}
pub fn active_mods(ctx: &Context) -> KeyMods {
ctx.keyboard_context.active_mods()
}
pub fn is_mod_active(ctx: &Context, keymods: KeyMods) -> bool {
ctx.keyboard_context.active_mods().contains(keymods)
}
bitflags! {
#[derive(Default)]
pub struct KeyMods: u8 {
const NONE = 0b0000_0000;
const SHIFT = 0b0000_0001;
const CTRL = 0b0000_0010;
const ALT = 0b0000_0100;
const LOGO = 0b0000_1000;
}
}
impl From<miniquad::KeyMods> for KeyMods {
fn from(quad_mods: miniquad::KeyMods) -> Self {
let mut keymods = KeyMods::NONE;
if quad_mods.shift {
keymods |= KeyMods::SHIFT;
}
if quad_mods.ctrl {
keymods |= KeyMods::CTRL;
}
if quad_mods.alt {
keymods |= KeyMods::ALT;
}
if quad_mods.logo {
keymods |= KeyMods::LOGO;
}
keymods
}
}