use std::ptr;
use std::cell::RefCell;
use std::os::raw::{c_int, c_void};
use super::super::{now, ControlFlow};
extern "C" {
fn emscripten_set_main_loop(
func: unsafe extern "C" fn(),
fps: c_int,
simulate_infinite_loop: c_int,
);
fn emscripten_resume_main_loop();
fn emscripten_pause_main_loop();
}
thread_local!(
static MAIN_LOOP_CALLBACK: RefCell<*mut c_void> = RefCell::new(ptr::null_mut());
static MAIN_MS: RefCell<f64> = RefCell::new(0.0);
);
unsafe extern "C" fn callback_wrapper<F>()
where
F: FnMut(f64),
{
MAIN_LOOP_CALLBACK.with(|ref_cell| {
let closure = *ref_cell.borrow_mut() as *mut F;
let ms = now() - MAIN_MS.with(|ref_cell| *ref_cell.borrow());
(*closure)(ms);
});
}
#[inline]
fn set_callback_loop<F>(callback: F)
where
F: FnMut(f64),
{
MAIN_LOOP_CALLBACK.with(|ref_cell| {
*ref_cell.borrow_mut() = &callback as *const _ as *mut c_void;
});
unsafe {
emscripten_set_main_loop(callback_wrapper::<F>, 0, 1);
emscripten_pause_main_loop();
}
}
#[inline(always)]
fn pause_loop() {
unsafe {
emscripten_pause_main_loop();
}
}
#[inline(always)]
pub fn set_target_fps(_: f64) {}
#[inline(always)]
pub fn target_fps() -> f64 {
1000.0 / 60.0
}
#[inline]
pub fn run<F>(mut callback: F)
where
F: FnMut(f64) -> ControlFlow,
{
set_callback_loop(move |ms| match callback(ms) {
ControlFlow::Break => pause_loop(),
ControlFlow::Continue => (),
});
MAIN_MS.with(|ref_cell| {
*ref_cell.borrow_mut() = now();
});
unsafe {
emscripten_resume_main_loop();
}
}