winit: Use user event
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m47s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m47s
This commit is contained in:
parent
6a6b1821a4
commit
f1ae54bc73
8 changed files with 227 additions and 29 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
src/core/app/user_event.rs
Normal file
9
src/core/app/user_event.rs
Normal 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>),
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub mod assets;
|
||||
pub mod main_scene;
|
||||
pub mod scenes;
|
||||
|
|
|
@ -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
2
src/game/scenes/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod main_scene;
|
||||
pub mod test_scene;
|
111
src/game/scenes/test_scene.rs
Normal file
111
src/game/scenes/test_scene.rs
Normal 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) {}
|
||||
}
|
|
@ -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(_) => {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue