From 7083a19bf1029bff21a9550d40cc3260e99aac53 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 18 Oct 2025 17:04:28 +0200 Subject: refactor(engine): use winit instead of glfw --- engine/src/input.rs | 247 +++------------------------------------------------- 1 file changed, 11 insertions(+), 236 deletions(-) (limited to 'engine/src/input.rs') diff --git a/engine/src/input.rs b/engine/src/input.rs index c53175e..f8c9dfd 100644 --- a/engine/src/input.rs +++ b/engine/src/input.rs @@ -1,257 +1,32 @@ -use std::collections::HashMap; - +use ecs::declare_entity; use ecs::extension::Collector as ExtensionCollector; -use ecs::pair::{ChildOf, Pair}; -use ecs::phase::{Phase, PRE_UPDATE as PRE_UPDATE_PHASE, START as START_PHASE}; -use ecs::sole::Single; -use ecs::{declare_entity, Sole}; - -use crate::vector::Vec2; -use crate::window::{Window, UPDATE_PHASE as WINDOW_UPDATE_PHASE}; +use ecs::pair::{DependsOn, Pair}; +use ecs::phase::Phase; -mod reexports -{ - pub use crate::window::{Key, KeyState}; -} +use crate::windowing::PHASE as WINDOWING_PHASE; -pub use reexports::*; +pub mod keyboard; +pub mod mouse; declare_entity!( - SET_PREV_KEY_STATE_PHASE, + pub PHASE, ( Phase, Pair::builder() - .relation::() - .target_id(*WINDOW_UPDATE_PHASE) + .relation::() + .target_id(*WINDOWING_PHASE) .build() ) ); -#[derive(Debug, Sole)] -pub struct Keys -{ - map: HashMap, - pending: Vec<(Key, KeyState)>, -} - -impl Keys -{ - #[must_use] - pub fn new() -> Self - { - Self { - map: Key::KEYS - .iter() - .map(|key| { - ( - *key, - KeyData { - state: KeyState::Released, - prev_tick_state: KeyState::Released, - }, - ) - }) - .collect(), - pending: Vec::with_capacity(Key::KEYS.len()), - } - } - - #[must_use] - pub fn get_key_state(&self, key: Key) -> KeyState - { - let Some(key_data) = self.map.get(&key) else { - unreachable!(); - }; - - key_data.state - } - - #[must_use] - pub fn get_prev_key_state(&self, key: Key) -> KeyState - { - let Some(key_data) = self.map.get(&key) else { - unreachable!(); - }; - - key_data.prev_tick_state - } - - pub fn set_key_state(&mut self, key: Key, new_key_state: KeyState) - { - let Some(key_data) = self.map.get_mut(&key) else { - unreachable!(); - }; - - key_data.state = new_key_state; - } - - #[must_use] - pub fn is_anything_pressed(&self) -> bool - { - self.map - .values() - .any(|key_data| matches!(key_data.state, KeyState::Pressed)) - } -} - -impl Default for Keys -{ - fn default() -> Self - { - Self::new() - } -} - -#[derive(Debug, Default, Clone, Sole)] -pub struct Cursor -{ - pub position: Vec2, - pub has_moved: bool, -} - -#[derive(Debug, Clone, Sole)] -pub struct CursorFlags -{ - /// This flag is set in two situations: - /// A: The window has just started - /// B: The window has gained focus again after losing focus. - /// - /// This flag only lasts a single tick then it is cleared (at the beginning of the - /// next tick). - pub is_first_move: CursorFlag, -} - -impl Default for CursorFlags -{ - fn default() -> Self - { - Self { - is_first_move: CursorFlag { flag: true, ..Default::default() }, - } - } -} - -#[derive(Debug, Default, Clone)] -pub struct CursorFlag -{ - pub flag: bool, - pub pending_clear: bool, -} - -impl CursorFlag -{ - pub fn clear(&mut self) - { - self.flag = false; - self.pending_clear = false; - } -} - /// Input extension. #[derive(Debug, Default)] pub struct Extension {} impl ecs::extension::Extension for Extension { - fn collect(self, mut collector: ExtensionCollector<'_>) + fn collect(self, _collector: ExtensionCollector<'_>) { - collector.add_declared_entity(&SET_PREV_KEY_STATE_PHASE); - - collector.add_system(*START_PHASE, initialize); - collector.add_system(*PRE_UPDATE_PHASE, maybe_clear_cursor_is_first_move); - collector.add_system(*SET_PREV_KEY_STATE_PHASE, set_pending_key_states); - - collector.add_sole(Keys::default()).ok(); - collector.add_sole(Cursor::default()).ok(); - collector.add_sole(CursorFlags::default()).ok(); - } -} - -fn initialize( - keys: Single, - cursor: Single, - cursor_flags: Single, - window: Single, -) -{ - let keys_weak_ref = keys.to_weak_ref(); - - window.set_key_callback(move |key, _scancode, key_state, _modifiers| { - let keys_ref = keys_weak_ref.access().expect("No world"); - - let mut keys = keys_ref.to_single(); - - keys.pending.push((key, key_state)); - }); - - let cursor_weak_ref = cursor.to_weak_ref(); - - window.set_cursor_pos_callback(move |cursor_position| { - 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; - }); - - let cursor_flags_weak_ref = cursor_flags.to_weak_ref(); - - window.set_focus_callback(move |is_focused| { - tracing::trace!("Window is focused: {is_focused}"); - - let cursor_flags_ref = cursor_flags_weak_ref.access().expect("No world"); - - cursor_flags_ref.to_single().is_first_move.flag = is_focused; - }); -} - -fn maybe_clear_cursor_is_first_move( - cursor: Single, - mut cursor_flags: Single, -) -{ - if cursor_flags.is_first_move.pending_clear { - tracing::trace!("Clearing is_first_move"); - - // This flag was set for the whole previous tick so it can be cleared now - cursor_flags.is_first_move.clear(); - - return; - } - - if cursor.has_moved && cursor_flags.is_first_move.flag { - tracing::trace!("Setting flag to clear is_first_move next tick"); - - // Make this system clear is_first_move the next time it runs - cursor_flags.is_first_move.pending_clear = true; + // TODO: Add input mapping } } - -fn set_pending_key_states(mut keys: Single) -{ - let Keys { map, pending } = &mut *keys; - - for key_data in map.values_mut() { - key_data.prev_tick_state = key_data.state; - } - - for (key, key_state) in pending { - let Some(key_data) = map.get_mut(key) else { - unreachable!(); - }; - - key_data.state = *key_state; - } -} - -#[derive(Debug)] -struct KeyData -{ - state: KeyState, - prev_tick_state: KeyState, -} -- cgit v1.2.3-18-g5258