aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrian cully <bjc@spork.org>2025-12-27 16:53:11 -0500
committerbrian cully <bjc@spork.org>2025-12-27 16:53:11 -0500
commitfdc957cae7f5efca792b40df7ff90ec4f512269b (patch)
treec66b53403d31b152cce22b7c68559b3d78f1bb07
parent4a8f968b6cf8e7e3fc3cee72cc8b552a8ceec047 (diff)
downloadpolyring-fdc957cae7f5efca792b40df7ff90ec4f512269b.tar.gz
polyring-fdc957cae7f5efca792b40df7ff90ec4f512269b.zip
get wasm go button working
-rw-r--r--src/lib.rs76
-rw-r--r--src/state.rs31
2 files changed, 71 insertions, 36 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f43b2ad..1c5f028 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,8 @@
use std::cell::RefCell;
+use std::sync::{Mutex};
use std::rc::Rc;
-use log::{Level, info};
+use log::{Level, info, debug};
use wasm_bindgen::prelude::*;
use state::State;
@@ -28,12 +29,40 @@ fn window() -> web_sys::Window {
web_sys::window().expect("no window")
}
+fn document() -> web_sys::Document {
+ window().document().expect("no document")
+}
+
+fn canvas() -> Result<web_sys::HtmlCanvasElement, JsValue> {
+ let x = document()
+ .query_selector("canvas")?
+ .expect("canvas element");
+ Ok(x.dyn_into::<web_sys::HtmlCanvasElement>()?)
+}
+
+fn fps() -> Result<web_sys::HtmlElement, JsValue> {
+ let x = document()
+ .query_selector("#fps")?
+ .expect("fps counter exists");
+ Ok(x.dyn_into::<web_sys::HtmlElement>()?)
+}
+
+fn go() -> Result<web_sys::HtmlElement, JsValue> {
+ let x = document()
+ .query_selector("button")?
+ .expect("go button exists");
+ Ok(x.dyn_into::<web_sys::HtmlElement>()?)
+}
+
#[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 mut s = State::new()?;
+ let paused = Rc::new(Mutex::new(true));
+ let p1 = paused.clone();
+
+ let mut s = State::new(canvas()?, fps()?)?;
s.render_frame(0.0)?;
//
@@ -43,12 +72,13 @@ pub fn init() -> Result<(), JsValue> {
let render_loop: Rc<RefCell<RenderLoop>> = Rc::new(RefCell::new(RenderLoop::new()));
{
let closure: Closure<dyn FnMut(f64)> = {
- let render_loop = render_loop.clone();
+ let render_loop_clone = render_loop.clone();
Closure::wrap(Box::new(move |t| {
s.render_frame(t).expect("should render frame");
- if !s.paused {
- let mut render_loop = render_loop.borrow_mut();
- render_loop.animation_id = if let Some(ref closure) = render_loop.closure {
+ 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())
@@ -60,18 +90,46 @@ pub fn init() -> Result<(), JsValue> {
}
}))
};
- let mut render_loop = render_loop.borrow_mut();
- render_loop.animation_id = Some(
+
+ 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.closure = Some(closure);
+ render_loop_last.closure = Some(closure);
}
//
//
//
+ let a = Closure::<dyn FnMut()>::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(())
}
diff --git a/src/state.rs b/src/state.rs
index 4adb952..f5435f5 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -10,49 +10,27 @@ use crate::point::Point;
pub const TAU: f64 = PI * 2.0;
pub const MAX_SPEED: f64 = 0.01;
-const NUM_POINTS: usize = 40;
+const NUM_POINTS: usize = 10;
const VELVEC_SCALE: f64 = 3.0;
-fn window() -> web_sys::Window {
- web_sys::window().expect("no window")
-}
-
-fn document() -> web_sys::Document {
- window().document().expect("no document")
-}
-
-fn canvas() -> Result<web_sys::HtmlCanvasElement, JsValue> {
- let x = document()
- .query_selector("canvas")?
- .expect("canvas element");
- Ok(x.dyn_into::<web_sys::HtmlCanvasElement>()?)
-}
-
#[derive(Debug)]
pub struct State {
canvas: HtmlCanvasElement,
ctx: CanvasRenderingContext2d,
fps: HtmlElement,
points: Vec<Point>,
- pub paused: bool,
last_time: Option<f64>,
inter_count: u16,
}
impl State {
- pub fn new() -> Result<Self, JsValue> {
+ pub fn new(canvas: HtmlCanvasElement, fps: HtmlElement) -> Result<Self, JsValue> {
debug!("State::new()");
- let canvas = canvas()?;
let ctx: CanvasRenderingContext2d = canvas
.get_context("2d")?
.expect("2d context on canvas")
.dyn_into()?;
ctx.scale(canvas.width().into(), canvas.height().into())?;
- let fps = document()
- .query_selector("#fps")?
- .expect("fps counter exists")
- .dyn_into::<HtmlElement>()
- .expect("is html element");
let points = (0..NUM_POINTS)
.map(|_| Point::new(fastrand::f64(), fastrand::f64()))
@@ -63,8 +41,7 @@ impl State {
ctx,
fps,
points,
- paused: false,
- last_time: document().timeline().current_time(),
+ last_time: None,
inter_count: 1,
})
}
@@ -75,12 +52,12 @@ impl State {
let ic: f64 = self.inter_count.into();
let val: f64 = (1_000.0 * ic / (t - last_time)).trunc();
self.fps.set_text_content(Some(val.to_string().as_str()));
- self.last_time = Some(t);
self.inter_count = 1;
} else {
self.inter_count += 1;
}
}
+ self.last_time = Some(t);
self.ctx.clear_rect(
0.0,