diff --git a/lyra-game/src/game.rs b/lyra-game/src/game.rs index 4a349d4..7633257 100755 --- a/lyra-game/src/game.rs +++ b/lyra-game/src/game.rs @@ -1,10 +1,8 @@ -use std::{cell::OnceCell, collections::VecDeque, ptr::NonNull, sync::Arc}; +use std::{cell::OnceCell, collections::VecDeque, ptr::NonNull}; -use async_std::task::block_on; use lyra_ecs::{system::{IntoSystem, System}, ResourceObject, World}; -use lyra_math::{IVec2, Vec2}; -use rustc_hash::FxHashMap; -use tracing::{debug, debug_span, info, warn, error, Level}; +use lyra_math::IVec2; +use tracing::{info, error, Level}; use tracing_appender::non_blocking; use tracing_subscriber::{ layer::SubscriberExt, @@ -12,9 +10,7 @@ use tracing_subscriber::{ util::SubscriberInitExt, fmt, }; -use winit::{application::ApplicationHandler, event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, keyboard::{Key, NamedKey}, window::{Window, WindowId}}; - -use crate::{change_tracker::Ct, input::InputEvent, plugin::Plugin, render::{renderer::{BasicRenderer, Renderer}, window::{PrimaryWindow, WindowOptions}}, winit::WinitWindows, EventQueue, Stage, StagedExecutor}; +use crate::{plugin::Plugin, render::renderer::Renderer, Stage, StagedExecutor}; #[derive(Clone, Copy, Hash, Debug)] pub enum GameStages { @@ -54,8 +50,7 @@ impl WindowState { } pub struct App { - windows: FxHashMap>, - renderer: OnceCell>, + pub(crate) renderer: OnceCell>, pub world: World, plugins: VecDeque>, startup_systems: VecDeque>, @@ -97,7 +92,6 @@ impl App { staged.add_stage_after(GameStages::PostUpdate, GameStages::Last); Self { - windows: FxHashMap::default(), renderer: OnceCell::new(), world, plugins: Default::default(), @@ -115,13 +109,13 @@ impl App { } } - fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize) { + pub(crate) fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize) { self.renderer.get_mut() .expect("renderer was not initialized") .on_resize(&mut self.world, new_size); } - fn on_exit(&mut self) { + pub(crate) fn on_exit(&mut self) { info!("On exit!"); } @@ -221,109 +215,3 @@ impl App { f(self); } } - -impl ApplicationHandler for App { - fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { - debug!("update now"); - - self.update(); - - let renderer = self.renderer.get_mut().expect("renderer was not initialized"); - renderer.prepare(&mut self.world); - - if let Some(mut event_queue) = self.world.try_get_resource_mut::() { - event_queue.update_events(); - } - - match renderer.render() { - Ok(_) => {} - // Reconfigure the surface if lost - //Err(wgpu::SurfaceError::Lost) => self.on_resize(.surface_size()), - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => { - error!("OOM"); - event_loop.exit(); - } - // All other errors (Outdated, Timeout) should be resolved by the next frame - Err(e) => eprintln!("{:?}", e), - } - } - - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { - let world = &mut self.world; - let en = world.spawn((WindowOptions::default(), PrimaryWindow)); - - let attr = Window::default_attributes(); - let mut windows = world.get_resource_mut::(); - let wid = windows.create_window(event_loop, en, attr).unwrap(); - let window = windows.windows.get(&wid).unwrap().clone(); - drop(windows); - - let renderer = block_on(BasicRenderer::create_with_window(world, window)); - if self.renderer.set(Box::new(renderer)).is_err() { - warn!("renderer was re-initialized"); - } - } - - fn window_event( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - window_id: winit::window::WindowId, - event: WindowEvent, - ) { - //let _e = debug_span!("window_event", window=window_id).entered(); - let windows = self.world.get_resource::(); - let window = match windows.windows.get(&window_id) { - Some(w) => w.clone(), - None => return, - }; - drop(windows); - - // If try_from failed, that means that the WindowEvent is not an - // input related event. - if let Some(input_ev) = InputEvent::from_window_event(&event) { - // 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. - if let Some(mut event_queue) = self.world.try_get_resource_mut::() { - event_queue.trigger_event(input_ev.clone()); - } - } else { - - match event { - WindowEvent::ActivationTokenDone { serial, token } => todo!(), - WindowEvent::Resized(physical_size) => { - self.on_resize(physical_size); - }, - WindowEvent::Moved(physical_position) => { - let mut state = self.world.get_resource_or_else(WindowState::new); - state.position = IVec2::new(physical_position.x, physical_position.y); - }, - WindowEvent::CloseRequested => { - self.on_exit(); - event_loop.exit(); - }, - WindowEvent::Destroyed => todo!(), - WindowEvent::DroppedFile(path_buf) => todo!(), - WindowEvent::HoveredFile(path_buf) => todo!(), - WindowEvent::HoveredFileCancelled => todo!(), - WindowEvent::Focused(focused) => { - let mut state = self.world.get_resource_or_else(WindowState::new); - state.focused = focused; - }, - WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers), - WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer } => { - info!("changed scale to {scale_factor}"); - }, - WindowEvent::ThemeChanged(theme) => todo!(), - WindowEvent::Occluded(occ) => { - let mut state = self.world.get_resource_or_else(WindowState::new); - state.occluded = occ; - }, - WindowEvent::RedrawRequested => { - debug!("should redraw"); - }, - _ => {} - } - } - } -} diff --git a/lyra-game/src/plugin.rs b/lyra-game/src/plugin.rs index af4253d..3601770 100644 --- a/lyra-game/src/plugin.rs +++ b/lyra-game/src/plugin.rs @@ -1,9 +1,3 @@ -use std::cell::Cell; -use std::cell::OnceCell; -use std::cell::RefCell; -use std::ptr::NonNull; - -use lyra_ecs::system::System; use lyra_ecs::CommandQueue; use lyra_resource::ResourceManager; @@ -41,18 +35,6 @@ impl

Plugin for P } } -/// An ECS system converted to a plugin. -/// -/// The system is executed in plugin setup phase. -pub(crate) struct SystemPlugin(pub RefCell); - -impl Plugin for SystemPlugin { - fn setup(&self, app: &mut App) { - let mut s = self.0.borrow_mut(); - s.execute(NonNull::from(&app.world)); - } -} - /// Represents a set of plugins that will be executed in order they are supplied. #[derive(Default)] pub struct PluginSet { diff --git a/lyra-game/src/winit/mod.rs b/lyra-game/src/winit/mod.rs index 727a96a..cdfa8ec 100644 --- a/lyra-game/src/winit/mod.rs +++ b/lyra-game/src/winit/mod.rs @@ -1,11 +1,13 @@ use std::sync::Arc; +use async_std::task::block_on; +use glam::IVec2; use lyra_ecs::Entity; use rustc_hash::FxHashMap; -use tracing::debug; -use winit::{application::ApplicationHandler, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}}; +use tracing::{debug, error, info, warn}; +use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}}; -use crate::{game::App, plugin::Plugin, render::window::WindowOptions}; +use crate::{game::{App, WindowState}, input::InputEvent, plugin::Plugin, render::{renderer::BasicRenderer, window::{PrimaryWindow, WindowOptions}}, EventQueue}; #[derive(Default)] pub struct WinitPlugin; @@ -16,15 +18,15 @@ impl Plugin for WinitPlugin { app.add_resource(WinitWindows::default()); } - fn is_ready(&self, app: &mut crate::game::App) -> bool { + fn is_ready(&self, _app: &mut crate::game::App) -> bool { true } - fn complete(&self, app: &mut crate::game::App) { + fn complete(&self, _app: &mut crate::game::App) { } - fn cleanup(&self, app: &mut crate::game::App) { + fn cleanup(&self, _app: &mut crate::game::App) { } } @@ -52,37 +54,122 @@ impl WinitWindows { } } -pub fn winit_app_runner(mut app: App) { +pub fn winit_app_runner(app: App) { let evloop = EventLoop::new() .expect("failed to create winit EventLoop"); - evloop.run_app(&mut app) + let mut winit_runner = WinitRunner { + app, + }; + evloop.run_app(&mut winit_runner) .expect("loop error"); } -/* struct WinitRunner { +struct WinitRunner { app: App } impl ApplicationHandler for WinitRunner { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - debug!("resumed") + fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + debug!("update now"); + + self.app.update(); + + let renderer = self.app.renderer.get_mut().expect("renderer was not initialized"); + renderer.prepare(&mut self.app.world); + + if let Some(mut event_queue) = self.app.world.try_get_resource_mut::() { + event_queue.update_events(); + } + + match renderer.render() { + Ok(_) => {} + // Reconfigure the surface if lost + //Err(wgpu::SurfaceError::Lost) => self.on_resize(.surface_size()), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + error!("OOM"); + event_loop.exit(); + } + // All other errors (Outdated, Timeout) should be resolved by the next frame + Err(e) => eprintln!("{:?}", e), + } + } + + fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + let world = &mut self.app.world; + let en = world.spawn((WindowOptions::default(), PrimaryWindow)); + + let attr = Window::default_attributes(); + let mut windows = world.get_resource_mut::(); + let wid = windows.create_window(event_loop, en, attr).unwrap(); + let window = windows.windows.get(&wid).unwrap().clone(); + drop(windows); + + let renderer = block_on(BasicRenderer::create_with_window(world, window)); + if self.app.renderer.set(Box::new(renderer)).is_err() { + warn!("renderer was re-initialized"); + } } fn window_event( &mut self, - event_loop: &ActiveEventLoop, - window_id: WindowId, - event: winit::event::WindowEvent, + event_loop: &winit::event_loop::ActiveEventLoop, + window_id: winit::window::WindowId, + event: WindowEvent, ) { - let world = &mut self.app.world; - let mut windows = world.get_resource_mut::(); - - let window = match windows.windows.get_mut(&window_id) { - Some(w) => w, + let windows = self.app.world.get_resource::(); + let window = match windows.windows.get(&window_id) { + Some(w) => w.clone(), None => return, }; + drop(windows); - + // If try_from failed, that means that the WindowEvent is not an + // input related event. + if let Some(input_ev) = InputEvent::from_window_event(&event) { + // 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. + if let Some(mut event_queue) = self.app.world.try_get_resource_mut::() { + event_queue.trigger_event(input_ev.clone()); + } + } else { + + match event { + WindowEvent::ActivationTokenDone { serial, token } => todo!(), + WindowEvent::Resized(physical_size) => { + self.app.on_resize(physical_size); + }, + WindowEvent::Moved(physical_position) => { + let mut state = self.app.world.get_resource_or_else(WindowState::new); + state.position = IVec2::new(physical_position.x, physical_position.y); + }, + WindowEvent::CloseRequested => { + self.app.on_exit(); + event_loop.exit(); + }, + WindowEvent::Destroyed => todo!(), + WindowEvent::DroppedFile(path_buf) => todo!(), + WindowEvent::HoveredFile(path_buf) => todo!(), + WindowEvent::HoveredFileCancelled => todo!(), + WindowEvent::Focused(focused) => { + let mut state = self.app.world.get_resource_or_else(WindowState::new); + state.focused = focused; + }, + WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers), + WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer } => { + info!("changed scale to {scale_factor}"); + }, + WindowEvent::ThemeChanged(theme) => todo!(), + WindowEvent::Occluded(occ) => { + let mut state = self.app.world.get_resource_or_else(WindowState::new); + state.occluded = occ; + }, + WindowEvent::RedrawRequested => { + debug!("should redraw"); + }, + _ => {} + } + } } -} */ \ No newline at end of file +} \ No newline at end of file