pyxel_platform/
platform.rs

1use std::mem::transmute;
2use std::ptr::{addr_of_mut, null_mut};
3
4use cfg_if::cfg_if;
5use glow::Context as GlowContext;
6
7use crate::gamepad::{init_gamepads, Gamepad};
8use crate::sdl2_sys::*;
9use crate::window::{init_glow, init_window};
10
11pub struct Platform {
12    pub window: *mut SDL_Window,
13    pub glow_context: *mut GlowContext,
14    pub audio_device_id: SDL_AudioDeviceID,
15    pub mouse_x: i32,
16    pub mouse_y: i32,
17    pub gamepads: Vec<Gamepad>,
18    #[cfg(target_os = "emscripten")]
19    pub virtual_gamepad_states: [bool; 8],
20}
21
22static mut PLATFORM: *mut Platform = null_mut();
23
24pub fn platform() -> &'static mut Platform {
25    unsafe { &mut *PLATFORM }
26}
27
28pub fn init<'a, F: FnOnce(u32, u32) -> (&'a str, u32, u32)>(window_params: F) {
29    assert!(
30        unsafe { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER,) } >= 0,
31        "Failed to initialize SDL2"
32    );
33
34    let mut display_mode = SDL_DisplayMode {
35        format: 0,
36        w: 0,
37        h: 0,
38        refresh_rate: 0,
39        driverdata: null_mut(),
40    };
41    assert!(
42        unsafe { SDL_GetCurrentDisplayMode(0, addr_of_mut!(display_mode)) } == 0,
43        "Failed to get display size"
44    );
45
46    let (title, width, height) = window_params(display_mode.w as u32, display_mode.h as u32);
47
48    let window = init_window(title, width, height);
49    let glow_context = init_glow(window);
50    let gamepads = init_gamepads();
51
52    unsafe {
53        PLATFORM = transmute::<Box<Platform>, *mut Platform>(Box::new(Platform {
54            window,
55            glow_context,
56            audio_device_id: 0,
57            mouse_x: i32::MIN,
58            mouse_y: i32::MIN,
59            gamepads,
60            #[cfg(target_os = "emscripten")]
61            virtual_gamepad_states: [false; 8],
62        }));
63    }
64}
65
66#[allow(unused_mut)]
67pub fn run<F: FnMut()>(mut main_loop: F) {
68    cfg_if! {
69        if #[cfg(target_os = "emscripten")] {
70            crate::emscripten::run(main_loop);
71        } else {
72            loop {
73                let start_ms = elapsed_time() as f64;
74                main_loop();
75                let elapsed_ms = elapsed_time() as f64 - start_ms;
76                let wait_ms = 1000.0 / 60.0 - elapsed_ms;
77                if wait_ms > 0.0 {
78                    sleep((wait_ms / 2.0) as u32);
79                }
80            }
81        }
82    }
83}
84
85pub fn quit() {
86    unsafe {
87        SDL_Quit();
88    }
89
90    cfg_if! {
91        if #[cfg(target_os = "emscripten")] {
92            crate::emscripten::exit(0);
93        } else {
94            std::process::exit(0);
95        }
96    }
97}
98
99pub fn elapsed_time() -> u32 {
100    unsafe { SDL_GetTicks() }
101}
102
103pub fn sleep(ms: u32) {
104    unsafe {
105        SDL_Delay(ms);
106    }
107}