use std::collections::HashMap; use ecs::extension::Collector as ExtensionCollector; use ecs::sole::Single; use ecs::Sole; use crate::event::Start as StartEvent; use crate::vector::Vec2; use crate::window::{Key, KeyState, Window}; #[derive(Debug, Clone, Default, Sole)] pub struct Keys { map: HashMap, } impl Keys { #[must_use] pub fn new() -> Self { Self::default() } #[must_use] pub fn get_key_state(&self, key: Key) -> KeyState { self.map.get(&key).copied().unwrap_or(KeyState::Released) } pub fn set_key_state(&mut self, key: Key, key_state: KeyState) { if matches!(key_state, KeyState::Released) { self.map.remove(&key); return; } if matches!(key_state, KeyState::Repeat) { return; } self.map.insert(key, key_state); } #[must_use] pub fn is_anything_pressed(&self) -> bool { !self.map.is_empty() } } #[derive(Debug, Clone, Default, Sole)] pub struct Cursor { pub position: Vec2, pub has_moved: bool, } impl Cursor { #[must_use] pub fn new() -> Self { Self::default() } } /// Input extension. #[derive(Debug, Default)] pub struct Extension {} impl ecs::extension::Extension for Extension { fn collect(self, mut collector: ExtensionCollector<'_>) { collector.add_system(StartEvent, initialize); collector.add_sole(Keys::default()).ok(); collector.add_sole(Cursor::default()).ok(); } } fn initialize(keys: Single, cursor: Single, window: Single) { let keys_weak_ref = keys.to_weak_ref(); window.set_key_callback(move |key, _scancode, key_state, _modifiers| { let keys_weak_ref = keys_weak_ref.clone(); let keys_ref = keys_weak_ref.access().expect("No world"); let mut keys = keys_ref.to_single(); keys.set_key_state(key, key_state); }); let cursor_weak_ref = cursor.to_weak_ref(); window.set_cursor_pos_callback(move |cursor_position| { let cursor_weak_ref = cursor_weak_ref.clone(); let cursor_ref = cursor_weak_ref.access().expect("No world"); let mut cursor = cursor_ref.to_single(); cursor.position = Vec2 { x: cursor_position.x, y: cursor_position.y, }; cursor.has_moved = true; }); }