winit: Use user event
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m47s

This commit is contained in:
Florian RICHER 2025-05-29 21:38:07 +02:00
parent 6a6b1821a4
commit f1ae54bc73
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
8 changed files with 227 additions and 29 deletions

View file

@ -6,8 +6,9 @@ use super::scene::SceneContext;
use crate::core::input::InputManager;
use crate::core::scene::SceneManager;
use crate::core::timer::Timer;
use crate::game::main_scene::MainScene;
use crate::game::scenes::test_scene::TestScene;
use egui_winit_vulkano::{Gui, GuiConfig};
use user_event::UserEvent;
use vulkano::format::Format;
use vulkano::image::ImageUsage;
use vulkano::swapchain::PresentMode;
@ -15,34 +16,42 @@ 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::event_loop::{ActiveEventLoop, EventLoopProxy};
use winit::window::WindowId;
pub mod user_event;
pub const DEPTH_IMAGE_ID: usize = 0;
pub struct App {
vulkan_context: Arc<VulkanContext>,
vulkano_windows: Arc<VulkanoWindows>,
gui: HashMap<WindowId, Gui>,
scene_manager: SceneManager,
scene_manager: HashMap<WindowId, SceneManager>,
input_manager: Arc<InputManager>,
timer: Arc<Timer>,
event_loop_proxy: EventLoopProxy<UserEvent>,
}
impl App {
pub fn new(vulkano_context: VulkanoContext, input_manager: InputManager) -> Self {
pub fn new(
vulkano_context: VulkanoContext,
input_manager: InputManager,
event_loop_proxy: EventLoopProxy<UserEvent>,
) -> Self {
Self {
vulkan_context: Arc::new(VulkanContext::new(vulkano_context)),
vulkano_windows: Arc::new(VulkanoWindows::default()),
gui: HashMap::new(),
input_manager: Arc::new(input_manager),
scene_manager: SceneManager::new(),
scene_manager: HashMap::new(),
timer: Arc::new(Timer::new()),
event_loop_proxy,
}
}
}
impl ApplicationHandler for App {
impl ApplicationHandler<UserEvent> 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(
@ -81,10 +90,12 @@ impl ApplicationHandler for App {
)
};
self.gui.insert(window_id, gui);
}
self.scene_manager
.load_scene(Box::new(MainScene::default()));
let mut scene_manager = SceneManager::new();
scene_manager.load_scene(Box::new(TestScene::default()));
self.scene_manager.insert(window_id, scene_manager);
}
}
fn device_event(
@ -139,13 +150,16 @@ impl ApplicationHandler for App {
&self.vulkan_context,
&self.input_manager,
&self.timer,
id,
&self.event_loop_proxy,
));
self.scene_manager
let scene_manager = self.scene_manager.get_mut(&id).unwrap();
scene_manager
.load_scene_if_not_loaded(&scene_context)
.unwrap();
if let Some(scene) = self.scene_manager.current_scene_mut() {
if let Some(scene) = scene_manager.current_scene_mut() {
scene.update(&scene_context).unwrap();
let acquire_future = renderer.acquire(None, |_| {}).unwrap();
@ -164,4 +178,23 @@ impl ApplicationHandler for App {
let window = self.vulkano_windows.get_primary_window().unwrap();
window.request_redraw();
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
match event {
UserEvent::CursorGrabMode(window_id, grab) => {
let window = self.vulkano_windows.get_window(window_id).unwrap();
if let Err(e) = window.set_cursor_grab(grab) {
log::error!("Failed to set cursor grab: {}", e);
}
}
UserEvent::CursorVisible(window_id, visible) => {
let window = self.vulkano_windows.get_window(window_id).unwrap();
window.set_cursor_visible(visible);
}
UserEvent::ChangeScene(window_id, scene) => {
let scene_manager = self.scene_manager.get_mut(&window_id).unwrap();
scene_manager.load_scene(scene);
}
}
}
}

View file

@ -0,0 +1,9 @@
use winit::window::{CursorGrabMode, WindowId};
use crate::core::scene::Scene;
pub enum UserEvent {
CursorGrabMode(WindowId, CursorGrabMode),
CursorVisible(WindowId, bool),
ChangeScene(WindowId, Box<dyn Scene>),
}

View file

@ -9,12 +9,19 @@ use vulkano::{
memory::allocator::StandardMemoryAllocator,
};
use vulkano_util::renderer::VulkanoWindowRenderer;
use crate::core::{
app::DEPTH_IMAGE_ID, input::InputManager, render::vulkan_context::VulkanContext, timer::Timer,
use winit::{
event_loop::EventLoopProxy,
window::{Window, WindowId},
};
pub struct SceneContext {
use crate::core::{
app::{DEPTH_IMAGE_ID, user_event::UserEvent},
input::InputManager,
render::vulkan_context::VulkanContext,
timer::Timer,
};
pub struct SceneContext<'a> {
pub instance: Arc<Instance>,
pub device: Arc<Device>,
pub graphics_queue: Arc<Queue>,
@ -29,22 +36,28 @@ pub struct SceneContext {
pub depth_stencil_image_view: Arc<ImageView>,
pub input_manager: Arc<InputManager>,
pub timer: Arc<Timer>,
pub event_loop_proxy: &'a EventLoopProxy<UserEvent>,
pub window_id: WindowId,
}
impl
impl<'a>
From<(
&mut VulkanoWindowRenderer,
&Arc<VulkanContext>,
&Arc<InputManager>,
&Arc<Timer>,
)> for SceneContext
WindowId,
&'a EventLoopProxy<UserEvent>,
)> for SceneContext<'a>
{
fn from(
(renderer, vulkan_context, input_manager, timer): (
(renderer, vulkan_context, input_manager, timer, window_id, event_loop_proxy): (
&mut VulkanoWindowRenderer,
&Arc<VulkanContext>,
&Arc<InputManager>,
&Arc<Timer>,
WindowId,
&'a EventLoopProxy<UserEvent>,
),
) -> Self {
let (command_buffer_allocator, descriptor_set_allocator) = {
@ -81,6 +94,8 @@ impl
depth_stencil_image_view: renderer.get_additional_image_view(DEPTH_IMAGE_ID),
input_manager: input_manager.clone(),
timer: timer.clone(),
event_loop_proxy,
window_id,
}
}
}

View file

@ -1,2 +1,2 @@
pub mod assets;
pub mod main_scene;
pub mod scenes;

View file

@ -1,31 +1,26 @@
use std::{error::Error, sync::Arc};
use crate::core::app::user_event::UserEvent;
use crate::core::render::primitives::camera::Camera3D;
use crate::core::render::primitives::transform::Transform;
use crate::core::render::texture::Texture;
use crate::core::scene::Scene;
use crate::core::scene::SceneContext;
use crate::game::assets::square::Square;
use egui_winit_vulkano::{Gui, egui};
use glam::EulerRot;
use glam::Quat;
use glam::Vec3;
use vulkano::format::Format;
use vulkano::image::Image;
use vulkano::image::ImageCreateInfo;
use vulkano::image::ImageUsage;
use vulkano::memory::allocator::AllocationCreateInfo;
use vulkano::{
command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
RenderingAttachmentInfo, RenderingInfo,
},
image::view::ImageView,
pipeline::graphics::viewport::Viewport,
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
sync::GpuFuture,
};
use super::assets::square::Square;
use winit::window::CursorGrabMode;
pub struct MainSceneState {
square: Square,
@ -119,6 +114,38 @@ impl Scene for MainScene {
scene_context.aspect_ratio,
);
if scene_context
.input_manager
.get_virtual_input_state("mouse_left")
> 0.0
{
let _ = scene_context
.event_loop_proxy
.send_event(UserEvent::CursorVisible(scene_context.window_id, false));
let _ = scene_context
.event_loop_proxy
.send_event(UserEvent::CursorGrabMode(
scene_context.window_id,
CursorGrabMode::Locked,
));
}
if scene_context
.input_manager
.get_virtual_input_state("mouse_right")
> 0.0
{
let _ = scene_context
.event_loop_proxy
.send_event(UserEvent::CursorVisible(scene_context.window_id, true));
let _ = scene_context
.event_loop_proxy
.send_event(UserEvent::CursorGrabMode(
scene_context.window_id,
CursorGrabMode::None,
));
}
Ok(())
}

2
src/game/scenes/mod.rs Normal file
View file

@ -0,0 +1,2 @@
pub mod main_scene;
pub mod test_scene;

View file

@ -0,0 +1,111 @@
use std::error::Error;
use crate::core::app::user_event::UserEvent;
use crate::core::scene::Scene;
use crate::core::scene::SceneContext;
use egui_winit_vulkano::{Gui, egui};
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::CommandBufferUsage;
use vulkano::command_buffer::RenderingAttachmentInfo;
use vulkano::command_buffer::RenderingInfo;
use vulkano::pipeline::graphics::viewport::Viewport;
use vulkano::render_pass::AttachmentLoadOp;
use vulkano::render_pass::AttachmentStoreOp;
use vulkano::sync::GpuFuture;
use super::main_scene::MainScene;
pub struct MainSceneState {}
#[derive(Default)]
pub struct TestScene {
state: Option<MainSceneState>,
}
impl Scene for TestScene {
fn loaded(&self) -> bool {
self.state.is_some()
}
fn load(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
self.state = Some(MainSceneState {});
Ok(())
}
fn update(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
Ok(())
}
fn render(
&mut self,
acquire_future: Box<dyn GpuFuture>,
scene_context: &SceneContext,
gui: &mut Gui,
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
let mut builder = AutoCommandBufferBuilder::primary(
scene_context.command_buffer_allocator.clone(),
scene_context.graphics_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)?;
{
let viewport = Viewport {
offset: [0.0, 0.0],
extent: scene_context.window_size,
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([0.0, 0.0, 0.0, 1.0].into()),
..RenderingAttachmentInfo::image_view(
scene_context.swapchain_image_view.clone(),
)
})],
depth_attachment: Some(RenderingAttachmentInfo {
load_op: AttachmentLoadOp::Clear,
store_op: AttachmentStoreOp::DontCare,
clear_value: Some([1.0].into()),
..RenderingAttachmentInfo::image_view(
scene_context.depth_stencil_image_view.clone(),
)
}),
..Default::default()
})?
.set_viewport(0, [viewport].into_iter().collect())?;
}
builder.end_rendering()?;
let command_buffer = builder.build()?;
let render_future =
acquire_future.then_execute(scene_context.graphics_queue.clone(), command_buffer)?;
gui.immediate_ui(|gui| {
let ctx = gui.context();
egui::CentralPanel::default().show(&ctx, |ui| {
if ui.button("Start Game").clicked() {
let _ = scene_context
.event_loop_proxy
.send_event(UserEvent::ChangeScene(
scene_context.window_id,
Box::new(MainScene::default()),
));
}
});
});
let render_future =
gui.draw_on_image(render_future, scene_context.swapchain_image_view.clone());
Ok(render_future)
}
fn unload(&mut self) {}
}

View file

@ -77,10 +77,11 @@ fn main() {
let vulkano_context = VulkanoContext::new(vulkano_config);
let event_loop = EventLoop::new().unwrap();
let event_loop = EventLoop::with_user_event().build().unwrap();
event_loop.set_control_flow(ControlFlow::Poll);
let proxy = event_loop.create_proxy();
let mut app = core::app::App::new(vulkano_context, input_manager);
let mut app = core::app::App::new(vulkano_context, input_manager, proxy);
match event_loop.run_app(&mut app) {
Ok(_) => {}