diff --git a/Cargo.lock b/Cargo.lock index adf963e..3665a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1380,6 +1380,7 @@ dependencies = [ "raidillon_engine", "raidillon_glium", "raidillon_platform", + "winit", ] [[package]] diff --git a/engine/src/system.rs b/engine/src/system.rs index 18eb01e..cd4c1d4 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -15,10 +15,10 @@ pub struct SystemContext<'a> { pub trait System { /// Initialize the system. - fn initialize(&mut self); + fn initialize(&mut self) {} /// Spawn the first entities of the world. - fn load_world(&mut self, ctx: &mut SystemContext); - fn update(&mut self, ctx: &mut SystemContext); + fn load_world(&mut self, ctx: &mut SystemContext) {} + fn update(&mut self, ctx: &mut SystemContext) {} } pub type SystemID = &'static str; diff --git a/game/Cargo.toml b/game/Cargo.toml index 0e1d7e9..484e434 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -15,3 +15,4 @@ raidillon_ecs = { path = "../ecs" } raidillon_engine = { path = "../engine" } raidillon_glium = { path = "../glium_platform", optional = true } glam = "0.30.5" +winit = "0.30.12" diff --git a/game/src/main.rs b/game/src/main.rs index c19ca94..a02b359 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -11,15 +11,39 @@ use raidillon_core::scene::Scene; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; use raidillon_core::DebugUIBuffer; +use winit::event::{Event, WindowEvent}; const TEST_GLTF: &str = "pink-monkey.gltf"; const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; +const UPDATE_ASPECT_RATIO_SYSTEM: &str = "update_aspect_ratio_system"; + const MAIN_SCENE_ID: &str = "main_scene"; -struct RenderingTestSystem; +struct UpdateAspectRatioSystem; +impl System for UpdateAspectRatioSystem { + fn initialize(&mut self) {} + fn load_world(&mut self, ctx: &mut SystemContext) {} + + fn update(&mut self, ctx: &mut SystemContext) { + // FIXME: Need an event handler rework for systems. + match &ctx.platform_context.current_event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(sz) => { + let _ = ctx.scene.world.query_mut::<&mut Camera>().into_iter().map(|mut cam| { + cam.1.aspect = sz.width as f32 / sz.height as f32; + }); + } + _ => {} + }, + _ => {} + } + } +} + +struct RenderingTestSystem; impl System for RenderingTestSystem { fn initialize(&mut self) {} fn load_world(&mut self, ctx: &mut SystemContext) { @@ -61,6 +85,7 @@ fn main() { // engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem); // engine.system_manager.add_system("movement".to_string(), MovementSystem); engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem)); + engine.system_manager.add_system(UPDATE_ASPECT_RATIO_SYSTEM, Box::new(UpdateAspectRatioSystem)); // Set up the scene let main_scene = Scene::new( diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index c01cf60..34864c3 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -75,6 +75,11 @@ impl Platform for GliumPlatform { }; self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.handle_event(&mut self.window, event.clone())); + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => { @@ -93,9 +98,10 @@ impl Platform for GliumPlatform { debug_ui_buffer, }; - for (system_id, system) in self.rendering_system_manager.systems.iter_mut() { - system.render(&mut context); - } + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.render(&mut context)); target.finish().unwrap(); } _ => {}, @@ -104,6 +110,10 @@ impl Platform for GliumPlatform { let mut ctx2 = ctx.clone(); ctx2.current_event = event.clone(); self.engine.update(ctx2); + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.prepare_frame(&mut self.window)); self.window.request_redraw(); } _ => {}, diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs index 3f141c5..ff29fe1 100644 --- a/glium_platform/src/render/debug_ui.rs +++ b/glium_platform/src/render/debug_ui.rs @@ -1,70 +1,55 @@ -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::Arc; use std::time::Instant; use glium::Display; use glium::glutin::surface::WindowSurface; use imgui::{Context as ImguiContext}; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_glium_renderer::Renderer as ImguiGliumRenderer; -use winit::raw_window_handle::DisplayHandle; use winit::window::Window; -use anyhow::{Result}; +use winit::event::Event; +use glium::Frame; use crate::RenderingSystem; use crate::system::RenderingContext; -use glium::Frame; -use raidillon_core::DebugUIBuffer; pub struct ImguiBridge { imgui: ImguiContext, platform: WinitPlatform, renderer: ImguiGliumRenderer, -} - -impl ImguiBridge { - pub fn render(&mut self, target: &mut Frame, window: &Window, build_ui: F) - where - F: FnOnce(&imgui::Ui), - { - let ui = self.imgui.frame(); - - build_ui(&ui); - - self.platform.prepare_render(ui, window); - let draw_data = self.imgui.render(); - - self - .renderer - .render(target, draw_data) - .expect("imgui rendering failed"); - } - - // pub fn initialize_frame(&mut self) -> &mut imgui::Ui { - // self.imgui.frame() - // } - // - // pub fn finish_frame(&mut self, target: &mut Frame, window: &Window, ui: imgui::Ui) { - // self.platform.prepare_render(&ui, window); - // let draw_data = self.imgui.render(); - // self.renderer.render(target, draw_data).expect("imgui rendering failed"); - // } + last_frame: Instant, + rendered_this_frame: bool, } impl RenderingSystem for ImguiBridge { - fn render(&mut self, ctx: &mut RenderingContext) { - let mut ui = self.imgui.frame(); + fn handle_event(&mut self, window: &mut Window, event: Event<()>) { + self.platform.handle_event(self.imgui.io_mut(), window, &event); + } - ctx.debug_ui_buffer.borrow_mut().write_buffer(&mut ui); + fn prepare_frame(&mut self, window: &mut Window) { + self.rendered_this_frame = false; + let now = Instant::now(); + self.imgui.io_mut().update_delta_time(now - self.last_frame); + self.last_frame = now; + self.platform + .prepare_frame(self.imgui.io_mut(), window) + .expect("Failed to prepare frame"); + } + + fn render(&mut self, ctx: &mut RenderingContext) { + if self.rendered_this_frame { return; } + self.rendered_this_frame = true; + + let ui = self.imgui.frame(); + ctx.debug_ui_buffer.borrow().write_buffer(&ui); self.platform.prepare_render(&ui, ctx.window); let draw_data = self.imgui.render(); + if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 { + return; + } + self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); } - fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self - where - Self: Sized, - { + fn initialize(display: &Display, window: &Window) -> Self { let mut imgui = ImguiContext::create(); imgui.set_ini_filename(None); let mut platform = WinitPlatform::new(&mut imgui); @@ -76,6 +61,8 @@ impl RenderingSystem for ImguiBridge { imgui, platform, renderer, + last_frame: Instant::now(), + rendered_this_frame: false, } } -} \ No newline at end of file +} diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 3c21a04..6a31a2d 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -19,6 +19,8 @@ pub struct RenderingContext<'a> { /// The internal "rendering system" trait of glium_platform. /// This is unrelated to the main System trait in core. pub trait RenderingSystem { + fn handle_event(&mut self, window: &mut glium::winit::window::Window, event: winit::event::Event<()>) {} + fn prepare_frame(&mut self, window: &mut glium::winit::window::Window) {} fn render(&mut self, ctx: &mut RenderingContext); fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self where Self: Sized; }