swamp_app/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/swamp-render
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 */
pub mod prelude;

use int_math::UVec2;
use log::trace;
use std::sync::Arc;
use swamp_render::prelude::{Assets, Gfx};
use swamp_render::Render;
use swamp_wgpu_window::WgpuWindow;
use swamp_window::AppHandler;
use winit::dpi;
use winit::window::Window;

pub trait Application {
    fn new(gfx: &mut impl Assets) -> Self;
    fn tick(&mut self);
    fn render(&mut self, gfx: &mut impl Gfx);
}

pub struct AppInfo<'a, T: Application> {
    window: WgpuWindow<'a>,
    main_render: Render,
    app: T,
}

pub struct App<'a, T: Application> {
    app: Option<AppInfo<'a, T>>,
    virtual_surface_size: UVec2,
    suggested_physical_surface_size: UVec2,
}

impl<'a, T: Application> AppHandler for App<'a, T> {
    fn create_window(&mut self, window: Arc<Window>) {
        trace!("create window, boot up");
        let physical_size = window.inner_size();

        let wgpu_window = pollster::block_on(WgpuWindow::new(window)).expect("REASON");

        let mut render = Render::new(
            Arc::clone(wgpu_window.device()),
            Arc::clone(wgpu_window.queue()),
            wgpu_window.surface_config().format,
            (physical_size.width as u16, physical_size.height as u16).into(),
            self.virtual_surface_size,
        );

        let custom_app = T::new(&mut render);

        self.app = Some(AppInfo {
            window: wgpu_window,
            main_render: render,
            app: custom_app,
        })
    }

    fn resized(&mut self, physical_size: dpi::PhysicalSize<u32>) {
        trace!("window resized (physical_size: {:?})", physical_size);
        if let Some(ref mut info) = self.app {
            info.window.resize(physical_size);
            info.main_render
                .resize((physical_size.width as u16, physical_size.height as u16).into());
        }
    }

    fn min_size(&self) -> (u16, u16) {
        (self.virtual_surface_size.x, self.virtual_surface_size.y)
    }

    fn start_size(&self) -> (u16, u16) {
        (
            self.suggested_physical_surface_size.x,
            self.suggested_physical_surface_size.y,
        )
    }

    fn redraw(&mut self) {
        if let Some(ref mut info) = self.app {
            info.app.tick(); // TODO: Fix a better tick rate
            info.app.render(&mut info.main_render);
            info.window
                .render(info.main_render.clear_color(), |render_pass, _, _| {
                    info.main_render.render(render_pass)
                })
                .expect("TODO: panic message");
        }
    }
}
impl<'a, T: Application> App<'a, T> {
    pub fn run(title: &str, virtual_surface_size: UVec2, suggested_physical_surface_size: UVec2) {
        env_logger::init();

        let mut app = Self {
            app: None,
            virtual_surface_size,
            suggested_physical_surface_size,
        };

        let _ = swamp_window::WindowRunner::run_app(&mut app, title);
    }
}