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

@ -0,0 +1,251 @@
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::{
command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
RenderingAttachmentInfo, RenderingInfo,
},
pipeline::graphics::viewport::Viewport,
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
sync::GpuFuture,
};
use winit::window::CursorGrabMode;
pub struct MainSceneState {
square: Square,
instances: Vec<Transform>,
camera: Camera3D,
texture: Texture,
speed: f32,
}
#[derive(Default)]
pub struct MainScene {
state: Option<MainSceneState>,
}
impl Scene for MainScene {
fn loaded(&self) -> bool {
self.state.is_some()
}
fn load(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
let square = Square::new(
&scene_context.device,
&scene_context.memory_allocator,
scene_context.swapchain_image_view.format(),
scene_context.depth_stencil_image_view.format(),
)?;
let num_instances = 100;
let instance_size = 10.0;
let instance_spacing = 10.0;
let num_instances_per_row = (num_instances as f32 / instance_spacing as f32).ceil() as u32;
let instances: Vec<Transform> = (0..num_instances)
.map(|i| Transform {
position: Vec3::new(
(i % num_instances_per_row) as f32 * (instance_spacing + instance_size),
0.0,
(i / num_instances_per_row) as f32 * (instance_spacing + instance_size),
),
rotation: Quat::from_euler(
EulerRot::XYZ,
0.0,
rand::random_range(0.0..=360.0),
0.0,
),
scale: Vec3::new(instance_size, instance_size, instance_size),
})
.collect();
let camera = Camera3D::new(
scene_context.aspect_ratio,
std::f32::consts::FRAC_PI_2,
0.01,
1000.0,
);
let mut uploads = AutoCommandBufferBuilder::primary(
scene_context.command_buffer_allocator.clone(),
scene_context.graphics_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)?;
let texture = Texture::from_file(
&scene_context.device,
&scene_context.memory_allocator,
&mut uploads,
"res/textures/wooden-crate.jpg",
)?;
let _ = uploads
.build()?
.execute(scene_context.graphics_queue.clone())?;
self.state = Some(MainSceneState {
square,
instances,
camera,
texture,
speed: 50.0,
});
Ok(())
}
fn update(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
let state = self.state.as_mut().ok_or("State not found")?;
state.camera.update(
&scene_context.input_manager,
&scene_context.timer,
state.speed,
10.0,
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(())
}
fn render(
&mut self,
acquire_future: Box<dyn GpuFuture>,
scene_context: &SceneContext,
gui: &mut Gui,
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
let state = self.state.as_ref().ok_or("State not found")?;
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())?;
}
let camera_uniform = state
.camera
.create_buffer(&scene_context.memory_allocator)?;
let transform_uniform =
Transform::create_buffer(&scene_context.memory_allocator, &state.instances)?;
state
.square
.render(
&mut builder,
&scene_context.descriptor_set_allocator,
&camera_uniform,
&transform_uniform,
&state.texture,
)
.unwrap();
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::Window::new("Informations")
.vscroll(true)
.show(&ctx, |ui| {
ui.label(format!("Resolution: {:?}", scene_context.window_size));
ui.label(format!("{:#?}", scene_context.input_manager));
ui.label(format!(
"Delta time: {:?}",
scene_context.timer.delta_time()
));
ui.label(format!(
"Position: {:?}, Rotation: {:?}",
state.camera.get_position(),
state.camera.get_rotation()
));
});
});
let render_future =
gui.draw_on_image(render_future, scene_context.swapchain_image_view.clone());
Ok(render_future)
}
fn unload(&mut self) {}
}