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
/*
 * 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.
 */

use async_trait::async_trait;
use log::info;
use std::fmt::Debug;
use std::sync::Arc;
use swamp_render::Render;
use swamp_wgpu_window::WgpuWindow;
use swamp_window::AppHandler;
use winit::dpi;
use winit::window::Window;

pub trait Application: Debug {
    fn init(&mut self, render: &mut Render);
    fn tick(&mut self);
    fn render(&mut self, render: &mut Render);
    fn virtual_surface_size(&self) -> (u16, u16);
    fn physical_surface_size(&self) -> (u16, u16);
}

#[derive(Debug)]
pub struct App<'a> {
    main_render: Option<Render>,
    wgpu_window: Option<WgpuWindow<'a>>,
    app: &'a mut dyn Application,
}

#[async_trait(?Send)]
impl<'a> AppHandler for App<'a> {
    fn create_window(&mut self, window: Arc<Window>) {
        info!("create window!");
        let physical_size = window.inner_size();
        let virtual_size = self.app.virtual_surface_size();
        let wgpu_window = pollster::block_on(WgpuWindow::new(window)).expect("REASON");

        self.main_render = Some(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),
            virtual_size,
        ));

        self.wgpu_window = Some(wgpu_window);

        self.app.init(self.main_render.as_mut().unwrap())
    }

    fn resized(&mut self, physical_size: dpi::PhysicalSize<u32>) {
        info!("resized! (physical_size: {:?})", physical_size);
        self.wgpu_window.as_mut().unwrap().resize(physical_size);
        self.main_render
            .as_mut()
            .unwrap()
            .resize((physical_size.width as u16, physical_size.height as u16));
    }

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

    fn start_size(&self) -> (u16, u16) {
        self.app.physical_surface_size()
    }

    fn redraw(&mut self) {
        let main_render = self.main_render.as_mut().expect("REASON");
        self.app.tick(); // TODO: Fix a better tick rate
        self.app.render(main_render);
        self.wgpu_window
            .as_mut()
            .unwrap()
            .render(main_render.clear_color(), |render_pass, _, _| {
                main_render.render(render_pass)
            })
            .expect("TODO: panic message");
    }
}

impl<'a> App<'a> {
    pub fn run(application: &'a mut impl Application, title: &str) {
        let mut app = Self {
            main_render: None,
            app: application,
            wgpu_window: None,
        };
        let _ = swamp_window::WindowRunner::run_app(&mut app, title);
    }
}