From ad44a96f0c9b98a9b67e8622bbb2f19c5919fae5 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Fri, 21 Jul 2023 17:54:55 -0400 Subject: [PATCH] Rewrite the input system using an event based system --- Cargo.lock | 60 +------- Cargo.toml | 1 - src/ecs/world.rs | 81 +++++++---- src/game.rs | 95 +++---------- src/input.rs | 358 +++++++++++++++++++++++------------------------ src/main.rs | 57 +++----- 6 files changed, 271 insertions(+), 381 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bec52f..c35f8ed 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1045,7 +1045,6 @@ dependencies = [ "instant", "petgraph", "quote", - "resources", "syn 2.0.26", "tobj", "tracing", @@ -1383,7 +1382,7 @@ version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" dependencies = [ - "redox_syscall 0.3.5", + "redox_syscall", ] [[package]] @@ -1407,17 +1406,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -1425,21 +1413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -1450,7 +1424,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", "windows-targets 0.48.1", ] @@ -1564,15 +1538,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -1588,17 +1553,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" -[[package]] -name = "resources" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42070ea13709eb92d2977b48c7d3bd44866fa328e14248f8d1f00d6ea14d5066" -dependencies = [ - "downcast-rs", - "fxhash", - "parking_lot 0.11.2", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2161,7 +2115,7 @@ dependencies = [ "js-sys", "log", "naga", - "parking_lot 0.12.1", + "parking_lot", "profiling", "raw-window-handle", "smallvec", @@ -2187,7 +2141,7 @@ dependencies = [ "fxhash", "log", "naga", - "parking_lot 0.12.1", + "parking_lot", "profiling", "raw-window-handle", "smallvec", @@ -2226,7 +2180,7 @@ dependencies = [ "metal", "naga", "objc", - "parking_lot 0.12.1", + "parking_lot", "profiling", "range-alloc", "raw-window-handle", @@ -2459,7 +2413,7 @@ dependencies = [ "orbclient", "percent-encoding", "raw-window-handle", - "redox_syscall 0.3.5", + "redox_syscall", "sctk-adwaita", "smithay-client-toolkit", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index dc66d3d..8b850be 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ async-trait = "0.1.65" hecs = "0.10.3" glam = { version = "0.24.0", features = ["bytemuck"] } petgraph = "0.6.3" -resources = "1.1.0" gilrs-core = "0.5.6" syn = "2.0.26" quote = "1.0.29" diff --git a/src/ecs/world.rs b/src/ecs/world.rs index c2fcfaf..e209d4d 100755 --- a/src/ecs/world.rs +++ b/src/ecs/world.rs @@ -1,16 +1,18 @@ -use std::{any::{TypeId, Any}, collections::{HashMap, HashSet, VecDeque}, ops::{Deref, DerefMut}}; +use std::{any::{TypeId, Any}, collections::{HashMap, HashSet, VecDeque}, ops::{Deref, DerefMut}, cell::{RefCell, Ref, RefMut}}; + +use tracing::debug; use super::resources::{Resource, Events}; pub struct World { inner: hecs::World, - resources: HashMap>, + resources: HashMap>>, updated_resources: HashSet, // a boolean that flip flops to clear events every other frame events_flipflop: bool, - events: HashMap>, - event_write_queue: HashMap>,//VecDeque<(TypeId, Box)>, + events: HashMap>>, + event_write_queue: HashMap>>,//VecDeque<(TypeId, Box)>, } impl Deref for World { @@ -47,16 +49,16 @@ impl World { /// Attempts to query a resource, or will create it when its not found. /// /// The resource will be created by a function passed in `default`. - pub fn query_or_insert_res(&mut self, default: impl Fn() -> Box) -> &mut R + pub fn query_or_insert_res(&mut self, default: impl Fn() -> Box>) -> RefMut where R: Resource, { let type_id = TypeId::of::(); - self.resources.entry(type_id) + let r = self.resources.entry(type_id) .or_insert_with(default) - .as_any_mut() - .downcast_mut() - .unwrap() + .borrow_mut(); + + RefMut::map(r, |r| r.as_any_mut().downcast_mut::().unwrap()) } /// Insert a resource into the World. You can only have one resource of the same type. @@ -68,7 +70,7 @@ impl World { R: Resource { let type_id = res.type_id(); - self.resources.insert(type_id, Box::new(res)); + self.resources.insert(type_id, Box::new(RefCell::new(res))); self.updated_resources.insert(type_id); } @@ -90,22 +92,23 @@ impl World { E: Clone + Send + Sync + 'static { // the compiler wants me to explicit right here for some reason - let default = || Box::new(Events::::new()) as Box<(dyn Resource + 'static)>; + let default = || Box::new(RefCell::new(Events::::new())) as Box>; // Get, or create, a list of events of this type - let type_id = TypeId::of::(); - let events: &mut Events = self.event_write_queue.entry(type_id) + let type_id = event.type_id(); + let events = self.event_write_queue.entry(type_id) .or_insert_with(default) - .as_any_mut() - .downcast_mut() - .unwrap(); + .borrow_mut(); + + // downcast resource as an events storage + let mut events: RefMut> = RefMut::map(events, |e| e.as_any_mut().downcast_mut().unwrap()); events.push_back(event); } /// Clear events, this should happen at the start of every tick since events are cloned /// before being given to the reader. - pub fn clear_events(&mut self) { + pub fn update_events(&mut self) { self.events.clear(); // get all keys of events @@ -113,37 +116,58 @@ impl World { // remove all elements from self.event_write_queue and insert them to events for k in keys.into_iter() { - self.events.insert(k, self.event_write_queue.remove(&k).unwrap()); + let v = self.event_write_queue.remove(&k).unwrap(); + self.events.insert(k, v); } } - pub fn read_events(&self) -> Option<&Events> + pub fn read_events(&self) -> Option>> where E: Clone + Send + Sync + 'static { - self.events.get(&TypeId::of::()) - .map(|r| r.as_any().downcast_ref::>()) - .flatten() + if let Some(event ) = self.events.get(&TypeId::of::()) { + //.or_else(|| self.event_write_queue.get(&TypeId::of::())) { + let eref = event.borrow(); + + Some(Ref::map(eref, |x| x.as_any().downcast_ref::>().unwrap())) + } else { + None + } + + /* if let Some(event) = self.events.get(&TypeId::of::()) { + let eref = event.borrow(); + + Some(Ref::map(eref, |x| x.as_any().downcast_ref::>().unwrap())) + } else if let Some(event) = self.events.get(&TypeId::of::()) { + None + } */ + + /* self.events.get(&TypeId::of::()) + //.map(|r| r.borrow().as_any().downcast_ref::>()) + .map(|r| r.borrow().as_any().do) + .flatten() */ } /// Query a resource. /// /// This is O(1), resources are stored in HashMaps. - pub fn query_res(&self) -> Option<&R> + pub fn query_res(&self) -> Option> where R: Resource { self.resources .get(&TypeId::of::()) - .map(|r| r.as_any().downcast_ref()) - .flatten() + .map(|r| { + let r = r.borrow(); + Ref::map(r, |r| r.as_any().downcast_ref().unwrap()) + }) } /// Query a resource mutably. /// /// This will mark the resource as changed, even if it actually wasn't modified when mutably borrowed. /// This is O(1), resources are stored in HashMaps. - pub fn query_res_mut(&mut self) -> Option<&mut R> + pub fn query_res_mut(&mut self) -> Option> where R: Resource { @@ -153,8 +177,9 @@ impl World { // update resource self.updated_resources.insert(TypeId::of::()); - r.as_any_mut().downcast_mut() + let r = r.borrow_mut(); + + RefMut::map(r, |r| r.as_any_mut().downcast_mut::().unwrap()) }) - .flatten() } } \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index 366dbbf..f45a7a9 100755 --- a/src/game.rs +++ b/src/game.rs @@ -4,7 +4,6 @@ use async_std::{task::block_on, sync::Mutex}; //use hecs::World; use instant::Instant; -use resources::{Resources, Resource}; use tracing::{metadata::LevelFilter, info, debug, warn, error}; use tracing_subscriber::{ layer::{Layer, SubscriberExt}, @@ -14,11 +13,10 @@ use tracing_subscriber::{ use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}}; -use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::{components::{mesh::MeshComponent, transform::TransformComponent}, SimpleSystem, SystemDispatcher, world::World, resources::{WindowState, Events}}, input::Input}; +use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::{components::{mesh::MeshComponent, transform::TransformComponent}, SimpleSystem, SystemDispatcher, world::World, resources::{WindowState, Events}}, input::InputEventUpdater}; pub struct Controls<'a> { pub world: &'a mut World, - pub resources: &'a mut Resources, } struct TickCounter { @@ -81,7 +79,6 @@ struct GameLoop { renderer: Box, world: Arc>, - resources: Arc>, /// higher priority systems engine_sys_dispatcher: SystemDispatcher, user_sys_dispatcher: SystemDispatcher, @@ -89,13 +86,12 @@ struct GameLoop { } impl GameLoop { - pub async fn new(window: Arc, world: Arc>, resources: Arc>, user_systems: SystemDispatcher) -> GameLoop { + pub async fn new(window: Arc, world: Arc>, user_systems: SystemDispatcher) -> GameLoop { Self { window: Arc::clone(&window), renderer: Box::new(BasicRenderer::create_with_window(window).await), world, - resources, engine_sys_dispatcher: SystemDispatcher::new(), user_sys_dispatcher: user_systems, fps_counter: TickCounter::new(), @@ -112,13 +108,9 @@ impl GameLoop { async fn update(&mut self) { let mut world = self.world.lock().await; - let mut resources = self.resources.lock().await; - - world.clear_events(); let mut controls = Controls { world: &mut world, - resources: &mut resources }; if let Err(e) = self.engine_sys_dispatcher.execute_mut(&mut controls) { @@ -149,16 +141,8 @@ impl GameLoop { // TODO: Create system for this? or maybe merge into input system, idk InputEvent::CursorEntered { .. } => { let mut world = self.world.lock().await; - let state = match world.query_res_mut::() { - Some(i) => i, - None => { - world.insert_resource(WindowState::new()); - - // must succeed since it was just added - world.query_res_mut::().unwrap() - } - }; + let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); state.is_cursor_inside_window = true; None @@ -166,16 +150,8 @@ impl GameLoop { InputEvent::CursorLeft { .. } => { let mut world = self.world.lock().await; - let state = match world.query_res_mut::() { - Some(i) => i, - None => { - world.insert_resource(WindowState::new()); - - // must succeed since it was just added - world.query_res_mut::().unwrap() - } - }; + let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); state.is_cursor_inside_window = false; None @@ -210,15 +186,17 @@ impl GameLoop { let mut world = self.world.lock().await; // make sure that the mouse is inside the window and the mouse has focus before reporting mouse motion - if let Some(window_state) = world.query_res::() { - if window_state.is_focused && window_state.is_cursor_inside_window { - - let event_queue = world.query_or_insert_res::> - (|| Box::new(Events::::new())); - - let input_event = InputEvent::MouseMotion { device_id, delta, }; - event_queue.push_back(input_event); - } + let trigger = match world.query_res::() { + Some(window_state) if window_state.is_focused && window_state.is_cursor_inside_window => true, + _ => false, + }; + + if trigger { + let mut event_queue = world.query_or_insert_res::> + (|| Box::new(RefCell::new(Events::::new()))); + + let input_event = InputEvent::MouseMotion { device_id, delta, }; + event_queue.push_back(input_event); } }, _ => {} @@ -236,17 +214,6 @@ impl GameLoop { { let mut world = self.world.lock().await; world.trigger_event(input_event.clone()); - /* let event_queue = match world.query_res_mut::>() { - Some(i) => i, - None => { - world.insert_resource(VecDeque::::new()); - - // must succeed since it was just added - world.query_res_mut::>().unwrap() - } - }; - - event_queue.push_back(input_event.clone()); */ } if let Some(new_control) = self.input_update(&input_event).await { @@ -270,16 +237,8 @@ impl GameLoop { WindowEvent::Focused(is_focused) => { let mut world = self.world.lock().await; - let state = match world.query_res_mut::() { - Some(s) => s, - None => { - world.insert_resource(WindowState::new()); - - // must succeed since it was just added - world.query_res_mut::().unwrap() - } - }; - + + let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); state.is_focused = *is_focused; }, @@ -300,6 +259,7 @@ impl GameLoop { let mut world = self.world.lock().await; self.renderer.as_mut().prepare(&mut world).await; world.clear_updated_resources(); + world.update_events(); drop(world); match self.renderer.as_mut().render().await { @@ -323,7 +283,6 @@ impl GameLoop { pub struct Game { world: Option>>, - resources: Option>>, system_dispatcher: Option } @@ -331,7 +290,6 @@ impl Default for Game { fn default() -> Self { Self { world: None, - resources: Some(Arc::new(Mutex::new(Resources::new()))), system_dispatcher: Some(SystemDispatcher::new()), } } @@ -382,30 +340,15 @@ impl Game { self } - - pub async fn with_res(&mut self, r: T) -> &mut Self - where - T: Resource - { - let resources = self.resources.as_mut().unwrap(); - let mut resources = resources.lock().await; - - resources.insert(r); - drop(resources); - - self - } - pub async fn run(&mut self) { let world = self.world.take().expect("ECS World was never given to Game!"); - let resources = self.resources.take().unwrap(); let event_loop = EventLoop::new(); let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap()); let systems = self.system_dispatcher.take().unwrap(); - let mut g_loop = GameLoop::new(Arc::clone(&window), world, resources, systems).await; + let mut g_loop = GameLoop::new(Arc::clone(&window), world, systems).await; event_loop.run(move |event, _, control_flow| { g_loop.run_sync(event, control_flow); diff --git a/src/input.rs b/src/input.rs index c4b3149..f6ff8f4 100755 --- a/src/input.rs +++ b/src/input.rs @@ -1,4 +1,4 @@ -use std::{any::{Any, TypeId}, collections::{HashMap, hash_map::DefaultHasher, VecDeque}, hash::{Hash, Hasher}, sync::{Arc, Mutex}}; +use std::{any::{Any, TypeId}, collections::{HashMap, hash_map::DefaultHasher, VecDeque, HashSet}, hash::{Hash, Hasher}, sync::{Arc, Mutex}, cell::RefCell}; use gilrs_core::Gilrs; use glam::Vec2; @@ -9,45 +9,24 @@ use crate::{ecs::{SimpleSystem, resources::{Resource, Events}, world::World}, in pub type KeyCode = winit::event::VirtualKeyCode; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum ButtonEvent { +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub enum ButtonEvent { Pressed(T), Released(T), JustPressed(T), } -pub struct InputSystem; - -impl InputSystem { - pub fn new() -> Self { - Self {} - } -} - -impl SimpleSystem for InputSystem { - fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> { - let world = &mut controls.world; - - if let Some(queue) = world.query_res_mut::>() { - // Clone the queue, then clear it - let mut queue = { - let a = queue.clone(); - queue.clear(); - a - }; - - if let Some(input) = world.query_res_mut::() { - // clear input before processing the queue - input.clear(); - - // process the all events that happened this tick - while let Some(event) = queue.pop_front() { - input.update(&event, world); - } - } +impl ButtonEvent { + fn take_val(self) -> T { + match self { + ButtonEvent::Pressed(t) => t, + ButtonEvent::JustPressed(t) => t, + ButtonEvent::Released(t) => t, } + } - Ok(()) + fn clone_val(&self) -> T { + self.clone().take_val() } } @@ -121,10 +100,28 @@ pub struct Touches { pub touches: Vec, } +impl Resource for Touches { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +impl Touches { + pub fn new() -> Self { + Self { + touches: Vec::new() + } + } +} + /// A mouse button event /// /// Translated `WindowEvent::MouseButton` from `winit` crate -#[derive(Clone, Copy, Debug, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub enum MouseButton { Left, Right, @@ -149,14 +146,13 @@ pub struct CursorEnteredWindow; #[derive(Clone, Debug, Eq, PartialEq)] pub struct CursorLeftWindow; -pub struct Input { - gilrs: Option>>, // TODO - // the key is a u64. This is a hash of the value stored inside of the Box - button_events: HashMap>, - typed_events: HashMap>, +pub struct InputButtons { + // the u64 as the key is the hashed value of T. this makes it easier to + // search for a button and see its state + button_events: HashMap>, } -impl Resource for Input { +impl Resource for InputButtons { fn as_any(&self) -> &dyn Any { self } @@ -166,28 +162,108 @@ impl Resource for Input { } } -/// helper function for converting -#[inline(always)] -fn button_event_retain(val: &mut Box) -> bool -where - E: Clone + Hash + 'static, -{ - if let Some(ev) = val.downcast_mut::>() { - match ev { - ButtonEvent::Released(_) => { - return false; - }, - ButtonEvent::JustPressed(v) => { - *ev = ButtonEvent::Pressed(v.clone()); - }, - _ => {} +impl InputButtons { + pub fn new() -> Self { + Self { + button_events: HashMap::new(), } } - true + fn get_button_hash(button: &T) -> u64 { + let mut hasher = DefaultHasher::new(); + button.hash(&mut hasher); + hasher.finish() + } + + /// Add a button event to this input type + pub fn add_input(&mut self, button: ButtonEvent) { + let hash = Self::get_button_hash(&button.clone_val()); + + self.button_events.insert(hash, button); + } + + pub(crate) fn add_input_from_winit(&mut self, button: T, state: ElementState) { + let event = match state { + ElementState::Pressed if self.is_pressed(button.clone()) => ButtonEvent::Pressed(button), + ElementState::Pressed => ButtonEvent::JustPressed(button), + ElementState::Released => ButtonEvent::Released(button), + }; + + self.add_input(event); + } + + /// Returns true if the button is pressed (or was just pressed) + pub fn is_pressed(&self, button: T) -> bool + { + let hash = Self::get_button_hash(&button); + match self.button_events.get(&hash) { + Some(button_event) => match button_event { + // this if statement should always be true, but just in case ;) + ButtonEvent::Pressed(b) | ButtonEvent::JustPressed(b) if button == *b => true, + _ => false, + }, + None => false + } + } + + /// Returns true if the button was just pressed this tick + pub fn was_just_pressed(&self, button: T) -> bool { + let hash = Self::get_button_hash(&button); + match self.button_events.get(&hash) { + Some(button_event) => match button_event { + // this if statement should always be true, but just in case ;) + ButtonEvent::JustPressed(b) if button == *b => true, + _ => false, + }, + None => false + } + } } -impl Input { +trait InputStorage { + fn update_just_pressed(&mut self); +} + +impl InputStorage for InputButtons { + fn update_just_pressed(&mut self) { + /* for (hash, button) in self.button_events.iter_mut() { + + /* if let ButtonEvent::JustPressed(b) = button { + *button = ButtonEvent::Pressed(b.clone()); + } */ + match button { + ButtonEvent::Pressed(_) => todo!(), + ButtonEvent::Released(b) => { + return false; + }, + ButtonEvent::JustPressed(b) => { + *button = ButtonEvent::Pressed(b.clone()); + }, + } + } */ + + self.button_events.retain(|_hash, button| { + match button { + // remove released, no need to keep those around. + ButtonEvent::Released(_) => { + return false; + }, + ButtonEvent::JustPressed(b) => { + *button = ButtonEvent::Pressed(b.clone()); + }, + _ => {}, + } + + true + }); + } +} + +pub struct InputEventUpdater { + gilrs: Option>>, // TODO +} + +impl InputEventUpdater { pub(crate) fn new() -> Self { let gilrs = match Gilrs::new() { Ok(g) => Some(Arc::new(Mutex::new(g))), @@ -200,38 +276,6 @@ impl Input { Self { gilrs, - button_events: HashMap::new(), - typed_events: HashMap::new(), - } - } - - pub fn clear(&mut self) { - // Convert JustPressed inputs to Pressed, and remove Released events - self.button_events.retain(|_, v| { - if !button_event_retain::(v) - || !button_event_retain::(v) - { - return false; - } - - true - }); - - self.typed_events.retain(|_, v| { - if v.downcast_ref::().is_some() - || v.downcast_ref::().is_some() - || v.downcast_ref::().is_some() - || v.downcast_ref::().is_some() - || v.downcast_ref::().is_some() - { - return false; - } - - true - }); - - if let Some(touches) = self.get_event_mut::() { - touches.touches.clear(); } } @@ -239,7 +283,9 @@ impl Input { match event { InputEvent::KeyboardInput { input, .. } => { if let Some(code) = input.virtual_keycode { - self.create_button_event(code, input.state); + let mut e = world.query_or_insert_res::> + (|| Box::new(RefCell::new(InputButtons::::new()))); + e.add_input_from_winit(code, input.state); } }, InputEvent::MouseMotion { delta, .. } => { @@ -247,22 +293,22 @@ impl Input { delta: Vec2::new(delta.0 as f32, delta.1 as f32) }; - self.typed_events.insert(delta.type_id(), Box::new(delta)); + world.trigger_event(delta); }, InputEvent::CursorMoved { position, .. } => { let exact = MouseExact { pos: Vec2::new(position.x as f32, position.y as f32) }; - self.typed_events.insert(exact.type_id(), Box::new(exact)); + world.trigger_event(exact); }, InputEvent::CursorEntered { .. } => { let event = CursorEnteredWindow {}; - self.typed_events.insert(event.type_id(), Box::new(event)); + world.trigger_event(event); }, InputEvent::CursorLeft { .. } => { let event = CursorLeftWindow {}; - self.typed_events.insert(event.type_id(), Box::new(event)); + world.trigger_event(event); }, InputEvent::MouseWheel { delta, .. } => { let event = match delta { @@ -274,17 +320,21 @@ impl Input { }, }; - self.typed_events.insert(event.type_id(), Box::new(event)); + world.trigger_event(event); }, //MouseButton InputEvent::MouseInput { button, state, .. } => { - let button = match button { + let button_event = match button { winit::event::MouseButton::Left => MouseButton::Left, winit::event::MouseButton::Right => MouseButton::Right, winit::event::MouseButton::Middle => MouseButton::Middle, winit::event::MouseButton::Other(v) => MouseButton::Other(*v), }; - self.create_button_event(button, *state); + world.trigger_event(button_event.clone()); + + let mut e = world.query_or_insert_res::> + (|| Box::new(RefCell::new(InputButtons::::new()))); + e.add_input_from_winit(button_event, state.clone()); }, InputEvent::Touch(t) => { let touch = Touch { @@ -297,17 +347,8 @@ impl Input { finger_id: t.id, }; - let touches = match self.get_event_mut::() { - Some(t) => t, - None => { - let t = Touches { - touches: Vec::new(), - }; - - self.typed_events.insert(t.type_id(), Box::new(t)); - self.get_event_mut::().unwrap() - } - }; + let mut touches = world.query_or_insert_res:: + (|| Box::new(RefCell::new(Touches::new()))); touches.touches.push(touch); }, @@ -316,89 +357,38 @@ impl Input { false } +} - fn create_button_event(&mut self, button: B, state: ElementState) - where - B: Hash + PartialEq + Clone + Copy + Sync + Send + 'static - { - // Get a hash of the button - let mut hasher = DefaultHasher::new(); - button.hash(&mut hasher); - let code_hash = hasher.finish(); +impl SimpleSystem for InputEventUpdater { + fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> { + let world = &mut controls.world; - // convert state - let buttonev = Box::new(match state { - ElementState::Pressed if self.is_pressed(button) => ButtonEvent::Pressed(button), - ElementState::Pressed => ButtonEvent::JustPressed(button), - ElementState::Released => ButtonEvent::Released(button), - }); + let queue = world.read_events::(); - self.button_events.insert(code_hash, buttonev); - } - - pub fn get_event(&self) -> Option<&E> { - self.typed_events.get(&TypeId::of::()) - .and_then(|e| e.as_ref() - .downcast_ref::()) - } - - pub(crate) fn get_event_mut(&mut self) -> Option<&mut E> { - self.typed_events.get_mut(&TypeId::of::()) - .and_then(|e| e.as_mut() - .downcast_mut::()) - } - - pub fn was_just_pressed(&self, code: T) -> bool - where - T: Hash + PartialEq + Clone + 'static - { - // get a hash of the key code - let mut hasher = DefaultHasher::new(); - code.hash(&mut hasher); - let inner_hash = hasher.finish(); - - if let Some(e) = self.button_events.get(&inner_hash) { - if let Some(ev) = e.downcast_ref::>() { - match ev { - ButtonEvent::JustPressed(v) => { - if v.clone() == code { - return true; - } - }, - _ => { - return false; - } - } - } + if queue.is_none() { + return Ok(()); } - false - } + let queue = queue.unwrap(); - pub fn is_pressed(&self, code: T) -> bool - where - T: Hash + PartialEq + Clone + 'static - { - // get a hash of the key code - let mut hasher = DefaultHasher::new(); - code.hash(&mut hasher); - let inner_hash = hasher.finish(); - - if let Some(e) = self.button_events.get(&inner_hash) { - if let Some(ev) = e.downcast_ref::>() { - match ev { - ButtonEvent::Pressed(v) | ButtonEvent::JustPressed(v) => { - if v.clone() == code { - return true; - } - }, - _ => { - return false; - } - } - } + // borrow checker isn't happy when I query multiple things :( + let mut events = queue.clone(); + drop(queue); + + while let Some(event) = events.pop_front() { + self.update(&event, world); } - false + /* if let Some(queue) = world.read_events::() { + // Clone the queue, then clear it + let mut events = queue.clone(); + drop(queue); + + while let Some(event) = events.pop_front() { + self.update(&event, world); + } + } */ + + Ok(()) } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 28b5912..65777a6 100755 --- a/src/main.rs +++ b/src/main.rs @@ -6,14 +6,17 @@ mod ecs; mod math; mod input; +use std::cell::Ref; + use ecs::components::mesh::MeshComponent; use ecs::components::transform::TransformComponent; use game::Game; +use input_event::InputEvent; use tracing::debug; use crate::ecs::world::World; -use crate::input::{Input, KeyCode, InputSystem, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton}; +use crate::input::{InputEventUpdater, KeyCode, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton, InputButtons}; use crate::render::material::Material; use crate::render::texture::Texture; use crate::ecs::components::camera::CameraComponent; @@ -86,64 +89,40 @@ async fn main() { camera.transform.translation += glam::Vec3::new(0.0, 0.0, 2.0); //camera.transform.rotate_y(Angle::Degrees(-25.0)); camera.transform.rotate_z(Angle::Degrees(-90.0)); - world.insert_resource(Input::new()); world.spawn((camera,)); let jiggle_system = |world: &mut World| -> anyhow::Result<()> { - let input: &Input = world.query_res().unwrap(); + //let input: &InputEventUpdater = world.query_res().unwrap(); + + let keys = world.query_res(); + if keys.is_none() { + return Ok(()); + } + + let keys: Ref> = keys.unwrap(); let speed = 0.001; let mut dir_x = 0.0; let mut dir_y = 0.0; - if input.is_pressed(KeyCode::A) { + if keys.is_pressed(KeyCode::A) { dir_x -= speed; } - if input.is_pressed(KeyCode::D) { + if keys.is_pressed(KeyCode::D) { dir_x += speed; } - if input.is_pressed(KeyCode::S) { + if keys.is_pressed(KeyCode::S) { dir_y -= speed; } - if input.is_pressed(KeyCode::W) { + if keys.is_pressed(KeyCode::W) { dir_y += speed; } - if input.is_pressed(MouseButton::Left) { - debug!("left mouse button!"); - } - - if input.is_pressed(MouseButton::Middle) { - debug!("middle mouse button!"); - } - - if input.is_pressed(MouseButton::Right) { - debug!("right mouse button!"); - } - - if let Some(motion) = input.get_event::() { - debug!("delta: {}", motion.delta); - } - - if let Some(exact) = input.get_event::() { - debug!("exact pos: {:?}", exact); - } - - if let Some(scroll) = input.get_event::() { - debug!("scrolled: {:?}", scroll); - } - - if input.get_event::().is_some() { - debug!("cursor entered window!"); - } - - if input.get_event::().is_some() { - debug!("cursor left window!"); - } + drop(keys); for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() { let t = &mut transform.transform; @@ -161,7 +140,7 @@ async fn main() { Game::initialize().await .with_world(world) + .with_system("input", InputEventUpdater::new(), &[]) .with_system("jiggle", jiggle_system, &[]) - .with_system("input_system", InputSystem::new(), &[]) .run().await; }