From 73b44857eb4c0f9989179e4e0a607becdc72ffc6 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Thu, 31 Aug 2023 21:34:58 -0400 Subject: [PATCH] Switch ecs to edict --- Cargo.lock | 61 ++++++++++ Cargo.toml | 2 + src/ecs/components/camera.rs | 2 + src/ecs/components/mesh.rs | 4 +- src/ecs/components/transform.rs | 4 +- src/ecs/mod.rs | 5 +- src/ecs/resources/event_queue.rs | 63 ++++++++++ src/ecs/resources/events.rs | 51 +------- src/ecs/resources/mod.rs | 18 +-- src/ecs/resources/window_state.rs | 12 +- src/ecs/world.rs | 185 ------------------------------ src/game.rs | 50 ++++---- src/input.rs | 76 ++++-------- src/input_event.rs | 12 +- src/main.rs | 26 +++-- src/math/angle.rs | 1 + src/render/render_job.rs | 8 +- src/render/renderer.rs | 27 ++--- 18 files changed, 232 insertions(+), 375 deletions(-) create mode 100644 src/ecs/resources/event_queue.rs delete mode 100755 src/ecs/world.rs diff --git a/Cargo.lock b/Cargo.lock index c35f8ed..498584f 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,6 +264,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +[[package]] +name = "atomicell" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157342dd84c64f16899b4b16c1fb2cce54b887990362aac3c590b3d13810890f" + [[package]] name = "autocfg" version = "1.1.0" @@ -534,6 +540,42 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "edict" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85bf7cde5687ce04b093bfe183453fa12996b6bdfd2567a0262ebd621761d77" +dependencies = [ + "atomicell", + "edict-proc", + "hashbrown 0.13.2", + "parking_lot", + "smallvec", + "tiny-fn", +] + +[[package]] +name = "edict-proc" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94d80dc0f05250a9082bb9455bbf3d6c6c51db388b060df914aebcfb4a9b9f1" +dependencies = [ + "edict-proc-lib", + "syn 2.0.26", +] + +[[package]] +name = "edict-proc-lib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d98f9931a4f71c7eb7d85cf4ef1271b27014625c85a65376a52c10ac4ffaea" +dependencies = [ + "proc-easy", + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1036,8 +1078,10 @@ dependencies = [ "anyhow", "async-std", "async-trait", + "atomicell", "bytemuck", "cfg-if", + "edict", "gilrs-core", "glam", "hecs", @@ -1492,6 +1536,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "proc-easy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea59c637cd0e6b71ae18e589854e9de9b7cb17fefdbf2047e42bd38e24285b19" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -1780,6 +1835,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiny-fn" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7b2c33e09916c65a15c92c1e583946052527e06102689ed11c6125f64fa8ba" + [[package]] name = "tiny-skia" version = "0.8.4" diff --git a/Cargo.toml b/Cargo.toml index 8b850be..f969378 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,5 @@ petgraph = "0.6.3" gilrs-core = "0.5.6" syn = "2.0.26" quote = "1.0.29" +edict = "0.5.0" +atomicell = "0.1.9" diff --git a/src/ecs/components/camera.rs b/src/ecs/components/camera.rs index f1762ed..32191bb 100755 --- a/src/ecs/components/camera.rs +++ b/src/ecs/components/camera.rs @@ -1,7 +1,9 @@ +use edict::Component; use winit::dpi::PhysicalSize; use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX, Transform}, render::camera::CameraProjectionMode}; +#[derive(Clone, Component)] pub struct CameraComponent { pub transform: Transform, pub fov: Angle, diff --git a/src/ecs/components/mesh.rs b/src/ecs/components/mesh.rs index 97e6dbc..b169c63 100755 --- a/src/ecs/components/mesh.rs +++ b/src/ecs/components/mesh.rs @@ -1,6 +1,8 @@ +use edict::Component; + use crate::render::{vertex::Vertex, mesh::Mesh, material::Material}; -#[derive(Clone)] +#[derive(Clone, Component)] pub struct MeshComponent { pub mesh: Mesh, pub material: Material, diff --git a/src/ecs/components/transform.rs b/src/ecs/components/transform.rs index 2bab3bf..4deeaf0 100755 --- a/src/ecs/components/transform.rs +++ b/src/ecs/components/transform.rs @@ -1,6 +1,8 @@ +use edict::Component; + use crate::math::Transform; -#[derive(Clone)] +#[derive(Clone, Component)] pub struct TransformComponent { pub transform: Transform, } diff --git a/src/ecs/mod.rs b/src/ecs/mod.rs index ab10102..fca2e95 100755 --- a/src/ecs/mod.rs +++ b/src/ecs/mod.rs @@ -6,11 +6,8 @@ use tracing::warn; use crate::game::Controls; pub mod components; -pub mod world; pub mod resources; -use world::World; - /// A trait that represents a simple system pub trait SimpleSystem { fn setup(&mut self, controls: &mut Controls) -> anyhow::Result<()> { @@ -22,7 +19,7 @@ pub trait SimpleSystem { } impl SimpleSystem for S - where S: FnMut(&mut World) -> anyhow::Result<()> + where S: FnMut(&mut edict::World) -> anyhow::Result<()> { fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> { self(controls.world) diff --git a/src/ecs/resources/event_queue.rs b/src/ecs/resources/event_queue.rs new file mode 100644 index 0000000..63ed76d --- /dev/null +++ b/src/ecs/resources/event_queue.rs @@ -0,0 +1,63 @@ +use std::{collections::{HashMap, VecDeque}, any::{TypeId, Any}, cell::{RefCell, Ref, RefMut}}; + +use super::{CastableAny, Events, Event}; + +pub struct EventQueue { + events: HashMap>>, + event_write_queue: HashMap>> +} + +impl EventQueue { + pub fn new() -> Self { + Self { + event_write_queue: HashMap::new(), + events: HashMap::new(), + } + } + + /// Trigger an event + pub fn trigger_event(&mut self, event: E) + where + E: Event + { + // the compiler wants me to explicit right here for some reason + let default = || RefCell::new(Box::new(Events::::new()) as Box); + + // Get, or create, a list of events of this type + let type_id = event.type_id(); + let mut events = self.event_write_queue.entry(type_id) + .or_insert_with(default) + .borrow_mut(); + + // downcast resource as an events storage + let e: &mut Events = events.as_mut().as_any_mut().downcast_mut().unwrap(); + e.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 update_events(&mut self) { + self.events.clear(); + + // get all keys of events + let keys: Vec = self.event_write_queue.keys().map(|k| k.clone()).collect(); + + // remove all elements from self.event_write_queue and insert them to events + for k in keys.into_iter() { + let v = self.event_write_queue.remove(&k).unwrap(); + self.events.insert(k, v); + } + } + + pub fn read_events(&self) -> Option> + where + E: Event + { + if let Some(event ) = self.events.get(&TypeId::of::()) { + let eref = event.borrow(); + Some(eref.as_ref().as_any().downcast_ref::>().unwrap().clone()) + } else { + None + } + } +} \ No newline at end of file diff --git a/src/ecs/resources/events.rs b/src/ecs/resources/events.rs index 51f3082..d6ce8a9 100755 --- a/src/ecs/resources/events.rs +++ b/src/ecs/resources/events.rs @@ -1,53 +1,6 @@ -use std::{collections::VecDeque, ops::{Deref, DerefMut}}; - -use super::Resource; +use std::collections::VecDeque; pub trait Event: Clone + Send + Sync + 'static {} impl Event for T {} -#[derive(Clone)] -pub struct Events { - inner: VecDeque -} - -impl Events { - pub fn new() -> Self { - Self { - inner: VecDeque::new() - } - } -} - -impl Deref for Events { - type Target = VecDeque; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl DerefMut for Events { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - -impl Resource for Events { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} - -pub trait EventHolder { - fn get_data() -> T; - -} - -pub struct EventStorage { - data: T, - is_future: bool, -} \ No newline at end of file +pub type Events = VecDeque; \ No newline at end of file diff --git a/src/ecs/resources/mod.rs b/src/ecs/resources/mod.rs index c0f1dc6..ed82625 100755 --- a/src/ecs/resources/mod.rs +++ b/src/ecs/resources/mod.rs @@ -8,22 +8,16 @@ pub use window_state::*; pub mod events; pub use events::*; -pub trait Resource: Send + Sync + 'static { +pub mod event_queue; +pub use event_queue::*; + +pub trait CastableAny: Send + Sync + 'static { fn as_any(&self) -> &dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any; } -impl Resource for WindowEvent<'static> { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } -} - -impl Resource for VecDeque { +/// Implements this trait for anything that fits the type bounds +impl CastableAny for T { fn as_any(&self) -> &dyn Any { self } diff --git a/src/ecs/resources/window_state.rs b/src/ecs/resources/window_state.rs index 9552ebf..fcd66c8 100755 --- a/src/ecs/resources/window_state.rs +++ b/src/ecs/resources/window_state.rs @@ -1,6 +1,6 @@ use std::any::Any; -use super::Resource; +use super::CastableAny; #[derive(Clone, Default)] pub struct WindowState { @@ -12,14 +12,4 @@ impl WindowState { pub fn new() -> Self { Self::default() } -} - -impl Resource for WindowState { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } } \ No newline at end of file diff --git a/src/ecs/world.rs b/src/ecs/world.rs deleted file mode 100755 index e209d4d..0000000 --- a/src/ecs/world.rs +++ /dev/null @@ -1,185 +0,0 @@ -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>>, - 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)>, -} - -impl Deref for World { - type Target = hecs::World; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl DerefMut for World { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - -#[allow(dead_code)] -impl World { - pub fn new() -> Self { - Self::from_hecs(hecs::World::new()) - } - - pub fn from_hecs(hecs_world: hecs::World) -> Self { - Self { - inner: hecs_world, - resources: HashMap::new(), - updated_resources: HashSet::new(), - events_flipflop: false, - events: HashMap::new(), - event_write_queue: HashMap::new(), - } - } - - /// 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>) -> RefMut - where - R: Resource, - { - let type_id = TypeId::of::(); - let r = self.resources.entry(type_id) - .or_insert_with(default) - .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. - /// If you attempt to add another resource of the same type, it will be replaced. - /// - /// This will also mark the resource as updated in this frame. - pub fn insert_resource(&mut self, res: R) - where - R: Resource - { - let type_id = res.type_id(); - self.resources.insert(type_id, Box::new(RefCell::new(res))); - self.updated_resources.insert(type_id); - } - - /// Checks if a resource was updated this frame. - pub fn was_res_updated(&self) -> bool - where - R: Resource - { - self.updated_resources.contains(&TypeId::of::()) - } - - pub(crate) fn clear_updated_resources(&mut self) { - self.updated_resources.clear(); - } - - /// Trigger an event - pub fn trigger_event(&mut self, event: E) - where - E: Clone + Send + Sync + 'static - { - // the compiler wants me to explicit right here for some reason - let default = || Box::new(RefCell::new(Events::::new())) as Box>; - - // Get, or create, a list of events of this type - let type_id = event.type_id(); - let events = self.event_write_queue.entry(type_id) - .or_insert_with(default) - .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 update_events(&mut self) { - self.events.clear(); - - // get all keys of events - let keys: Vec = self.event_write_queue.keys().map(|k| k.clone()).collect(); - - // remove all elements from self.event_write_queue and insert them to events - for k in keys.into_iter() { - let v = self.event_write_queue.remove(&k).unwrap(); - self.events.insert(k, v); - } - } - - pub fn read_events(&self) -> Option>> - where - E: Clone + Send + Sync + 'static - { - 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> - where - R: Resource - { - self.resources - .get(&TypeId::of::()) - .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> - where - R: Resource - { - self.resources - .get_mut(&TypeId::of::()) - .map(|r| { - // update resource - self.updated_resources.insert(TypeId::of::()); - - let r = r.borrow_mut(); - - RefMut::map(r, |r| r.as_any_mut().downcast_mut::().unwrap()) - }) - } -} \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index f45a7a9..78fdecb 100755 --- a/src/game.rs +++ b/src/game.rs @@ -1,4 +1,4 @@ -use std::{sync::Arc, cell::RefCell, borrow::Borrow, collections::VecDeque}; +use std::sync::Arc; use async_std::{task::block_on, sync::Mutex}; @@ -13,10 +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::InputEventUpdater}; +use crate::{render::renderer::{Renderer, BasicRenderer}, input_event::InputEvent, ecs::{SimpleSystem, SystemDispatcher, resources::{WindowState, Events, EventQueue}}}; pub struct Controls<'a> { - pub world: &'a mut World, + pub world: &'a mut edict::World, } struct TickCounter { @@ -78,7 +78,7 @@ struct GameLoop { window: Arc, renderer: Box, - world: Arc>, + world: Arc>, /// higher priority systems engine_sys_dispatcher: SystemDispatcher, user_sys_dispatcher: SystemDispatcher, @@ -86,7 +86,13 @@ struct GameLoop { } impl GameLoop { - pub async fn new(window: Arc, world: Arc>, user_systems: SystemDispatcher) -> GameLoop { + pub async fn new(window: Arc, world: Arc>, user_systems: SystemDispatcher) -> GameLoop { + // Create the EventQueue resource in the world + { + let mut world = world.lock().await; + world.insert_resource(EventQueue::new()); + } + Self { window: Arc::clone(&window), renderer: Box::new(BasicRenderer::create_with_window(window).await), @@ -99,7 +105,7 @@ impl GameLoop { } pub async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize) { - self.renderer.on_resize(new_size).await; + self.renderer.on_resize(new_size); } pub fn run_sync(&mut self, event: Event<()>, control_flow: &mut ControlFlow) { @@ -142,7 +148,7 @@ impl GameLoop { InputEvent::CursorEntered { .. } => { let mut world = self.world.lock().await; - let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); + let mut state = world.with_resource(|| WindowState::new()); state.is_cursor_inside_window = true; None @@ -151,7 +157,7 @@ impl GameLoop { InputEvent::CursorLeft { .. } => { let mut world = self.world.lock().await; - let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); + let mut state = world.with_resource(|| WindowState::new()); state.is_cursor_inside_window = false; None @@ -186,14 +192,13 @@ 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 - let trigger = match world.query_res::() { + let trigger = match world.get_resource::() { 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 event_queue = world.with_resource(|| Events::::new()); let input_event = InputEvent::MouseMotion { device_id, delta, }; event_queue.push_back(input_event); @@ -212,8 +217,10 @@ impl GameLoop { // Its possible to receive multiple input events before the update event for // the InputSystem is called, so we must use a queue for the events. { - let mut world = self.world.lock().await; - world.trigger_event(input_event.clone()); + let world = self.world.lock().await; + if let Some(mut event_queue) = world.get_resource_mut::() { + event_queue.trigger_event(input_event.clone()); + }; } if let Some(new_control) = self.input_update(&input_event).await { @@ -238,7 +245,7 @@ impl GameLoop { WindowEvent::Focused(is_focused) => { let mut world = self.world.lock().await; - let mut state = world.query_or_insert_res::(|| Box::new(RefCell::new(WindowState::new()))); + let mut state = world.with_resource(|| WindowState::new()); state.is_focused = *is_focused; }, @@ -257,12 +264,13 @@ impl GameLoop { } */ let mut world = self.world.lock().await; - self.renderer.as_mut().prepare(&mut world).await; - world.clear_updated_resources(); - world.update_events(); + self.renderer.as_mut().prepare(&mut world); + if let Some(mut event_queue) = world.get_resource_mut::() { + event_queue.update_events(); + } drop(world); - match self.renderer.as_mut().render().await { + match self.renderer.as_mut().render() { Ok(_) => {} // Reconfigure the surface if lost Err(wgpu::SurfaceError::Lost) => self.on_resize(self.renderer.as_ref().surface_size()).await, @@ -282,7 +290,7 @@ impl GameLoop { } pub struct Game { - world: Option>>, + world: Option>>, system_dispatcher: Option } @@ -312,13 +320,13 @@ impl Game { Self::default() } - pub fn with_world(&mut self, world: World) -> &mut Self { + pub fn with_world(&mut self, world: edict::World) -> &mut Self { self.world = Some(Arc::new(Mutex::new(world))); self } - pub fn with_world_arc(&mut self, world: Arc>) -> &mut Self { + pub fn with_world_arc(&mut self, world: Arc>) -> &mut Self { self.world = Some(world); self diff --git a/src/input.rs b/src/input.rs index f6ff8f4..9c26777 100755 --- a/src/input.rs +++ b/src/input.rs @@ -5,7 +5,7 @@ use glam::Vec2; use tracing::{warn, debug}; use winit::event::{VirtualKeyCode, ElementState, MouseScrollDelta}; -use crate::{ecs::{SimpleSystem, resources::{Resource, Events}, world::World}, input_event::InputEvent}; +use crate::{ecs::{SimpleSystem, resources::{CastableAny, Events, EventQueue}}, input_event::InputEvent}; pub type KeyCode = winit::event::VirtualKeyCode; @@ -100,16 +100,6 @@ 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 { @@ -152,16 +142,6 @@ pub struct InputButtons { button_events: HashMap>, } -impl Resource for InputButtons { - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } -} - impl InputButtons { pub fn new() -> Self { Self { @@ -279,12 +259,19 @@ impl InputEventUpdater { } } - pub fn update(&mut self, event: &InputEvent, world: &mut World) -> bool { + pub fn update(&mut self, event: &InputEvent, world: &mut edict::World) -> bool { + let event_queue = world.get_resource_mut::(); + if event_queue.is_none() { + return false; + } + let mut event_queue = event_queue.unwrap(); + match event { InputEvent::KeyboardInput { input, .. } => { if let Some(code) = input.virtual_keycode { - let mut e = world.query_or_insert_res::> - (|| Box::new(RefCell::new(InputButtons::::new()))); + drop(event_queue); + let mut e = world.with_resource(|| InputButtons::::new()); + //let mut e = with_resource_mut(world, || InputButtons::::new()); e.add_input_from_winit(code, input.state); } }, @@ -293,22 +280,22 @@ impl InputEventUpdater { delta: Vec2::new(delta.0 as f32, delta.1 as f32) }; - world.trigger_event(delta); + event_queue.trigger_event(delta); }, InputEvent::CursorMoved { position, .. } => { let exact = MouseExact { pos: Vec2::new(position.x as f32, position.y as f32) }; - world.trigger_event(exact); + event_queue.trigger_event(exact); }, InputEvent::CursorEntered { .. } => { let event = CursorEnteredWindow {}; - world.trigger_event(event); + event_queue.trigger_event(event); }, InputEvent::CursorLeft { .. } => { let event = CursorLeftWindow {}; - world.trigger_event(event); + event_queue.trigger_event(event); }, InputEvent::MouseWheel { delta, .. } => { let event = match delta { @@ -320,7 +307,7 @@ impl InputEventUpdater { }, }; - world.trigger_event(event); + event_queue.trigger_event(event); }, //MouseButton InputEvent::MouseInput { button, state, .. } => { let button_event = match button { @@ -330,13 +317,15 @@ impl InputEventUpdater { winit::event::MouseButton::Other(v) => MouseButton::Other(*v), }; - world.trigger_event(button_event.clone()); + event_queue.trigger_event(button_event.clone()); + drop(event_queue); - let mut e = world.query_or_insert_res::> - (|| Box::new(RefCell::new(InputButtons::::new()))); + let mut e = world.with_resource(|| InputButtons::::new()); e.add_input_from_winit(button_event, state.clone()); }, InputEvent::Touch(t) => { + drop(event_queue); + let touch = Touch { phase: TouchPhase::from(t.phase), location: Vec2::new(t.location.x as f32, t.location.y as f32), @@ -347,9 +336,7 @@ impl InputEventUpdater { finger_id: t.id, }; - let mut touches = world.query_or_insert_res:: - (|| Box::new(RefCell::new(Touches::new()))); - + let mut touches = world.with_resource(|| Touches::new()); touches.touches.push(touch); }, _ => {}, @@ -363,32 +350,19 @@ impl SimpleSystem for InputEventUpdater { fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> { let world = &mut controls.world; - let queue = world.read_events::(); + let queue = world.get_resource_mut::() + .map(|q| q.read_events::()).flatten(); if queue.is_none() { return Ok(()); } - let queue = queue.unwrap(); - - // borrow checker isn't happy when I query multiple things :( - let mut events = queue.clone(); - drop(queue); + let mut events = queue.unwrap(); while let Some(event) = events.pop_front() { self.update(&event, world); } - /* 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/input_event.rs b/src/input_event.rs index 5850f11..dfeabbc 100755 --- a/src/input_event.rs +++ b/src/input_event.rs @@ -1,6 +1,6 @@ use winit::{event::{DeviceId, KeyboardInput, ModifiersState, MouseScrollDelta, TouchPhase, MouseButton, AxisId, Touch, WindowEvent, ElementState}, dpi::PhysicalPosition}; -use crate::ecs::resources::Resource; +use crate::ecs::resources::CastableAny; /// Wrapper around events from `winit::WindowEvent` that are specific to input related events. /// @@ -220,14 +220,4 @@ impl<'a> TryFrom<&'a WindowEvent<'a>> for InputEvent { _ => Err(InputEventConversionError::FromError(value)) } } -} - -impl Resource for InputEvent { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 65777a6..45ad4cd 100755 --- a/src/main.rs +++ b/src/main.rs @@ -6,16 +6,15 @@ mod ecs; mod math; mod input; -use std::cell::Ref; - +use atomicell::Ref; use ecs::components::mesh::MeshComponent; use ecs::components::transform::TransformComponent; +use edict::QueryIter; use game::Game; use input_event::InputEvent; use tracing::debug; -use crate::ecs::world::World; use crate::input::{InputEventUpdater, KeyCode, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton, InputButtons}; use crate::render::material::Material; use crate::render::texture::Texture; @@ -68,7 +67,7 @@ impl Point3d { #[async_std::main] async fn main() { - let mut world = World::new(); + let mut world = edict::World::new(); //world.spawn((Point2d::new(10, 10), Point3d::new(50, 50, 50))); @@ -91,10 +90,8 @@ async fn main() { camera.transform.rotate_z(Angle::Degrees(-90.0)); world.spawn((camera,)); - let jiggle_system = |world: &mut World| -> anyhow::Result<()> { - //let input: &InputEventUpdater = world.query_res().unwrap(); - - let keys = world.query_res(); + let jiggle_system = |world: &mut edict::World| -> anyhow::Result<()> { + let keys = world.get_resource(); if keys.is_none() { return Ok(()); } @@ -124,7 +121,16 @@ async fn main() { drop(keys); - for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() { + for transform in world.query_mut::<(&mut TransformComponent,)>().iter_mut() { + let t = &mut transform.transform; + //debug!("Translation: {}", t.translation); + + /* t.translation += glam::Vec3::new(0.0, 0.001, 0.0); + t.translation.x *= -1.0; */ + t.translation.x += dir_x; + t.translation.y += dir_y; + } + /* for (transform,) in world.query_mut::<(TransformComponent, )>().iter() { let t = &mut transform.transform; /* debug!("Translation: {}", t.translation); @@ -133,7 +139,7 @@ async fn main() { t.translation.x *= -1.0 */ t.translation.x += dir_x; t.translation.y += dir_y; - } + } */ Ok(()) }; diff --git a/src/math/angle.rs b/src/math/angle.rs index 2067a6d..105aede 100755 --- a/src/math/angle.rs +++ b/src/math/angle.rs @@ -10,6 +10,7 @@ pub fn radians_to_degrees(radians: f32) -> f32 { radians * 180.0 / PI } +#[derive(Clone)] pub enum Angle { Degrees(f32), Radians(f32), diff --git a/src/render/render_job.rs b/src/render/render_job.rs index 4411e6c..c331039 100755 --- a/src/render/render_job.rs +++ b/src/render/render_job.rs @@ -1,4 +1,4 @@ -use hecs::Entity; +use edict::EntityId; use crate::math::Transform; @@ -7,14 +7,14 @@ use super::{mesh::Mesh, material::Material}; pub struct RenderJob { mesh: Mesh, material: Material, - entity: Entity, + entity: EntityId, transform: Transform, last_transform: Option, // TODO: render interpolation } impl RenderJob { - pub fn new(mesh: Mesh, material: Material, entity: Entity, transform: Transform, last_transform: Option) -> Self { + pub fn new(mesh: Mesh, material: Material, entity: EntityId, transform: Transform, last_transform: Option) -> Self { Self { mesh, material, @@ -32,7 +32,7 @@ impl RenderJob { &self.material } - pub fn entity(&self)-> Entity { + pub fn entity(&self)-> EntityId { self.entity } diff --git a/src/render/renderer.rs b/src/render/renderer.rs index afbc29d..049eaf2 100755 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -6,17 +6,16 @@ use std::borrow::Cow; use async_std::sync::Mutex; use async_trait::async_trait; +use atomicell::{AtomicCell, RefMut}; +use edict::{EntityId, Entities}; use tracing::{debug, warn}; use wgpu::{BindGroup, BindGroupLayout}; use wgpu::util::DeviceExt; use winit::window::Window; -use hecs::Entity; - use crate::ecs::components::camera::CameraComponent; use crate::ecs::components::mesh::MeshComponent; use crate::ecs::components::transform::TransformComponent; -use crate::ecs::world::World; use crate::math::{Transform, Angle}; use crate::resources; @@ -25,11 +24,10 @@ use super::desc_buf_lay::DescVertexBufferLayout; use super::texture::RenderTexture; use super::{render_pipeline::FullRenderPipeline, vertex::{VERTICES}, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh}; -#[async_trait] pub trait Renderer { - async fn prepare(&mut self, main_world: &mut World); - async fn render(&mut self) -> Result<(), wgpu::SurfaceError>; - async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize); + fn prepare(&mut self, main_world: &mut edict::World); + fn render(&mut self) -> Result<(), wgpu::SurfaceError>; + fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize); fn surface_size(&self) -> winit::dpi::PhysicalSize; fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc); @@ -57,7 +55,7 @@ pub struct BasicRenderer { pub render_pipelines: HashMap>, pub render_jobs: VecDeque, - buffer_storage: HashMap, // TODO: clean up left over buffers from deleted entities/components + buffer_storage: HashMap, // TODO: clean up left over buffers from deleted entities/components transform_buffer: wgpu::Buffer, transform_bind_group: wgpu::BindGroup, @@ -346,10 +344,10 @@ impl BasicRenderer { } } -#[async_trait] impl Renderer for BasicRenderer { - async fn prepare(&mut self, main_world: &mut World) { - for (entity, (model, transform)) in main_world.query::<(&MeshComponent, &TransformComponent)>().iter() { + fn prepare(&mut self, main_world: &mut edict::World) { + + for (entity, model, transform) in main_world.query::<(Entities, &MeshComponent, &TransformComponent)>().iter() { // Create the render job and push it to the queue let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None); self.render_jobs.push_back(job); @@ -360,8 +358,7 @@ impl Renderer for BasicRenderer { } } - // Find the active camera - if let Some((_e, (camera,))) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() { + if let Some(camera) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() { let view_proj = self.inuse_camera.update_view_projection(camera); self.queue.write_buffer(&self.camera_buffer, 0, bytemuck::cast_slice(&[view_proj.clone()])); } else { @@ -369,7 +366,7 @@ impl Renderer for BasicRenderer { } } - async fn render(&mut self) -> Result<(), wgpu::SurfaceError> { + fn render(&mut self) -> Result<(), wgpu::SurfaceError> { let output = self.surface.get_current_texture()?; let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); @@ -434,7 +431,7 @@ impl Renderer for BasicRenderer { Ok(()) } - async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize) { + fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize) { if new_size.width > 0 && new_size.height > 0 { self.size = new_size; self.config.width = new_size.width;