use std::collections::HashMap; use crate::render::scene::Scene; 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::window::{VulkanoWindows, WindowDescriptor}; use winit::application::ApplicationHandler; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::WindowId; use super::input::{InputState, KeyState}; use super::vulkan_context::VulkanContext; pub struct App { vulkan_context: VulkanContext, vulkano_windows: VulkanoWindows, gui: HashMap, scene: Option, clear_color: [f32; 3], input_state: InputState, } impl From for App { fn from(vulkano_context: VulkanoContext) -> Self { Self { vulkan_context: VulkanContext::new(vulkano_context), vulkano_windows: VulkanoWindows::default(), gui: HashMap::new(), scene: None, clear_color: [0.0, 0.0, 0.0], input_state: InputState::default(), } } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { let window_id = self.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 = self.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 = Some( Scene::load( &self.vulkan_context, self.vulkano_windows.get_primary_renderer_mut().unwrap(), ) .unwrap(), ); } fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { let renderer = self.vulkano_windows.get_renderer_mut(id).unwrap(); let gui = self.gui.get_mut(&id).unwrap(); if !gui.update(&event) { self.input_state.process_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_state.update(); 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.as_ref() { scene .render(&self.vulkan_context, renderer, &mut builder) .unwrap(); } 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!( "Mouse position: {:?}", self.input_state.get_mouse_state().position )); ui.label(format!( "Mouse delta: {:?}", self.input_state.get_mouse_state().delta )); for (key, state) in self.input_state.key_states.iter().filter(|(_, state)| { *state == &KeyState::Pressed || *state == &KeyState::Held }) { ui.label(format!("{:?} State: {:?}", key, state)); } }); }); 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(); } }