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
use core::{
app::{App, AppTimer, BackendAppRunner},
Scalar,
};
use std::{cell::RefCell, rc::Rc, time::Duration};
use wasm_bindgen::{prelude::*, JsCast};
fn window() -> web_sys::Window {
web_sys::window().expect("no global `window` exists")
}
fn request_animation_frame(f: &Closure<dyn FnMut()>) {
window()
.request_animation_frame(f.as_ref().unchecked_ref())
.expect("Could not perform `requestAnimationFrame`");
}
fn performance() -> web_sys::Performance {
window()
.performance()
.expect("no `window.performance` exists")
}
pub struct WebAppTimer {
timer: Scalar,
delta_time: Duration,
delta_time_seconds: Scalar,
}
impl Default for WebAppTimer {
fn default() -> Self {
Self {
timer: performance().now() as Scalar * 0.001,
delta_time: Duration::default(),
delta_time_seconds: 0.0,
}
}
}
impl AppTimer for WebAppTimer {
fn tick(&mut self) {
let t = performance().now() as Scalar * 0.001;
let d = t - self.timer;
self.timer = t;
self.delta_time = Duration::new(d as u64, (d.fract() * 1e9) as u32);
self.delta_time_seconds = d;
}
fn now_since_start(&self) -> Duration {
let t = performance().now() as Scalar * 0.001;
let d = t - self.timer;
Duration::new(d as u64, (d.fract() * 1e9) as u32)
}
fn delta_time(&self) -> Duration {
self.delta_time
}
fn delta_time_seconds(&self) -> Scalar {
self.delta_time_seconds
}
}
#[derive(Default)]
pub struct WebAppRunner;
impl BackendAppRunner<JsValue> for WebAppRunner {
fn run(&mut self, app: Rc<RefCell<App>>) -> Result<(), JsValue> {
let f = Rc::new(RefCell::new(None));
let g = f.clone();
*g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
if !app.borrow().multiverse.is_running() {
drop(f.borrow_mut().take());
return;
}
app.borrow_mut().process();
request_animation_frame(f.borrow().as_ref().unwrap());
}) as Box<dyn FnMut()>));
request_animation_frame(g.borrow().as_ref().unwrap());
Ok(())
}
}