Skip to main content

libdqg/
scene.rs

1use crate::{
2    input::{InputState, MouseState},
3    renderer::{DrawPass, Renderer},
4};
5
6pub trait Scene {
7    fn update(&mut self, delta_time: f32, input_state: &InputState, mouse_state: &MouseState, renderer: Option<&mut Renderer>) -> SceneTransition;
8    fn render(&mut self, pass: &mut DrawPass);
9
10    /// Receives every raw `winit` window event, ahead of any `App`-level handling. Default is a
11    /// no-op; override to feed events into something like `egui-winit` that needs the raw stream.
12    fn on_window_event(&mut self, _event: &winit::event::WindowEvent) {}
13
14    /// Called after the main render pass has ended but before the frame is submitted, with the
15    /// same encoder/target view so a second pass can be recorded on top (e.g. compositing an
16    /// `egui` UI). Default is a no-op.
17    fn render_overlay(&mut self, _device: &wgpu::Device, _queue: &wgpu::Queue, _encoder: &mut wgpu::CommandEncoder, _view: &wgpu::TextureView) {}
18}
19
20pub enum SceneTransition {
21    None,
22    Push(Box<dyn Scene>),
23    Pop,
24    Replace(Box<dyn Scene>),
25    Next,
26    Previous,
27    Quit,
28}
29
30pub struct SceneManager {
31    scenes: Vec<Box<dyn Scene>>,
32    current_scene_index: usize,
33}
34
35impl SceneManager {
36    pub fn new() -> Self {
37        Self { scenes: Vec::new(), current_scene_index: 0 }
38    }
39
40    pub fn add_scene(&mut self, scene: Box<dyn Scene>) {
41        self.scenes.push(scene);
42    }
43
44    pub fn update(&mut self, delta_time: f32, input_state: &InputState, mouse_state: &MouseState, renderer: Option<&mut Renderer>) {
45        if let Some(current_scene) = self.scenes.get_mut(self.current_scene_index) {
46            let transition = current_scene.update(delta_time, input_state, mouse_state, renderer);
47            match transition {
48                SceneTransition::None => (),
49                SceneTransition::Push(new_scene) => self.scenes.push(new_scene),
50                SceneTransition::Pop => {
51                    self.scenes.pop();
52                    self.current_scene_index %= self.scenes.len(); // Ensure the index is valid after popping
53                }
54                SceneTransition::Replace(new_scene) => {
55                    self.scenes[self.current_scene_index] = new_scene;
56                }
57                SceneTransition::Quit => {
58                    todo!(); // Handle quitting the game, e.g., by signaling the app to exit
59                }
60                SceneTransition::Next => {
61                    self.current_scene_index = (self.current_scene_index + 1) % self.scenes.len();
62                }
63                SceneTransition::Previous => {
64                    self.current_scene_index = (self.current_scene_index + self.scenes.len() - 1) % self.scenes.len();
65                }
66            }
67        }
68    }
69
70    pub fn render(&mut self, pass: &mut DrawPass) {
71        if let Some(current_scene) = self.scenes.get_mut(self.current_scene_index) {
72            current_scene.render(pass);
73        }
74    }
75
76    pub fn on_window_event(&mut self, event: &winit::event::WindowEvent) {
77        if let Some(current_scene) = self.scenes.get_mut(self.current_scene_index) {
78            current_scene.on_window_event(event);
79        }
80    }
81
82    pub fn render_overlay(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView) {
83        if let Some(current_scene) = self.scenes.get_mut(self.current_scene_index) {
84            current_scene.render_overlay(device, queue, encoder, view);
85        }
86    }
87}