pub enum SceneSwitch<C> {
None,
Push(Box<dyn Scene<C>>),
Replace(Box<dyn Scene<C>>),
Pop,
}
pub trait Scene<C> {
fn update(
&mut self,
gameworld: &mut C,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) -> SceneSwitch<C>;
fn draw(
&mut self,
gameworld: &mut C,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) -> crate::GameResult<()>;
fn resize_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_width: f32,
_height: f32,
) {
}
#[allow(clippy::too_many_arguments)]
fn mouse_motion_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_x: f32,
_y: f32,
_dx: f32,
_dy: f32,
) {
}
fn mouse_wheel_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_x: f32,
_y: f32,
) {
}
fn mouse_button_down_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_button: crate::event::MouseButton,
_x: f32,
_y: f32,
) {
}
fn mouse_button_up_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_button: crate::event::MouseButton,
_x: f32,
_y: f32,
) {
}
fn key_down_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_key: crate::event::KeyCode,
) {
}
fn key_up_event(
&mut self,
_gameworld: &mut C,
_ctx: &mut crate::Context,
_quad_ctx: &mut miniquad::graphics::GraphicsContext,
_key: crate::event::KeyCode,
) {
}
fn name(&self) -> &str;
fn draw_previous(&self) -> bool {
false
}
}
impl<C> SceneSwitch<C> {
pub fn replace<S>(scene: S) -> Self
where
S: Scene<C> + 'static,
{
SceneSwitch::Replace(Box::new(scene))
}
pub fn push<S>(scene: S) -> Self
where
S: Scene<C> + 'static,
{
SceneSwitch::Push(Box::new(scene))
}
}
pub struct SceneStack<C> {
pub world: C,
scenes: Vec<Box<dyn Scene<C>>>,
}
impl<C> SceneStack<C> {
pub fn new(_ctx: &mut crate::Context, global_state: C) -> Self {
Self {
world: global_state,
scenes: Vec::new(),
}
}
pub fn push(&mut self, scene: Box<dyn Scene<C>>) {
self.scenes.push(scene)
}
pub fn pop(&mut self) -> Box<dyn Scene<C>> {
self.scenes
.pop()
.expect("ERROR: Popped an empty scene stack.")
}
pub fn current(&self) -> &dyn Scene<C> {
&**self
.scenes
.last()
.expect("ERROR: Tried to get current scene of an empty scene stack.")
}
pub fn switch(&mut self, next_scene: SceneSwitch<C>) -> Option<Box<dyn Scene<C>>> {
match next_scene {
SceneSwitch::None => None,
SceneSwitch::Pop => {
let s = self.pop();
Some(s)
}
SceneSwitch::Push(s) => {
self.push(s);
None
}
SceneSwitch::Replace(s) => {
let old_scene = self.pop();
self.push(s);
Some(old_scene)
}
}
}
pub fn update(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) {
let next_scene = {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.update(&mut self.world, ctx, quad_ctx)
};
self.switch(next_scene);
}
fn draw_scenes(
scenes: &mut [Box<dyn Scene<C>>],
world: &mut C,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) {
assert!(!scenes.is_empty());
if let Some((current, rest)) = scenes.split_last_mut() {
if current.draw_previous() {
SceneStack::draw_scenes(rest, world, ctx, quad_ctx);
}
current
.draw(world, ctx, quad_ctx)
.expect("I would hope drawing a scene never fails!");
}
}
pub fn draw(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) {
SceneStack::draw_scenes(&mut self.scenes, &mut self.world, ctx, quad_ctx)
}
}
impl<C, E: std::error::Error> crate::event::EventHandler<E> for SceneStack<C> {
fn update(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) -> Result<(), E> {
self.update(ctx, quad_ctx);
Ok(())
}
fn draw(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
) -> Result<(), E> {
self.draw(ctx, quad_ctx);
Ok(())
}
fn resize_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
width: f32,
height: f32,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.resize_event(&mut self.world, ctx, quad_ctx, width, height)
}
fn mouse_motion_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
x: f32,
y: f32,
dx: f32,
dy: f32,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.mouse_motion_event(&mut self.world, ctx, quad_ctx, x, y, dx, dy);
}
fn mouse_wheel_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
x: f32,
y: f32,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.mouse_wheel_event(&mut self.world, ctx, quad_ctx, x, y);
}
fn mouse_button_down_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
button: crate::event::MouseButton,
x: f32,
y: f32,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.mouse_button_down_event(&mut self.world, ctx, quad_ctx, button, x, y);
}
fn mouse_button_up_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
button: crate::event::MouseButton,
x: f32,
y: f32,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.mouse_button_up_event(&mut self.world, ctx, quad_ctx, button, x, y);
}
fn key_down_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
keycode: crate::event::KeyCode,
_keymods: crate::event::KeyMods,
_repeat: bool,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.key_down_event(&mut self.world, ctx, quad_ctx, keycode);
}
fn key_up_event(
&mut self,
ctx: &mut crate::Context,
quad_ctx: &mut miniquad::graphics::GraphicsContext,
keycode: crate::event::KeyCode,
_keymods: crate::event::KeyMods,
) {
let current_scene = &mut **self
.scenes
.last_mut()
.expect("Tried to update empty scene stack");
current_scene.key_up_event(&mut self.world, ctx, quad_ctx, keycode);
}
}