Integration of ECS pattern: Iteration 1

This commit is contained in:
Florian RICHER 2025-06-11 16:05:35 +02:00
parent fc81f65a27
commit 8ce620a74b
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
13 changed files with 727 additions and 135 deletions

View file

@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
@ -8,6 +7,10 @@ use crate::core::app::context::WindowContext;
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::primitives::vulkan_resource::{
VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanDevice, VulkanGraphicsQueue,
VulkanMemoryAllocator,
};
use crate::core::render::primitives::{AsDescriptorSet, AsRecordable};
use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager};
use crate::core::render::resources::meshes::{ObjMesh, SquareMesh};
@ -15,6 +18,7 @@ use crate::core::render::resources::pipeline::PipelineLoader;
use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind};
use crate::core::scene::Scene;
use crate::game::assets::pipelines::simple::SimplePipeline;
use bevy_ecs::world::World;
use egui_winit_vulkano::egui;
use glam::EulerRot;
use glam::Quat;
@ -48,23 +52,27 @@ impl Scene for MainScene {
self.state.is_some()
}
fn load(&mut self, app_context: &mut WindowContext) -> Result<(), Box<dyn std::error::Error>> {
let depth_image_view = app_context.with_renderer_mut(|renderer| {
fn load(
&mut self,
world: &mut World,
window_context: &mut WindowContext,
) -> Result<(), Box<dyn std::error::Error>> {
let depth_image_view = window_context.with_renderer_mut(|renderer| {
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
});
let swapchain_image_view =
app_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let mut pipeline_loader = PipelineLoader::new(
app_context.device.clone(),
VulkanDevice::get_from_world(world).clone(),
swapchain_image_view.format(),
depth_image_view.format(),
);
pipeline_loader.register::<SimplePipeline>()?;
pipeline_loader.load_pending_pipelines()?;
let mut texture_loader = TextureLoader::new(app_context);
let mut texture_loader = TextureLoader::new(world);
texture_loader.add_texture(
"wooden-crate".to_string(),
TextureLoadInfo {
@ -93,10 +101,13 @@ impl Scene for MainScene {
);
texture_loader.load_pending_textures()?;
let square = SquareMesh::new(&app_context.memory_allocator)?;
let square = SquareMesh::new(VulkanMemoryAllocator::get_from_world(world))?;
let obj = {
let obj = ObjMesh::new(&app_context.memory_allocator, "res/objects/cube.obj")?;
let obj = ObjMesh::new(
VulkanMemoryAllocator::get_from_world(world),
"res/objects/cube.obj",
)?;
obj.into_iter().next().unwrap()
};
@ -139,7 +150,7 @@ impl Scene for MainScene {
})
.collect();
let camera = app_context.with_renderer(|renderer| {
let camera = window_context.with_renderer(|renderer| {
Camera3D::new(
renderer.aspect_ratio(),
std::f32::consts::FRAC_PI_2,
@ -162,21 +173,26 @@ impl Scene for MainScene {
Ok(())
}
fn update(&mut self, app_context: &mut WindowContext) -> Result<(), Box<dyn Error>> {
fn update(
&mut self,
_world: &mut World,
window_context: &WindowContext,
) -> Result<(), Box<dyn Error>> {
let state = self.state.as_mut().unwrap();
app_context.with_input_manager(|input_manager| {
app_context.with_timer(|timer| {
window_context.with_input_manager(|input_manager| {
window_context.with_timer(|timer| {
state.camera.update(
input_manager,
timer,
state.speed,
10.0,
app_context.get_aspect_ratio(),
window_context.get_aspect_ratio(),
);
});
});
let delta_time = app_context.get_delta_time();
let delta_time = window_context.get_delta_time();
for (i, instance) in state.square_instances.iter_mut().enumerate() {
let rotation_speed = (i % 10) as f32;
let rotation_delta = Quat::from_rotation_y(rotation_speed * delta_time);
@ -191,32 +207,32 @@ impl Scene for MainScene {
instance.rotate(rotation_delta);
}
if app_context
if window_context
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
> 0.0
{
let _ = app_context
let _ = window_context
.event_loop_proxy
.send_event(UserEvent::CursorVisible(app_context.window_id, false));
let _ = app_context
.send_event(UserEvent::CursorVisible(window_context.window_id, false));
let _ = window_context
.event_loop_proxy
.send_event(UserEvent::CursorGrabMode(
app_context.window_id,
window_context.window_id,
CursorGrabMode::Locked,
));
}
if app_context.with_input_manager(|input_manager| {
if window_context.with_input_manager(|input_manager| {
input_manager.get_virtual_input_state("mouse_right")
}) > 0.0
{
let _ = app_context
let _ = window_context
.event_loop_proxy
.send_event(UserEvent::CursorVisible(app_context.window_id, true));
let _ = app_context
.send_event(UserEvent::CursorVisible(window_context.window_id, true));
let _ = window_context
.event_loop_proxy
.send_event(UserEvent::CursorGrabMode(
app_context.window_id,
window_context.window_id,
CursorGrabMode::None,
));
}
@ -227,20 +243,21 @@ impl Scene for MainScene {
fn render(
&mut self,
before_future: Box<dyn GpuFuture>,
app_context: &mut WindowContext,
world: &mut World,
window_context: &mut WindowContext,
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
let state = self.state.as_mut().ok_or("State not loaded")?;
let mut builder = AutoCommandBufferBuilder::primary(
app_context.command_buffer_allocator.clone(),
app_context.graphics_queue.queue_family_index(),
VulkanCommandBufferAllocator::get_from_world(world).clone(),
VulkanGraphicsQueue::get_from_world(world).queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)?;
{
let swapchain_image_view =
app_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let depth_image_view = app_context.with_renderer_mut(|renderer| {
window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let depth_image_view = window_context.with_renderer_mut(|renderer| {
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
});
let config = RenderPassConfig::default();
@ -249,23 +266,31 @@ impl Scene for MainScene {
&config,
swapchain_image_view,
Some(depth_image_view),
app_context.get_window_size(),
window_context.get_window_size(),
)?;
}
// Create camera uniform using the actual camera
let camera_uniform = Arc::new(state.camera.create_buffer(&app_context.memory_allocator)?);
let square_transform_uniform =
Transform::create_buffer(&app_context.memory_allocator, &state.square_instances)?;
let obj_transform_uniform =
Transform::create_buffer(&app_context.memory_allocator, &state.obj_instances)?;
let camera_uniform = Arc::new(
state
.camera
.create_buffer(VulkanMemoryAllocator::get_from_world(world))?,
);
let square_transform_uniform = Transform::create_buffer(
VulkanMemoryAllocator::get_from_world(world),
&state.square_instances,
)?;
let obj_transform_uniform = Transform::create_buffer(
VulkanMemoryAllocator::get_from_world(world),
&state.obj_instances,
)?;
state
.pipeline_loader
.with_pipeline::<SimplePipeline, _>(|pipeline| {
SimplePipeline::record_commands(
&mut builder,
&app_context.descriptor_set_allocator,
&VulkanDescriptorSetAllocator::get_from_world(world),
pipeline,
&state.square,
&square_transform_uniform,
@ -281,7 +306,7 @@ impl Scene for MainScene {
SimplePipeline::record_commands(
&mut builder,
&app_context.descriptor_set_allocator,
&VulkanDescriptorSetAllocator::get_from_world(world),
pipeline,
&state.obj,
&obj_transform_uniform,
@ -302,19 +327,21 @@ impl Scene for MainScene {
let command_buffer = builder.build()?;
let render_future =
before_future.then_execute(app_context.graphics_queue.clone(), command_buffer)?;
let render_future = before_future.then_execute(
VulkanGraphicsQueue::get_from_world(world).clone(),
command_buffer,
)?;
let swapchain_image_view =
app_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let input_manager_status =
app_context.with_input_manager(|input_manager| format!("{:#?}", input_manager));
let event_loop_proxy = app_context.event_loop_proxy.clone();
let delta_time = app_context.get_delta_time();
let window_id = app_context.window_id;
let window_size = app_context.get_window_size();
window_context.with_input_manager(|input_manager| format!("{:#?}", input_manager));
let event_loop_proxy = window_context.event_loop_proxy.clone();
let delta_time = window_context.get_delta_time();
let window_id = window_context.window_id;
let window_size = window_context.get_window_size();
let render_future = app_context.with_gui_mut(|gui| {
let render_future = window_context.with_gui_mut(|gui| {
gui.immediate_ui(|gui| {
let ctx = gui.context();
egui::TopBottomPanel::top("top_panel").show(&ctx, |ui| {