use std::cell::RefCell; use std::sync::{Mutex}; use std::rc::Rc; use log::{Level, info, debug}; use wasm_bindgen::prelude::*; use state::State; mod line; mod point; mod state; struct RenderLoop { animation_id: Option, pub closure: Option>, } impl RenderLoop { pub fn new() -> Self { Self { animation_id: None, closure: None, } } } fn window() -> web_sys::Window { web_sys::window().expect("no window") } fn document() -> web_sys::Document { window().document().expect("no document") } fn canvas() -> Result { let x = document() .query_selector("canvas")? .expect("canvas element"); Ok(x.dyn_into::()?) } fn fps() -> Result { let x = document() .query_selector("#fps")? .expect("fps counter exists"); Ok(x.dyn_into::()?) } fn go() -> Result { let x = document() .query_selector("button")? .expect("go button exists"); Ok(x.dyn_into::()?) } #[wasm_bindgen(start)] pub fn init() -> Result<(), JsValue> { console_log::init_with_level(Level::Debug).expect("couldn't init console log"); info!("wasm init"); let paused = Rc::new(Mutex::new(true)); let p1 = paused.clone(); let mut s = State::new(canvas()?, fps()?)?; s.render_frame(0.0)?; // // from https://users.rust-lang.org/t/wasm-web-sys-how-to-use-window-request-animation-frame-resolved/20882 // let render_loop: Rc> = Rc::new(RefCell::new(RenderLoop::new())); { let closure: Closure = { let render_loop_clone = render_loop.clone(); Closure::wrap(Box::new(move |t| { s.render_frame(t).expect("should render frame"); let p = paused.lock().unwrap(); if !*p { let mut render_loop_mut = render_loop_clone.borrow_mut(); render_loop_mut.animation_id = if let Some(ref closure) = render_loop_mut.closure { Some( window() .request_animation_frame(closure.as_ref().unchecked_ref()) .expect("req anim frame"), ) } else { None } } })) }; let mut render_loop_last = render_loop.borrow_mut(); render_loop_last.animation_id = Some( window() .request_animation_frame(closure.as_ref().unchecked_ref()) .expect("req anim frame"), ); render_loop_last.closure = Some(closure); } // // // let a = Closure::::new(move || { let mut p = p1.lock().unwrap(); debug!("go clicked: {}", *p); *p = !*p; let text = if *p { "go" } else { let render_loop_clone = render_loop.clone(); let mut render_loop_mut = render_loop_clone.borrow_mut(); render_loop_mut.animation_id = if let Some(ref closure) = render_loop_mut.closure { Some( window() .request_animation_frame(closure.as_ref().unchecked_ref()) .expect("req anim frame"), ) } else { None }; "pause" }; go().expect("go button works").set_text_content(Some(text)); }); go()?.set_onclick(Some(a.as_ref().unchecked_ref())); // otherwise it gets dropped after we're done, invalidating the // handler. a.forget(); Ok(()) }