Refactor app context and render pass manager
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 9m10s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 9m10s
This commit is contained in:
parent
f1ae54bc73
commit
2c169548b9
12 changed files with 846 additions and 466 deletions
230
src/core/app/context.rs
Normal file
230
src/core/app/context.rs
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use egui_winit_vulkano::Gui;
|
||||||
|
use vulkano::{
|
||||||
|
command_buffer::allocator::StandardCommandBufferAllocator,
|
||||||
|
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
||||||
|
device::{Device, Queue},
|
||||||
|
instance::Instance,
|
||||||
|
memory::allocator::StandardMemoryAllocator,
|
||||||
|
};
|
||||||
|
use vulkano_util::{renderer::VulkanoWindowRenderer, window::VulkanoWindows};
|
||||||
|
use winit::{
|
||||||
|
event_loop::EventLoopProxy,
|
||||||
|
window::{Window, WindowId},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::core::{input::InputManager, render::vulkan_context::VulkanContext, timer::Timer};
|
||||||
|
|
||||||
|
use super::user_event::UserEvent;
|
||||||
|
|
||||||
|
/// Contexte d'application unifié avec Arc<Mutex<>> pour la mutabilité partagée
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ApplicationContext {
|
||||||
|
// Données Vulkan (immutables)
|
||||||
|
pub vulkan_context: Arc<VulkanContext>,
|
||||||
|
pub device: Arc<Device>,
|
||||||
|
pub instance: Arc<Instance>,
|
||||||
|
pub graphics_queue: Arc<Queue>,
|
||||||
|
pub compute_queue: Arc<Queue>,
|
||||||
|
pub transfer_queue: Option<Arc<Queue>>,
|
||||||
|
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
||||||
|
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||||
|
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||||
|
pub event_loop_proxy: EventLoopProxy<UserEvent>,
|
||||||
|
pub window_id: WindowId,
|
||||||
|
|
||||||
|
// Données mutables partagées avec Arc<Mutex<>>
|
||||||
|
pub vulkano_windows: Arc<Mutex<VulkanoWindows>>,
|
||||||
|
pub input_manager: Arc<Mutex<InputManager>>,
|
||||||
|
pub timer: Arc<Mutex<Timer>>,
|
||||||
|
pub gui: Arc<Mutex<Gui>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplicationContext {
|
||||||
|
pub fn new(
|
||||||
|
vulkan_context: Arc<VulkanContext>,
|
||||||
|
vulkano_windows: Arc<Mutex<VulkanoWindows>>,
|
||||||
|
input_manager: Arc<Mutex<InputManager>>,
|
||||||
|
timer: Arc<Mutex<Timer>>,
|
||||||
|
gui: Arc<Mutex<Gui>>,
|
||||||
|
event_loop_proxy: EventLoopProxy<UserEvent>,
|
||||||
|
window_id: WindowId,
|
||||||
|
) -> Self {
|
||||||
|
let vulkano_context_inner = vulkan_context.vulkano_context();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
// Données Vulkan
|
||||||
|
vulkan_context: vulkan_context.clone(),
|
||||||
|
device: vulkano_context_inner.device().clone(),
|
||||||
|
instance: vulkano_context_inner.instance().clone(),
|
||||||
|
graphics_queue: vulkano_context_inner.graphics_queue().clone(),
|
||||||
|
compute_queue: vulkano_context_inner.compute_queue().clone(),
|
||||||
|
transfer_queue: vulkano_context_inner.transfer_queue().cloned(),
|
||||||
|
memory_allocator: vulkano_context_inner.memory_allocator().clone(),
|
||||||
|
command_buffer_allocator: vulkan_context.command_buffer_allocator().clone(),
|
||||||
|
descriptor_set_allocator: vulkan_context.descriptor_set_allocator().clone(),
|
||||||
|
event_loop_proxy,
|
||||||
|
window_id,
|
||||||
|
|
||||||
|
// Données mutables partagées
|
||||||
|
vulkano_windows,
|
||||||
|
input_manager,
|
||||||
|
timer,
|
||||||
|
gui,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Récupère les résolutions disponibles du moniteur (méthode utilitaire statique)
|
||||||
|
fn get_monitor_resolutions(window: &Window) -> Vec<(u32, u32)> {
|
||||||
|
// Première tentative : moniteur actuel
|
||||||
|
if let Some(monitor) = window.current_monitor() {
|
||||||
|
let resolutions = Self::extract_resolutions_from_monitor(&monitor);
|
||||||
|
if !resolutions.is_empty() {
|
||||||
|
log::debug!(
|
||||||
|
"Résolutions trouvées via moniteur actuel: {:?}",
|
||||||
|
resolutions
|
||||||
|
);
|
||||||
|
return resolutions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deuxième tentative : tous les moniteurs disponibles
|
||||||
|
log::debug!("Tentative de récupération via tous les moniteurs disponibles...");
|
||||||
|
let mut all_resolutions = Vec::new();
|
||||||
|
|
||||||
|
for monitor in window.available_monitors() {
|
||||||
|
let resolutions = Self::extract_resolutions_from_monitor(&monitor);
|
||||||
|
all_resolutions.extend(resolutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !all_resolutions.is_empty() {
|
||||||
|
// Supprime les doublons et trie
|
||||||
|
all_resolutions.sort_unstable();
|
||||||
|
all_resolutions.dedup();
|
||||||
|
all_resolutions.sort_by(|a, b| (b.0 * b.1).cmp(&(a.0 * a.1)));
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"Résolutions trouvées via tous les moniteurs: {:?}",
|
||||||
|
all_resolutions
|
||||||
|
);
|
||||||
|
return all_resolutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aucune résolution détectée - retourne un vecteur vide
|
||||||
|
log::warn!("Aucune résolution détectée pour cette fenêtre");
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extrait les résolutions d'un moniteur donné
|
||||||
|
fn extract_resolutions_from_monitor(
|
||||||
|
monitor: &winit::monitor::MonitorHandle,
|
||||||
|
) -> Vec<(u32, u32)> {
|
||||||
|
let video_modes: Vec<_> = monitor.video_modes().collect();
|
||||||
|
|
||||||
|
if video_modes.is_empty() {
|
||||||
|
log::debug!(
|
||||||
|
"Aucun mode vidéo trouvé pour le moniteur {:?}",
|
||||||
|
monitor.name()
|
||||||
|
);
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let resolutions: Vec<(u32, u32)> = video_modes
|
||||||
|
.into_iter()
|
||||||
|
.map(|mode| {
|
||||||
|
let size = mode.size();
|
||||||
|
(size.width, size.height)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"Modes vidéo trouvés pour {:?}: {:?}",
|
||||||
|
monitor.name(),
|
||||||
|
resolutions
|
||||||
|
);
|
||||||
|
resolutions
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Récupère les résolutions disponibles
|
||||||
|
pub fn get_available_resolutions(&self) -> Vec<(u32, u32)> {
|
||||||
|
self.with_renderer(|renderer| Self::get_monitor_resolutions(&renderer.window()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Récupère le delta time actuel depuis le timer
|
||||||
|
pub fn get_delta_time(&self) -> f32 {
|
||||||
|
self.with_timer(|timer| timer.delta_time())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Récupère la taille de la fenêtre depuis le renderer
|
||||||
|
pub fn get_window_size(&self) -> [f32; 2] {
|
||||||
|
self.with_renderer(|renderer| renderer.window_size())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Récupère l'aspect ratio depuis le renderer
|
||||||
|
pub fn get_aspect_ratio(&self) -> f32 {
|
||||||
|
self.with_renderer(|renderer| renderer.aspect_ratio())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_renderer<T, F>(&self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&VulkanoWindowRenderer) -> T,
|
||||||
|
{
|
||||||
|
let vulkano_windows = self
|
||||||
|
.vulkano_windows
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock vulkano_windows");
|
||||||
|
let renderer = vulkano_windows
|
||||||
|
.get_renderer(self.window_id)
|
||||||
|
.expect("Failed to get renderer");
|
||||||
|
f(&renderer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_renderer_mut<T, F>(&mut self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut VulkanoWindowRenderer) -> T,
|
||||||
|
{
|
||||||
|
let mut vulkano_windows = self
|
||||||
|
.vulkano_windows
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock vulkano_windows");
|
||||||
|
let renderer = vulkano_windows
|
||||||
|
.get_renderer_mut(self.window_id)
|
||||||
|
.expect("Failed to get renderer");
|
||||||
|
f(renderer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_gui<T, F>(&self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&Gui) -> T,
|
||||||
|
{
|
||||||
|
let gui = self.gui.lock().unwrap();
|
||||||
|
f(&gui)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_gui_mut<T, F>(&mut self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Gui) -> T,
|
||||||
|
{
|
||||||
|
let mut gui = self.gui.lock().unwrap();
|
||||||
|
f(&mut gui)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Méthode utilitaire pour accéder à l'input manager de manière thread-safe
|
||||||
|
pub fn with_input_manager<T, F>(&self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&InputManager) -> T,
|
||||||
|
{
|
||||||
|
let input_manager = self.input_manager.lock().unwrap();
|
||||||
|
f(&input_manager)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Méthode utilitaire pour accéder au timer de manière thread-safe
|
||||||
|
pub fn with_timer<T, F>(&self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(&Timer) -> T,
|
||||||
|
{
|
||||||
|
let timer = self.timer.lock().unwrap();
|
||||||
|
f(&timer)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use super::render::vulkan_context::VulkanContext;
|
use super::render::vulkan_context::VulkanContext;
|
||||||
use super::scene::SceneContext;
|
|
||||||
use crate::core::input::InputManager;
|
use crate::core::input::InputManager;
|
||||||
use crate::core::scene::SceneManager;
|
use crate::core::scene::manager::SceneManager;
|
||||||
use crate::core::timer::Timer;
|
use crate::core::timer::Timer;
|
||||||
use crate::game::scenes::test_scene::TestScene;
|
use crate::game::scenes::main_scene::MainScene;
|
||||||
use egui_winit_vulkano::{Gui, GuiConfig};
|
use egui_winit_vulkano::{Gui, GuiConfig};
|
||||||
use user_event::UserEvent;
|
use user_event::UserEvent;
|
||||||
use vulkano::format::Format;
|
use vulkano::format::Format;
|
||||||
|
@ -19,18 +18,23 @@ use winit::event::WindowEvent;
|
||||||
use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
|
use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
|
||||||
use winit::window::WindowId;
|
use winit::window::WindowId;
|
||||||
|
|
||||||
|
use self::context::ApplicationContext;
|
||||||
|
|
||||||
|
pub mod context;
|
||||||
pub mod user_event;
|
pub mod user_event;
|
||||||
|
|
||||||
pub const DEPTH_IMAGE_ID: usize = 0;
|
pub const DEPTH_IMAGE_ID: usize = 0;
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
vulkan_context: Arc<VulkanContext>,
|
vulkan_context: Arc<VulkanContext>,
|
||||||
vulkano_windows: Arc<VulkanoWindows>,
|
vulkano_windows: Arc<Mutex<VulkanoWindows>>,
|
||||||
gui: HashMap<WindowId, Gui>,
|
gui: HashMap<WindowId, Arc<Mutex<Gui>>>,
|
||||||
scene_manager: HashMap<WindowId, SceneManager>,
|
scene_manager: HashMap<WindowId, SceneManager>,
|
||||||
input_manager: Arc<InputManager>,
|
input_manager: Arc<Mutex<InputManager>>,
|
||||||
timer: Arc<Timer>,
|
timer: Arc<Mutex<Timer>>,
|
||||||
event_loop_proxy: EventLoopProxy<UserEvent>,
|
event_loop_proxy: EventLoopProxy<UserEvent>,
|
||||||
|
// Context d'application partagé par fenêtre - architecture unifiée
|
||||||
|
app_contexts: HashMap<WindowId, Arc<Mutex<ApplicationContext>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
@ -41,61 +45,61 @@ impl App {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
vulkan_context: Arc::new(VulkanContext::new(vulkano_context)),
|
vulkan_context: Arc::new(VulkanContext::new(vulkano_context)),
|
||||||
vulkano_windows: Arc::new(VulkanoWindows::default()),
|
vulkano_windows: Arc::new(Mutex::new(VulkanoWindows::default())),
|
||||||
gui: HashMap::new(),
|
gui: HashMap::new(),
|
||||||
input_manager: Arc::new(input_manager),
|
input_manager: Arc::new(Mutex::new(input_manager)),
|
||||||
scene_manager: HashMap::new(),
|
scene_manager: HashMap::new(),
|
||||||
timer: Arc::new(Timer::new()),
|
timer: Arc::new(Mutex::new(Timer::new())),
|
||||||
event_loop_proxy,
|
event_loop_proxy,
|
||||||
|
app_contexts: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplicationHandler<UserEvent> for App {
|
impl ApplicationHandler<UserEvent> for App {
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
if let Some(vulkano_windows) = Arc::get_mut(&mut self.vulkano_windows) {
|
let mut vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
let window_id = vulkano_windows.create_window(
|
let window_id = 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,
|
||||||
|
cursor_visible: false,
|
||||||
|
cursor_locked: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
|_| {},
|
||||||
|
);
|
||||||
|
|
||||||
|
let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap();
|
||||||
|
renderer.add_additional_image_view(
|
||||||
|
DEPTH_IMAGE_ID,
|
||||||
|
Format::D16_UNORM,
|
||||||
|
ImageUsage::DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
);
|
||||||
|
|
||||||
|
let gui = {
|
||||||
|
Gui::new(
|
||||||
event_loop,
|
event_loop,
|
||||||
self.vulkan_context.vulkano_context(),
|
renderer.surface(),
|
||||||
&WindowDescriptor {
|
renderer.graphics_queue(),
|
||||||
title: "Rust ASH Test".to_string(),
|
renderer.swapchain_format(),
|
||||||
width: 800.0,
|
GuiConfig {
|
||||||
height: 600.0,
|
is_overlay: true,
|
||||||
present_mode: PresentMode::Fifo,
|
allow_srgb_render_target: true,
|
||||||
cursor_visible: false,
|
|
||||||
cursor_locked: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|_| {},
|
)
|
||||||
);
|
};
|
||||||
|
self.gui.insert(window_id, Arc::new(Mutex::new(gui)));
|
||||||
|
|
||||||
let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap();
|
let mut scene_manager = SceneManager::new();
|
||||||
renderer.add_additional_image_view(
|
scene_manager.load_scene(Box::new(MainScene::default()));
|
||||||
DEPTH_IMAGE_ID,
|
|
||||||
Format::D16_UNORM,
|
|
||||||
ImageUsage::DEPTH_STENCIL_ATTACHMENT,
|
|
||||||
);
|
|
||||||
|
|
||||||
let gui = {
|
self.scene_manager.insert(window_id, scene_manager);
|
||||||
Gui::new(
|
|
||||||
event_loop,
|
|
||||||
renderer.surface(),
|
|
||||||
renderer.graphics_queue(),
|
|
||||||
renderer.swapchain_format(),
|
|
||||||
GuiConfig {
|
|
||||||
is_overlay: true,
|
|
||||||
allow_srgb_render_target: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
|
||||||
self.gui.insert(window_id, gui);
|
|
||||||
|
|
||||||
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(
|
fn device_event(
|
||||||
|
@ -104,23 +108,17 @@ impl ApplicationHandler<UserEvent> for App {
|
||||||
_device_id: winit::event::DeviceId,
|
_device_id: winit::event::DeviceId,
|
||||||
event: winit::event::DeviceEvent,
|
event: winit::event::DeviceEvent,
|
||||||
) {
|
) {
|
||||||
match Arc::get_mut(&mut self.input_manager) {
|
let mut input_manager = self.input_manager.lock().unwrap();
|
||||||
Some(input_manager) => input_manager.process_device_event(&event),
|
input_manager.process_device_event(&event);
|
||||||
None => log::error!("Failed to get a mutable reference to the input manager"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
|
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
|
||||||
let renderer = Arc::get_mut(&mut self.vulkano_windows)
|
{
|
||||||
.unwrap()
|
let gui = self.gui.get_mut(&id).unwrap();
|
||||||
.get_renderer_mut(id)
|
let mut gui = gui.lock().unwrap();
|
||||||
.unwrap();
|
if !gui.update(&event) {
|
||||||
let gui = self.gui.get_mut(&id).unwrap();
|
let mut input_manager = self.input_manager.lock().unwrap();
|
||||||
|
input_manager.process_window_event(&event);
|
||||||
if !gui.update(&event) {
|
|
||||||
match Arc::get_mut(&mut self.input_manager) {
|
|
||||||
Some(input_manager) => input_manager.process_window_event(&event),
|
|
||||||
None => log::error!("Failed to get a mutable reference to the input manager"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,45 +127,64 @@ impl ApplicationHandler<UserEvent> for App {
|
||||||
log::debug!("The close button was pressed; stopping");
|
log::debug!("The close button was pressed; stopping");
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
WindowEvent::Resized(_) => {
|
WindowEvent::Resized(_) | WindowEvent::ScaleFactorChanged { .. } => {
|
||||||
renderer.resize();
|
let mut vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
}
|
vulkano_windows.get_renderer_mut(id).unwrap().resize();
|
||||||
WindowEvent::ScaleFactorChanged { .. } => {
|
|
||||||
renderer.resize();
|
|
||||||
}
|
}
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
match Arc::get_mut(&mut self.input_manager) {
|
{
|
||||||
Some(input_manager) => input_manager.update(),
|
let mut input_manager = self
|
||||||
None => log::error!("Failed to get a mutable reference to the input manager"),
|
.input_manager
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock input manager");
|
||||||
|
input_manager.update();
|
||||||
}
|
}
|
||||||
match Arc::get_mut(&mut self.timer) {
|
{
|
||||||
Some(timer) => timer.update(),
|
let mut timer = self.timer.lock().expect("Failed to lock timer");
|
||||||
None => log::error!("Failed to get a mutable reference to the timer"),
|
timer.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scene_context = SceneContext::from((
|
// Créer ou mettre à jour le contexte d'application
|
||||||
&mut *renderer,
|
let app_context = self
|
||||||
&self.vulkan_context,
|
.app_contexts
|
||||||
&self.input_manager,
|
.entry(id)
|
||||||
&self.timer,
|
.or_insert_with(|| {
|
||||||
id,
|
Arc::new(Mutex::new(ApplicationContext::new(
|
||||||
&self.event_loop_proxy,
|
self.vulkan_context.clone(),
|
||||||
));
|
self.vulkano_windows.clone(),
|
||||||
|
self.input_manager.clone(),
|
||||||
|
self.timer.clone(),
|
||||||
|
self.gui.get(&id).unwrap().clone(),
|
||||||
|
self.event_loop_proxy.clone(),
|
||||||
|
id,
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
|
||||||
let scene_manager = self.scene_manager.get_mut(&id).unwrap();
|
let scene_manager = self.scene_manager.get_mut(&id).unwrap();
|
||||||
scene_manager
|
|
||||||
.load_scene_if_not_loaded(&scene_context)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(scene) = scene_manager.current_scene_mut() {
|
// Utiliser le contexte partagé pour les scènes
|
||||||
scene.update(&scene_context).unwrap();
|
{
|
||||||
|
let mut context = app_context.lock().unwrap();
|
||||||
|
|
||||||
let acquire_future = renderer.acquire(None, |_| {}).unwrap();
|
scene_manager
|
||||||
// Update the swapchain image view to the current one after acquiring the next image
|
.load_scene_if_not_loaded(&mut context)
|
||||||
scene_context.swapchain_image_view = renderer.swapchain_image_view();
|
.unwrap();
|
||||||
|
|
||||||
let acquire_future = scene.render(acquire_future, &scene_context, gui).unwrap();
|
if let Some(scene) = scene_manager.current_scene_mut() {
|
||||||
renderer.present(acquire_future, true);
|
scene.update(&mut context).unwrap();
|
||||||
|
|
||||||
|
let acquire_future = context
|
||||||
|
.with_renderer_mut(|renderer| renderer.acquire(None, |_| {}).unwrap());
|
||||||
|
|
||||||
|
let acquire_future = scene.render(acquire_future, &mut context).unwrap();
|
||||||
|
|
||||||
|
context.with_renderer_mut(|renderer| {
|
||||||
|
renderer.present(acquire_future, true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
log::warn!("No current scene found for update!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -175,25 +192,46 @@ impl ApplicationHandler<UserEvent> for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
||||||
let window = self.vulkano_windows.get_primary_window().unwrap();
|
let vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
|
let window = vulkano_windows.get_primary_window().unwrap();
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
|
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
|
||||||
match event {
|
match event {
|
||||||
UserEvent::CursorGrabMode(window_id, grab) => {
|
UserEvent::CursorGrabMode(window_id, grab) => {
|
||||||
let window = self.vulkano_windows.get_window(window_id).unwrap();
|
let vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
|
let window = vulkano_windows.get_window(window_id).unwrap();
|
||||||
if let Err(e) = window.set_cursor_grab(grab) {
|
if let Err(e) = window.set_cursor_grab(grab) {
|
||||||
log::error!("Failed to set cursor grab: {}", e);
|
log::error!("Failed to set cursor grab: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UserEvent::CursorVisible(window_id, visible) => {
|
UserEvent::CursorVisible(window_id, visible) => {
|
||||||
let window = self.vulkano_windows.get_window(window_id).unwrap();
|
let vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
|
let window = vulkano_windows.get_window(window_id).unwrap();
|
||||||
window.set_cursor_visible(visible);
|
window.set_cursor_visible(visible);
|
||||||
}
|
}
|
||||||
UserEvent::ChangeScene(window_id, scene) => {
|
UserEvent::ChangeScene(window_id, scene) => {
|
||||||
let scene_manager = self.scene_manager.get_mut(&window_id).unwrap();
|
if let Some(scene_manager) = self.scene_manager.get_mut(&window_id) {
|
||||||
scene_manager.load_scene(scene);
|
scene_manager.load_scene(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UserEvent::ChangeResolution(window_id, width, height) => {
|
||||||
|
let mut vulkano_windows = self.vulkano_windows.lock().unwrap();
|
||||||
|
let window = vulkano_windows.get_window(window_id).unwrap();
|
||||||
|
let _ = window.request_inner_size(winit::dpi::LogicalSize::new(width, height));
|
||||||
|
let renderer = vulkano_windows.get_renderer_mut(window_id).unwrap();
|
||||||
|
renderer.resize();
|
||||||
|
log::info!(
|
||||||
|
"Resolution changed to {}x{} for window {:?}",
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
window_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
UserEvent::Exit(window_id) => {
|
||||||
|
log::info!("Exit requested for window {:?}", window_id);
|
||||||
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,6 @@ pub enum UserEvent {
|
||||||
CursorGrabMode(WindowId, CursorGrabMode),
|
CursorGrabMode(WindowId, CursorGrabMode),
|
||||||
CursorVisible(WindowId, bool),
|
CursorVisible(WindowId, bool),
|
||||||
ChangeScene(WindowId, Box<dyn Scene>),
|
ChangeScene(WindowId, Box<dyn Scene>),
|
||||||
|
ChangeResolution(WindowId, f32, f32),
|
||||||
|
Exit(WindowId),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
|
pub mod render_pass_manager;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
pub mod vulkan_context;
|
pub mod vulkan_context;
|
||||||
|
|
113
src/core/render/render_pass_manager.rs
Normal file
113
src/core/render/render_pass_manager.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::{
|
||||||
|
command_buffer::{AutoCommandBufferBuilder, RenderingAttachmentInfo, RenderingInfo},
|
||||||
|
image::view::ImageView,
|
||||||
|
pipeline::graphics::viewport::Viewport,
|
||||||
|
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Types de render passes disponibles
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum RenderPassType {
|
||||||
|
Standard,
|
||||||
|
ShadowMap,
|
||||||
|
PostProcess,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configuration pour un render pass
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RenderPassConfig {
|
||||||
|
pub pass_type: RenderPassType,
|
||||||
|
pub clear_color: Option<[f32; 4]>,
|
||||||
|
pub clear_depth: Option<f32>,
|
||||||
|
pub load_op: AttachmentLoadOp,
|
||||||
|
pub store_op: AttachmentStoreOp,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RenderPassConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pass_type: RenderPassType::Standard,
|
||||||
|
clear_color: Some([0.0, 0.0, 0.0, 1.0]),
|
||||||
|
clear_depth: Some(1.0),
|
||||||
|
load_op: AttachmentLoadOp::Clear,
|
||||||
|
store_op: AttachmentStoreOp::Store,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gestionnaire de render passes réutilisable
|
||||||
|
pub struct RenderPassManager;
|
||||||
|
|
||||||
|
impl RenderPassManager {
|
||||||
|
/// Commence un render pass standard avec les paramètres donnés
|
||||||
|
pub fn begin_standard_rendering(
|
||||||
|
builder: &mut AutoCommandBufferBuilder<vulkano::command_buffer::PrimaryAutoCommandBuffer>,
|
||||||
|
config: &RenderPassConfig,
|
||||||
|
color_attachment: Arc<ImageView>,
|
||||||
|
depth_attachment: Option<Arc<ImageView>>,
|
||||||
|
window_size: [f32; 2],
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let viewport = Viewport {
|
||||||
|
offset: [0.0, 0.0],
|
||||||
|
extent: window_size,
|
||||||
|
depth_range: 0.0..=1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut rendering_info = RenderingInfo {
|
||||||
|
color_attachments: vec![Some(RenderingAttachmentInfo {
|
||||||
|
load_op: config.load_op,
|
||||||
|
store_op: config.store_op,
|
||||||
|
clear_value: config.clear_color.map(|c| c.into()),
|
||||||
|
..RenderingAttachmentInfo::image_view(color_attachment)
|
||||||
|
})],
|
||||||
|
depth_attachment: None,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(depth_view) = depth_attachment {
|
||||||
|
rendering_info.depth_attachment = Some(RenderingAttachmentInfo {
|
||||||
|
load_op: AttachmentLoadOp::Clear,
|
||||||
|
store_op: AttachmentStoreOp::DontCare,
|
||||||
|
clear_value: config.clear_depth.map(|d| [d].into()),
|
||||||
|
..RenderingAttachmentInfo::image_view(depth_view)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.begin_rendering(rendering_info)?
|
||||||
|
.set_viewport(0, [viewport].into_iter().collect())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Termine le render pass actuel
|
||||||
|
pub fn end_rendering(
|
||||||
|
builder: &mut AutoCommandBufferBuilder<vulkano::command_buffer::PrimaryAutoCommandBuffer>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
builder.end_rendering()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crée une configuration pour un render pass shadow map
|
||||||
|
pub fn shadow_map_config() -> RenderPassConfig {
|
||||||
|
RenderPassConfig {
|
||||||
|
pass_type: RenderPassType::ShadowMap,
|
||||||
|
clear_color: None,
|
||||||
|
clear_depth: Some(1.0),
|
||||||
|
load_op: AttachmentLoadOp::Clear,
|
||||||
|
store_op: AttachmentStoreOp::Store,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crée une configuration pour un render pass de post-processing
|
||||||
|
pub fn post_process_config() -> RenderPassConfig {
|
||||||
|
RenderPassConfig {
|
||||||
|
pass_type: RenderPassType::PostProcess,
|
||||||
|
clear_color: Some([0.0, 0.0, 0.0, 1.0]),
|
||||||
|
clear_depth: None,
|
||||||
|
load_op: AttachmentLoadOp::Load,
|
||||||
|
store_op: AttachmentStoreOp::Store,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,101 +0,0 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use vulkano::{
|
|
||||||
command_buffer::allocator::StandardCommandBufferAllocator,
|
|
||||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
|
||||||
device::{Device, Queue},
|
|
||||||
image::view::ImageView,
|
|
||||||
instance::Instance,
|
|
||||||
memory::allocator::StandardMemoryAllocator,
|
|
||||||
};
|
|
||||||
use vulkano_util::renderer::VulkanoWindowRenderer;
|
|
||||||
use winit::{
|
|
||||||
event_loop::EventLoopProxy,
|
|
||||||
window::{Window, WindowId},
|
|
||||||
};
|
|
||||||
|
|
||||||
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>,
|
|
||||||
pub compute_queue: Arc<Queue>,
|
|
||||||
pub transfer_queue: Option<Arc<Queue>>,
|
|
||||||
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
|
||||||
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
|
||||||
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
|
||||||
pub window_size: [f32; 2],
|
|
||||||
pub aspect_ratio: f32,
|
|
||||||
pub swapchain_image_view: Arc<ImageView>,
|
|
||||||
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<'a>
|
|
||||||
From<(
|
|
||||||
&mut VulkanoWindowRenderer,
|
|
||||||
&Arc<VulkanContext>,
|
|
||||||
&Arc<InputManager>,
|
|
||||||
&Arc<Timer>,
|
|
||||||
WindowId,
|
|
||||||
&'a EventLoopProxy<UserEvent>,
|
|
||||||
)> for SceneContext<'a>
|
|
||||||
{
|
|
||||||
fn from(
|
|
||||||
(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) = {
|
|
||||||
(
|
|
||||||
vulkan_context.command_buffer_allocator().clone(),
|
|
||||||
vulkan_context.descriptor_set_allocator().clone(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (instance, device, graphics_queue, compute_queue, transfer_queue, memory_allocator) = {
|
|
||||||
let vulkan_context = vulkan_context.vulkano_context();
|
|
||||||
(
|
|
||||||
vulkan_context.instance().clone(),
|
|
||||||
vulkan_context.device().clone(),
|
|
||||||
vulkan_context.graphics_queue().clone(),
|
|
||||||
vulkan_context.compute_queue().clone(),
|
|
||||||
vulkan_context.transfer_queue().cloned(),
|
|
||||||
vulkan_context.memory_allocator().clone(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
instance,
|
|
||||||
device,
|
|
||||||
graphics_queue,
|
|
||||||
compute_queue,
|
|
||||||
transfer_queue,
|
|
||||||
memory_allocator,
|
|
||||||
command_buffer_allocator,
|
|
||||||
descriptor_set_allocator,
|
|
||||||
window_size: renderer.window_size(),
|
|
||||||
aspect_ratio: renderer.aspect_ratio(),
|
|
||||||
swapchain_image_view: renderer.swapchain_image_view(),
|
|
||||||
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,52 +1,84 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use super::{Scene, SceneContext};
|
use crate::core::app::context::ApplicationContext;
|
||||||
|
|
||||||
|
use super::Scene;
|
||||||
|
|
||||||
pub struct SceneManager {
|
pub struct SceneManager {
|
||||||
current_scene: Option<Box<dyn Scene>>,
|
scenes: Vec<Box<dyn Scene>>,
|
||||||
|
current_scene_index: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SceneManager {
|
impl SceneManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_scene: None,
|
scenes: Vec::new(),
|
||||||
|
current_scene_index: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_scene(&mut self, scene: Box<dyn Scene>) {
|
||||||
|
self.scenes.push(scene);
|
||||||
|
self.current_scene_index = Some(self.scenes.len() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_current_scene(&mut self, scene: Box<dyn Scene>) {
|
||||||
|
if let Some(index) = self.current_scene_index {
|
||||||
|
if index < self.scenes.len() {
|
||||||
|
self.scenes[index].unload();
|
||||||
|
self.scenes[index] = scene;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.load_scene(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_scene(&self) -> Option<&Box<dyn Scene>> {
|
||||||
|
if let Some(index) = self.current_scene_index {
|
||||||
|
self.scenes.get(index)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_scene_mut(&mut self) -> Option<&mut Box<dyn Scene>> {
|
||||||
|
log::debug!(
|
||||||
|
"current_scene_mut called - index: {:?}, scenes len: {}",
|
||||||
|
self.current_scene_index,
|
||||||
|
self.scenes.len()
|
||||||
|
);
|
||||||
|
if let Some(index) = self.current_scene_index {
|
||||||
|
log::debug!("Getting scene at index {}", index);
|
||||||
|
self.scenes.get_mut(index)
|
||||||
|
} else {
|
||||||
|
log::debug!("No current scene index set");
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_scene_if_not_loaded(
|
pub fn load_scene_if_not_loaded(
|
||||||
&mut self,
|
&mut self,
|
||||||
scene_context: &SceneContext,
|
app_context: &mut ApplicationContext,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
if let Some(current_scene) = self.current_scene.as_mut() {
|
log::debug!("SceneManager::load_scene_if_not_loaded called");
|
||||||
if !current_scene.loaded() {
|
log::debug!(
|
||||||
current_scene.load(scene_context)?;
|
"Current scene index: {:?}, scenes count: {}",
|
||||||
|
self.current_scene_index,
|
||||||
|
self.scenes.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(scene) = self.current_scene_mut() {
|
||||||
|
log::debug!("Scene found, checking if loaded: {}", scene.loaded());
|
||||||
|
if !scene.loaded() {
|
||||||
|
log::debug!("Scene not loaded, loading...");
|
||||||
|
scene.load(app_context)?;
|
||||||
|
log::debug!("Scene loaded successfully");
|
||||||
|
} else {
|
||||||
|
log::debug!("Scene already loaded");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!("No scene found in SceneManager!");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_scene(&mut self, scene: Box<dyn Scene>) {
|
|
||||||
if let Some(current_scene) = self.current_scene.as_mut() {
|
|
||||||
current_scene.unload();
|
|
||||||
}
|
|
||||||
self.current_scene = Some(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_scene(&self) -> Option<&Box<dyn Scene>> {
|
|
||||||
if let Some(current_scene) = self.current_scene.as_ref() {
|
|
||||||
if current_scene.loaded() {
|
|
||||||
return Some(current_scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_scene_mut(&mut self) -> Option<&mut Box<dyn Scene>> {
|
|
||||||
if let Some(current_scene) = self.current_scene.as_mut() {
|
|
||||||
if current_scene.loaded() {
|
|
||||||
return Some(current_scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,19 @@
|
||||||
use std::{error::Error, sync::Arc};
|
use std::error::Error;
|
||||||
|
|
||||||
use egui_winit_vulkano::Gui;
|
use vulkano::sync::GpuFuture;
|
||||||
use vulkano::{image::view::ImageView, sync::GpuFuture};
|
|
||||||
|
|
||||||
mod context;
|
use crate::core::app::context::ApplicationContext;
|
||||||
pub use context::SceneContext;
|
|
||||||
|
|
||||||
mod manager;
|
pub mod manager;
|
||||||
pub use manager::SceneManager;
|
|
||||||
|
|
||||||
pub trait Scene {
|
pub trait Scene {
|
||||||
fn loaded(&self) -> bool;
|
fn loaded(&self) -> bool;
|
||||||
fn load(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>>;
|
fn load(&mut self, app_context: &mut ApplicationContext) -> Result<(), Box<dyn Error>>;
|
||||||
fn update(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>>;
|
fn update(&mut self, app_context: &mut ApplicationContext) -> Result<(), Box<dyn Error>>;
|
||||||
fn render(
|
fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
acquire_future: Box<dyn GpuFuture>,
|
acquire_future: Box<dyn GpuFuture>,
|
||||||
scene_context: &SceneContext,
|
app_context: &mut ApplicationContext,
|
||||||
gui: &mut Gui,
|
|
||||||
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>>;
|
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>>;
|
||||||
fn unload(&mut self);
|
fn unload(&mut self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
use std::{error::Error, sync::Arc};
|
use std::error::Error;
|
||||||
|
|
||||||
|
use super::settings_scene::SettingsScene;
|
||||||
|
use crate::core::app::DEPTH_IMAGE_ID;
|
||||||
|
use crate::core::app::context::ApplicationContext;
|
||||||
use crate::core::app::user_event::UserEvent;
|
use crate::core::app::user_event::UserEvent;
|
||||||
use crate::core::render::primitives::camera::Camera3D;
|
use crate::core::render::primitives::camera::Camera3D;
|
||||||
use crate::core::render::primitives::transform::Transform;
|
use crate::core::render::primitives::transform::Transform;
|
||||||
|
use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager};
|
||||||
use crate::core::render::texture::Texture;
|
use crate::core::render::texture::Texture;
|
||||||
use crate::core::scene::Scene;
|
use crate::core::scene::Scene;
|
||||||
use crate::core::scene::SceneContext;
|
|
||||||
use crate::game::assets::square::Square;
|
use crate::game::assets::square::Square;
|
||||||
use egui_winit_vulkano::{Gui, egui};
|
use egui_winit_vulkano::egui;
|
||||||
use glam::EulerRot;
|
use glam::EulerRot;
|
||||||
use glam::Quat;
|
use glam::Quat;
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
command_buffer::{
|
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract},
|
||||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
|
|
||||||
RenderingAttachmentInfo, RenderingInfo,
|
|
||||||
},
|
|
||||||
pipeline::graphics::viewport::Viewport,
|
|
||||||
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
|
|
||||||
sync::GpuFuture,
|
sync::GpuFuture,
|
||||||
};
|
};
|
||||||
use winit::window::CursorGrabMode;
|
use winit::window::CursorGrabMode;
|
||||||
|
@ -40,12 +38,22 @@ impl Scene for MainScene {
|
||||||
self.state.is_some()
|
self.state.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
|
fn load(
|
||||||
|
&mut self,
|
||||||
|
app_context: &mut ApplicationContext,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let depth_image_view = app_context.with_renderer_mut(|renderer| {
|
||||||
|
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
let swapchain_image_view =
|
||||||
|
app_context.with_renderer_mut(|renderer| renderer.swapchain_image_view().clone());
|
||||||
|
|
||||||
let square = Square::new(
|
let square = Square::new(
|
||||||
&scene_context.device,
|
&app_context.device,
|
||||||
&scene_context.memory_allocator,
|
&app_context.memory_allocator,
|
||||||
scene_context.swapchain_image_view.format(),
|
swapchain_image_view.format(),
|
||||||
scene_context.depth_stencil_image_view.format(),
|
depth_image_view.format(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let num_instances = 100;
|
let num_instances = 100;
|
||||||
|
@ -69,29 +77,35 @@ impl Scene for MainScene {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let camera = Camera3D::new(
|
let texture = {
|
||||||
scene_context.aspect_ratio,
|
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||||
std::f32::consts::FRAC_PI_2,
|
app_context.command_buffer_allocator.clone(),
|
||||||
0.01,
|
app_context.graphics_queue.queue_family_index(),
|
||||||
1000.0,
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
);
|
)?;
|
||||||
|
|
||||||
let mut uploads = AutoCommandBufferBuilder::primary(
|
let texture = Texture::from_file(
|
||||||
scene_context.command_buffer_allocator.clone(),
|
&app_context.device,
|
||||||
scene_context.graphics_queue.queue_family_index(),
|
&app_context.memory_allocator,
|
||||||
CommandBufferUsage::OneTimeSubmit,
|
&mut uploads,
|
||||||
)?;
|
"res/textures/wooden-crate.jpg",
|
||||||
|
)?;
|
||||||
|
|
||||||
let texture = Texture::from_file(
|
let _ = uploads
|
||||||
&scene_context.device,
|
.build()?
|
||||||
&scene_context.memory_allocator,
|
.execute(app_context.graphics_queue.clone())?;
|
||||||
&mut uploads,
|
|
||||||
"res/textures/wooden-crate.jpg",
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let _ = uploads
|
texture
|
||||||
.build()?
|
};
|
||||||
.execute(scene_context.graphics_queue.clone())?;
|
|
||||||
|
let camera = app_context.with_renderer(|renderer| {
|
||||||
|
Camera3D::new(
|
||||||
|
renderer.aspect_ratio(),
|
||||||
|
std::f32::consts::FRAC_PI_2,
|
||||||
|
0.01,
|
||||||
|
1000.0,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
self.state = Some(MainSceneState {
|
self.state = Some(MainSceneState {
|
||||||
square,
|
square,
|
||||||
|
@ -104,44 +118,46 @@ impl Scene for MainScene {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, scene_context: &SceneContext) -> Result<(), Box<dyn Error>> {
|
fn update(&mut self, app_context: &mut ApplicationContext) -> Result<(), Box<dyn Error>> {
|
||||||
let state = self.state.as_mut().ok_or("State not found")?;
|
let state = self.state.as_mut().unwrap();
|
||||||
state.camera.update(
|
app_context.with_input_manager(|input_manager| {
|
||||||
&scene_context.input_manager,
|
app_context.with_timer(|timer| {
|
||||||
&scene_context.timer,
|
state.camera.update(
|
||||||
state.speed,
|
input_manager,
|
||||||
10.0,
|
timer,
|
||||||
scene_context.aspect_ratio,
|
state.speed,
|
||||||
);
|
10.0,
|
||||||
|
app_context.get_aspect_ratio(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if scene_context
|
if app_context
|
||||||
.input_manager
|
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
||||||
.get_virtual_input_state("mouse_left")
|
|
||||||
> 0.0
|
> 0.0
|
||||||
{
|
{
|
||||||
let _ = scene_context
|
let _ = app_context
|
||||||
.event_loop_proxy
|
.event_loop_proxy
|
||||||
.send_event(UserEvent::CursorVisible(scene_context.window_id, false));
|
.send_event(UserEvent::CursorVisible(app_context.window_id, false));
|
||||||
let _ = scene_context
|
let _ = app_context
|
||||||
.event_loop_proxy
|
.event_loop_proxy
|
||||||
.send_event(UserEvent::CursorGrabMode(
|
.send_event(UserEvent::CursorGrabMode(
|
||||||
scene_context.window_id,
|
app_context.window_id,
|
||||||
CursorGrabMode::Locked,
|
CursorGrabMode::Locked,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if scene_context
|
if app_context.with_input_manager(|input_manager| {
|
||||||
.input_manager
|
input_manager.get_virtual_input_state("mouse_right")
|
||||||
.get_virtual_input_state("mouse_right")
|
}) > 0.0
|
||||||
> 0.0
|
|
||||||
{
|
{
|
||||||
let _ = scene_context
|
let _ = app_context
|
||||||
.event_loop_proxy
|
.event_loop_proxy
|
||||||
.send_event(UserEvent::CursorVisible(scene_context.window_id, true));
|
.send_event(UserEvent::CursorVisible(app_context.window_id, true));
|
||||||
let _ = scene_context
|
let _ = app_context
|
||||||
.event_loop_proxy
|
.event_loop_proxy
|
||||||
.send_event(UserEvent::CursorGrabMode(
|
.send_event(UserEvent::CursorGrabMode(
|
||||||
scene_context.window_id,
|
app_context.window_id,
|
||||||
CursorGrabMode::None,
|
CursorGrabMode::None,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -151,87 +167,112 @@ impl Scene for MainScene {
|
||||||
|
|
||||||
fn render(
|
fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
acquire_future: Box<dyn GpuFuture>,
|
before_future: Box<dyn GpuFuture>,
|
||||||
scene_context: &SceneContext,
|
app_context: &mut ApplicationContext,
|
||||||
gui: &mut Gui,
|
|
||||||
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
|
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
|
||||||
let state = self.state.as_ref().ok_or("State not found")?;
|
let state = self.state.as_ref().ok_or("State not loaded")?;
|
||||||
|
|
||||||
let mut builder = AutoCommandBufferBuilder::primary(
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
scene_context.command_buffer_allocator.clone(),
|
app_context.command_buffer_allocator.clone(),
|
||||||
scene_context.graphics_queue.queue_family_index(),
|
app_context.graphics_queue.queue_family_index(),
|
||||||
CommandBufferUsage::OneTimeSubmit,
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let viewport = Viewport {
|
let swapchain_image_view =
|
||||||
offset: [0.0, 0.0],
|
app_context.with_renderer_mut(|renderer| renderer.swapchain_image_view().clone());
|
||||||
extent: scene_context.window_size,
|
let depth_image_view = app_context.with_renderer_mut(|renderer| {
|
||||||
depth_range: 0.0..=1.0,
|
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
|
||||||
};
|
});
|
||||||
|
let config = RenderPassConfig::default();
|
||||||
builder
|
RenderPassManager::begin_standard_rendering(
|
||||||
.begin_rendering(RenderingInfo {
|
&mut builder,
|
||||||
color_attachments: vec![Some(RenderingAttachmentInfo {
|
&config,
|
||||||
load_op: AttachmentLoadOp::Clear,
|
swapchain_image_view,
|
||||||
store_op: AttachmentStoreOp::Store,
|
Some(depth_image_view),
|
||||||
clear_value: Some([0.0, 0.0, 0.0, 1.0].into()),
|
app_context.get_window_size(),
|
||||||
..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
|
// Create camera uniform using the actual camera
|
||||||
.camera
|
let camera_uniform = state.camera.create_buffer(&app_context.memory_allocator)?;
|
||||||
.create_buffer(&scene_context.memory_allocator)?;
|
|
||||||
|
|
||||||
let transform_uniform =
|
let transform_uniform =
|
||||||
Transform::create_buffer(&scene_context.memory_allocator, &state.instances)?;
|
Transform::create_buffer(&app_context.memory_allocator, &state.instances)?;
|
||||||
|
|
||||||
state
|
state
|
||||||
.square
|
.square
|
||||||
.render(
|
.render(
|
||||||
&mut builder,
|
&mut builder,
|
||||||
&scene_context.descriptor_set_allocator,
|
&app_context.descriptor_set_allocator,
|
||||||
&camera_uniform,
|
&camera_uniform,
|
||||||
&transform_uniform,
|
&transform_uniform,
|
||||||
&state.texture,
|
&state.texture,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
builder.end_rendering()?;
|
RenderPassManager::end_rendering(&mut builder)?;
|
||||||
|
|
||||||
let command_buffer = builder.build()?;
|
let command_buffer = builder.build()?;
|
||||||
|
|
||||||
let render_future =
|
let render_future =
|
||||||
acquire_future.then_execute(scene_context.graphics_queue.clone(), command_buffer)?;
|
before_future.then_execute(app_context.graphics_queue.clone(), command_buffer)?;
|
||||||
|
|
||||||
gui.immediate_ui(|gui| {
|
let swapchain_image_view =
|
||||||
let ctx = gui.context();
|
app_context.with_renderer_mut(|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();
|
||||||
|
let render_future = app_context.with_gui_mut(|gui| {
|
||||||
|
gui.immediate_ui(|gui| {
|
||||||
|
let ctx = gui.context();
|
||||||
|
egui::TopBottomPanel::top("top_panel").show(&ctx, |ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.heading("Vulkan Test - Moteur 3D");
|
||||||
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
|
if ui.button("Paramètres").clicked() {
|
||||||
|
let _ = event_loop_proxy.send_event(UserEvent::ChangeScene(
|
||||||
|
window_id,
|
||||||
|
Box::new(SettingsScene::default()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if ui.button("Quitter").clicked() {
|
||||||
|
let _ = event_loop_proxy.send_event(UserEvent::Exit(window_id));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
egui::Window::new("Informations")
|
egui::SidePanel::left("side_panel").show(&ctx, |ui| {
|
||||||
.vscroll(true)
|
ui.heading("Informations");
|
||||||
.show(&ctx, |ui| {
|
|
||||||
ui.label(format!("Resolution: {:?}", scene_context.window_size));
|
|
||||||
|
|
||||||
ui.label(format!("{:#?}", scene_context.input_manager));
|
ui.separator();
|
||||||
|
|
||||||
ui.label(format!(
|
ui.label(format!("Résolution: {:?}", window_size));
|
||||||
"Delta time: {:?}",
|
ui.label(format!("Delta Time: {:.2}ms", delta_time * 1000.0));
|
||||||
scene_context.timer.delta_time()
|
|
||||||
));
|
ui.separator();
|
||||||
|
|
||||||
|
ui.label("Position caméra:");
|
||||||
|
let position = state.camera.get_position();
|
||||||
|
ui.label(format!(" X: {:.2}", position[0]));
|
||||||
|
ui.label(format!(" Y: {:.2}", position[1]));
|
||||||
|
ui.label(format!(" Z: {:.2}", position[2]));
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.label("Rotation caméra:");
|
||||||
|
let rotation = state.camera.get_rotation();
|
||||||
|
ui.label(format!(" Yaw: {:.2}°", rotation.y.to_degrees()));
|
||||||
|
ui.label(format!(" Pitch: {:.2}°", rotation.x.to_degrees()));
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
ui.label(input_manager_status);
|
||||||
|
|
||||||
|
ui.label(format!("Delta time: {:?}", delta_time));
|
||||||
|
|
||||||
ui.label(format!(
|
ui.label(format!(
|
||||||
"Position: {:?}, Rotation: {:?}",
|
"Position: {:?}, Rotation: {:?}",
|
||||||
|
@ -239,13 +280,17 @@ impl Scene for MainScene {
|
||||||
state.camera.get_rotation()
|
state.camera.get_rotation()
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let render_future =
|
let render_future = gui.draw_on_image(render_future, swapchain_image_view.clone());
|
||||||
gui.draw_on_image(render_future, scene_context.swapchain_image_view.clone());
|
|
||||||
|
render_future
|
||||||
|
});
|
||||||
|
|
||||||
Ok(render_future)
|
Ok(render_future)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unload(&mut self) {}
|
fn unload(&mut self) {
|
||||||
|
self.state = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod main_scene;
|
pub mod main_scene;
|
||||||
pub mod test_scene;
|
pub mod settings_scene;
|
||||||
|
|
135
src/game/scenes/settings_scene.rs
Normal file
135
src/game/scenes/settings_scene.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use crate::core::app::DEPTH_IMAGE_ID;
|
||||||
|
use crate::core::app::context::ApplicationContext;
|
||||||
|
use crate::core::app::user_event::UserEvent;
|
||||||
|
use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager};
|
||||||
|
use crate::core::scene::Scene;
|
||||||
|
use egui_winit_vulkano::egui;
|
||||||
|
use vulkano::{
|
||||||
|
command_buffer::AutoCommandBufferBuilder, command_buffer::CommandBufferUsage, sync::GpuFuture,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::main_scene::MainScene;
|
||||||
|
|
||||||
|
pub struct SettingsSceneState {
|
||||||
|
current_resolution: [f32; 2],
|
||||||
|
available_resolutions: Vec<(u32, u32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct SettingsScene {
|
||||||
|
state: Option<SettingsSceneState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scene for SettingsScene {
|
||||||
|
fn loaded(&self) -> bool {
|
||||||
|
self.state.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&mut self, app_context: &mut ApplicationContext) -> Result<(), Box<dyn Error>> {
|
||||||
|
let current_resolution = app_context.get_window_size();
|
||||||
|
let available_resolutions = app_context.get_available_resolutions();
|
||||||
|
|
||||||
|
self.state = Some(SettingsSceneState {
|
||||||
|
current_resolution,
|
||||||
|
available_resolutions,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _app_context: &mut ApplicationContext) -> Result<(), Box<dyn Error>> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(
|
||||||
|
&mut self,
|
||||||
|
before_future: Box<dyn GpuFuture>,
|
||||||
|
app_context: &mut ApplicationContext,
|
||||||
|
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
|
||||||
|
let state = self.state.as_ref().ok_or("State not found")?;
|
||||||
|
|
||||||
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
|
app_context.command_buffer_allocator.clone(),
|
||||||
|
app_context.graphics_queue.queue_family_index(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Utiliser le RenderPassManager
|
||||||
|
{
|
||||||
|
let swapchain_image_view =
|
||||||
|
app_context.with_renderer_mut(|renderer| renderer.swapchain_image_view().clone());
|
||||||
|
let depth_stencil_image_view = app_context.with_renderer_mut(|renderer| {
|
||||||
|
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
|
||||||
|
});
|
||||||
|
let config = RenderPassConfig::default();
|
||||||
|
RenderPassManager::begin_standard_rendering(
|
||||||
|
&mut builder,
|
||||||
|
&config,
|
||||||
|
swapchain_image_view,
|
||||||
|
Some(depth_stencil_image_view),
|
||||||
|
app_context.get_window_size(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pas de géométrie dans cette scène - juste un écran de paramètres
|
||||||
|
RenderPassManager::end_rendering(&mut builder)?;
|
||||||
|
|
||||||
|
let command_buffer = builder.build()?;
|
||||||
|
|
||||||
|
let render_future =
|
||||||
|
before_future.then_execute(app_context.graphics_queue.clone(), command_buffer)?;
|
||||||
|
|
||||||
|
let swapchain_image_view =
|
||||||
|
app_context.with_renderer_mut(|renderer| renderer.swapchain_image_view().clone());
|
||||||
|
|
||||||
|
let event_loop_proxy = app_context.event_loop_proxy.clone();
|
||||||
|
let window_id = app_context.window_id;
|
||||||
|
|
||||||
|
let render_future = app_context.with_gui_mut(|gui| {
|
||||||
|
gui.immediate_ui(|gui| {
|
||||||
|
let ctx = gui.context();
|
||||||
|
|
||||||
|
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||||
|
ui.heading("Paramètres");
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.label(format!(
|
||||||
|
"Résolution actuelle: {:?}",
|
||||||
|
state.current_resolution
|
||||||
|
));
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
ui.label("Changer la résolution:");
|
||||||
|
|
||||||
|
for &(width, height) in &state.available_resolutions {
|
||||||
|
if ui.button(format!("{}x{}", width, height)).clicked() {
|
||||||
|
let _ = event_loop_proxy.send_event(UserEvent::ChangeResolution(
|
||||||
|
window_id,
|
||||||
|
width as f32,
|
||||||
|
height as f32,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
if ui.button("Retour au jeu").clicked() {
|
||||||
|
let _ = event_loop_proxy.send_event(UserEvent::ChangeScene(
|
||||||
|
window_id,
|
||||||
|
Box::new(MainScene::default()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gui.draw_on_image(render_future, swapchain_image_view.clone())
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(render_future)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unload(&mut self) {}
|
||||||
|
}
|
|
@ -1,111 +0,0 @@
|
||||||
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) {}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue