diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..85af48d --- /dev/null +++ b/src/app.rs @@ -0,0 +1,3 @@ +pub struct App { + +} \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index b4aaa8a..01ed209 100755 --- a/src/game.rs +++ b/src/game.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{sync::Arc, collections::VecDeque}; use async_std::{task::block_on, sync::Mutex}; @@ -14,7 +14,7 @@ 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}, input_event::InputEvent, ecs::{SimpleSystem, SystemDispatcher, EventQueue, Events}, input::InputSystem}; +use crate::{render::renderer::{Renderer, BasicRenderer}, input_event::InputEvent, ecs::{SimpleSystem, SystemDispatcher, EventQueue, Events}, input::InputSystem, plugin::Plugin}; pub struct Controls<'a> { pub world: &'a mut edict::World, @@ -36,14 +36,14 @@ struct GameLoop { window: Arc, renderer: Box, - world: Arc>, + world: edict::World, /// higher priority systems engine_sys_dispatcher: SystemDispatcher, user_sys_dispatcher: SystemDispatcher, } impl GameLoop { - pub async fn new(window: Arc, world: Arc>, user_systems: SystemDispatcher) -> GameLoop { + pub async fn new(window: Arc, world: edict::World, user_systems: SystemDispatcher) -> GameLoop { Self { window: Arc::clone(&window), renderer: Box::new(BasicRenderer::create_with_window(window).await), @@ -60,8 +60,7 @@ impl GameLoop { pub async fn on_init(&mut self) { // Create the EventQueue resource in the world - let mut world = self.world.lock().await; - world.insert_resource(EventQueue::new()); + self.world.insert_resource(EventQueue::new()); } pub fn run_sync(&mut self, event: Event<()>, control_flow: &mut ControlFlow) { @@ -69,10 +68,8 @@ impl GameLoop { } async fn update(&mut self) { - let mut world = self.world.lock().await; - let mut controls = Controls { - world: &mut world, + world: &mut self.world, }; if let Err(e) = self.engine_sys_dispatcher.execute_mut(&mut controls) { @@ -102,18 +99,14 @@ impl GameLoop { // TODO: Create system for this? or maybe merge into input system, idk InputEvent::CursorEntered { .. } => { - let mut world = self.world.lock().await; - - let mut state = world.with_resource(|| WindowState::new()); + let mut state = self.world.with_resource(|| WindowState::new()); state.is_cursor_inside_window = true; None }, InputEvent::CursorLeft { .. } => { - let mut world = self.world.lock().await; - - let mut state = world.with_resource(|| WindowState::new()); + let mut state = self.world.with_resource(|| WindowState::new()); state.is_cursor_inside_window = false; None @@ -127,14 +120,6 @@ impl GameLoop { } } - fn render_window() { - todo!() - } - - fn render_item() { - todo!() - } - fn on_exit(&mut self) { info!("On exit!"); } @@ -145,16 +130,14 @@ impl GameLoop { Event::DeviceEvent { device_id, event } => match event { // convert a MouseMotion event to an InputEvent DeviceEvent::MouseMotion { delta } => { - 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.get_resource::() { + let trigger = match self.world.get_resource::() { Some(window_state) if window_state.is_focused && window_state.is_cursor_inside_window => true, _ => false, }; if trigger { - let event_queue = world.with_resource(|| Events::::new()); + let event_queue = self.world.with_resource(|| Events::::new()); let input_event = InputEvent::MouseMotion { device_id, delta, }; event_queue.push_back(input_event); @@ -173,8 +156,7 @@ 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 world = self.world.lock().await; - if let Some(mut event_queue) = world.get_resource_mut::() { + if let Some(mut event_queue) = self.world.get_resource_mut::() { event_queue.trigger_event(input_event.clone()); }; } @@ -199,9 +181,7 @@ impl GameLoop { }, WindowEvent::Focused(is_focused) => { - let mut world = self.world.lock().await; - - let mut state = world.with_resource(|| WindowState::new()); + let mut state = self.world.with_resource(|| WindowState::new()); state.is_focused = *is_focused; }, @@ -219,12 +199,10 @@ impl GameLoop { debug!("FPS: {}fps, {:.2}ms/frame", fps, self.fps_counter.get_tick_time()); } */ - let mut world = self.world.lock().await; - self.renderer.as_mut().prepare(&mut world); - if let Some(mut event_queue) = world.get_resource_mut::() { + self.renderer.as_mut().prepare(&mut self.world); + if let Some(mut event_queue) = self.world.get_resource_mut::() { event_queue.update_events(); } - drop(world); match self.renderer.as_mut().render() { Ok(_) => {} @@ -246,14 +224,16 @@ impl GameLoop { } pub struct Game { - world: Option>>, + pub world: Option, + plugins: VecDeque>, system_dispatcher: Option, } impl Default for Game { fn default() -> Self { Self { - world: None, + world: Some(edict::World::new()), + plugins: VecDeque::new(), system_dispatcher: Some(SystemDispatcher::new()), } } @@ -261,55 +241,33 @@ impl Default for Game { impl Game { pub async fn initialize() -> Game { - /* let filter = FilterFn::new(|metadata| { - metadata.module_path() - .unwrap_or_else(|| metadata.target()) - .starts_with("lyra_engine") && (LevelFilter::DEBUG >= metadata.level().to_owned()) - }); - - let layer = tracing_subscriber::fmt::layer(); - - tracing_subscriber::registry() - .with(layer.with_filter(filter)) - .init(); */ - - - /* tracing_subscriber::registry() - .with(fmt::layer().with_writer(stdout_layer)) - .with(filter::Targets::new() - .with_target("lyra_engine", Level::TRACE) - .with_default(Level::DEBUG)) - .init(); */ - - /* tracing_subscriber::fmt() - .with_max_level(Level::DEBUG) - .init(); */ - - info!("dheiudfgbwehifwe"); - let mut def = Self::default(); - def.system_dispatcher.as_mut().unwrap().add_system("input", InputSystem::new(), &[]); + //def.system_dispatcher.add_system("input", InputSystem::new(), &[]); def } - 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 { - self.world = Some(world); - - self - } - pub fn with_system(&mut self, name: &str, system: S, depends: &[&str]) -> &mut Self where S: SimpleSystem + 'static { - let dispatcher = self.system_dispatcher.as_mut().unwrap(); - dispatcher.add_system(name, system, depends); + let system_dispatcher = self.system_dispatcher.as_mut().unwrap(); + system_dispatcher.add_system(name, system, depends); + + self + } + + /// Add a plugin to the game + pub fn with_plugin

(&mut self, plugin: P) -> &mut Self + where + P: Plugin + 'static + { + self.plugins.push_back(Box::new(plugin)); + + self + } + + pub fn with_world(&mut self, world: edict::World) -> &mut Self { + self.world = Some(world); self } @@ -323,16 +281,19 @@ impl Game { .with_target("lyra_engine", Level::TRACE) .with_default(Level::INFO)) .init(); - - let world = self.world.take().expect("ECS World was never given to Game!"); + // setup all the plugins + while let Some(plugin) = self.plugins.pop_front() { + plugin.as_ref().setup(self); + } + + // start winit event loops 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, systems).await; - + let world = self.world.take().unwrap_or_else(|| edict::World::new()); + let system_dispatcher = self.system_dispatcher.take().unwrap(); + let mut g_loop = GameLoop::new(Arc::clone(&window), world, system_dispatcher).await; g_loop.on_init().await; event_loop.run(move |event, _, control_flow| { diff --git a/src/input.rs b/src/input.rs index 95b9410..4d71d08 100755 --- a/src/input.rs +++ b/src/input.rs @@ -5,7 +5,7 @@ use glam::Vec2; use tracing::{warn, debug}; use winit::event::{ElementState, MouseScrollDelta}; -use crate::{ecs::{SimpleSystem, EventQueue}, input_event::InputEvent}; +use crate::{ecs::{SimpleSystem, EventQueue}, input_event::InputEvent, plugin::Plugin}; pub type KeyCode = winit::event::VirtualKeyCode; @@ -84,8 +84,6 @@ impl From for Force { } } -/// -/// /// Translated `WindowEvent::Touch` from `winit` crate #[derive(Clone, Debug, PartialEq)] pub struct Touch { @@ -206,22 +204,6 @@ trait InputStorage { 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. @@ -365,4 +347,30 @@ impl SimpleSystem for InputSystem { Ok(()) } +} + +fn input_system_fn(world: &mut edict::World) -> anyhow::Result<()> { + //let world = &mut controls.world; + + let queue = world.get_resource_mut::() + .map(|q| q.read_events::()).flatten(); + + if queue.is_none() { + return Ok(()); + } + + let mut events = queue.unwrap(); + let mut input = InputSystem::new(); + + while let Some(event) = events.pop_front() { + input.update(&event, world); + } + + Ok(()) +} + +impl Plugin for InputSystem { + fn setup(&self, game: &mut crate::game::Game) { + game.with_system("input", input_system_fn, &[]); + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 4540345..886723b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,4 +5,6 @@ pub mod resources; pub mod ecs; pub mod math; pub mod input; -pub mod castable_any; \ No newline at end of file +pub mod castable_any; +pub mod plugin; +pub mod app; \ No newline at end of file diff --git a/src/plugin.rs b/src/plugin.rs new file mode 100644 index 0000000..762f441 --- /dev/null +++ b/src/plugin.rs @@ -0,0 +1,7 @@ +use crate::game::Game; + +pub trait Plugin { + /// Setup this plugin. This runs before the game has started + fn setup(&self, game: &mut Game); +} +