use std::collections::HashMap; use std::sync::Arc; use super::render::render_context::RenderContext; use super::render::vulkan_context::VulkanContext; use crate::core::input::InputManager; use crate::core::scene::SceneManager; use crate::core::timer::Timer; use crate::game::main_scene::MainScene; use egui_winit_vulkano::{Gui, GuiConfig, egui}; use vulkano::command_buffer::{ AutoCommandBufferBuilder, CommandBufferUsage, RenderingAttachmentInfo, RenderingInfo, }; use vulkano::pipeline::graphics::viewport::Viewport; use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp}; use vulkano::swapchain::PresentMode; use vulkano::sync::GpuFuture; use vulkano_util::context::VulkanoContext; use vulkano_util::renderer::VulkanoWindowRenderer; use vulkano_util::window::{VulkanoWindows, WindowDescriptor}; use winit::application::ApplicationHandler; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; pub struct App { vulkan_context: Arc, vulkano_windows: Arc, gui: HashMap, clear_color: [f32; 3], input_manager: InputManager, scene_manager: SceneManager, timer: Timer, } impl From<(&VulkanContext, &VulkanoWindowRenderer)> for RenderContext { fn from((vulkan_context, renderer): (&VulkanContext, &VulkanoWindowRenderer)) -> Self { RenderContext::new( vulkan_context.vulkano_context().instance().clone(), vulkan_context.vulkano_context().device().clone(), vulkan_context.vulkano_context().graphics_queue().clone(), vulkan_context.vulkano_context().compute_queue().clone(), vulkan_context.vulkano_context().transfer_queue().cloned(), vulkan_context.vulkano_context().memory_allocator().clone(), vulkan_context.command_buffer_allocator().clone(), vulkan_context.descriptor_set_allocator().clone(), renderer.resolution(), renderer.aspect_ratio(), renderer.swapchain_format(), ) } } impl App { pub fn new(vulkano_context: VulkanoContext, input_manager: InputManager) -> Self { Self { vulkan_context: Arc::new(VulkanContext::new(vulkano_context)), vulkano_windows: Arc::new(VulkanoWindows::default()), gui: HashMap::new(), clear_color: [0.0, 0.0, 0.0], input_manager, scene_manager: SceneManager::new(), timer: Timer::new(), } } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { if let Some(vulkano_windows) = Arc::get_mut(&mut self.vulkano_windows) { let window_id = vulkano_windows.create_window( event_loop, self.vulkan_context.vulkano_context(), &WindowDescriptor { title: "Rust ASH Test".to_string(), width: 800.0, height: 600.0, present_mode: PresentMode::Fifo, ..Default::default() }, |_| {}, ); let gui = { let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap(); Gui::new( event_loop, renderer.surface(), renderer.graphics_queue(), renderer.swapchain_format(), GuiConfig { is_overlay: true, ..Default::default() }, ) }; self.gui.insert(window_id, gui); } self.scene_manager .load_scene(Box::new(MainScene::default())); } fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { let renderer = Arc::get_mut(&mut self.vulkano_windows) .unwrap() .get_renderer_mut(id) .unwrap(); let gui = self.gui.get_mut(&id).unwrap(); let render_context = RenderContext::from((self.vulkan_context.as_ref(), &*renderer)); if !gui.update(&event) { self.input_manager.process_window_event(&event); } match event { WindowEvent::CloseRequested => { log::debug!("The close button was pressed; stopping"); event_loop.exit(); } WindowEvent::Resized(_) => { renderer.resize(); } WindowEvent::ScaleFactorChanged { .. } => { renderer.resize(); } WindowEvent::RedrawRequested => { self.input_manager.update(); self.timer.update(); self.scene_manager.load_scene_if_not_loaded(&render_context); if let Some(scene) = self.scene_manager.current_scene_mut() { scene.update(&render_context, &self.input_manager, &self.timer); } let acquire_future = renderer.acquire(None, |_| {}).unwrap(); let mut builder = AutoCommandBufferBuilder::primary( self.vulkan_context.command_buffer_allocator().clone(), self.vulkan_context .vulkano_context() .graphics_queue() .queue_family_index(), CommandBufferUsage::OneTimeSubmit, ) .unwrap(); { let viewport = Viewport { offset: [0.0, 0.0], extent: renderer.resolution(), depth_range: 0.0..=1.0, }; builder .begin_rendering(RenderingInfo { color_attachments: vec![Some(RenderingAttachmentInfo { load_op: AttachmentLoadOp::Clear, store_op: AttachmentStoreOp::Store, clear_value: Some(self.clear_color.into()), ..RenderingAttachmentInfo::image_view( renderer.swapchain_image_view().clone(), ) })], ..Default::default() }) .unwrap() .set_viewport(0, [viewport].into_iter().collect()) .unwrap(); } if let Some(scene) = self.scene_manager.current_scene() { scene.render(&render_context, &mut builder); } builder.end_rendering().unwrap(); let command_buffer = builder.build().unwrap(); let render_future = acquire_future .then_execute( self.vulkan_context .vulkano_context() .graphics_queue() .clone(), command_buffer, ) .unwrap(); gui.immediate_ui(|gui| { let ctx = gui.context(); egui::Window::new("Informations") .vscroll(true) .show(&ctx, |ui| { ui.label(format!("Resolution: {:?}", renderer.resolution())); ui.color_edit_button_rgb(&mut self.clear_color); ui.label(format!("{:#?}", self.input_manager.get_virtual_input())); ui.label(format!("Delta time: {:?}", self.timer.delta_time())); }); }); let render_future = gui.draw_on_image(render_future, renderer.swapchain_image_view()); renderer.present(render_future.boxed(), true); } _ => {} } } fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { let window = self.vulkano_windows.get_primary_window().unwrap(); window.request_redraw(); } }