From 0d3e4f7d15812371f9f4f7a297bc113b6795130a Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Tue, 16 Aug 2022 14:48:16 +0200 Subject: [PATCH] :sparkles: More WASM bindgen glue, World::draw() --- stackline-wasm/src/lib.rs | 103 +++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/stackline-wasm/src/lib.rs b/stackline-wasm/src/lib.rs index 6ea76cf..dde08e5 100644 --- a/stackline-wasm/src/lib.rs +++ b/stackline-wasm/src/lib.rs @@ -1,8 +1,8 @@ mod utils; +use js_sys::Function; use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; -use js_sys::Function; use stackline::pane::Pane as SLPane; use stackline::signal::Signal as SLSignal; @@ -11,6 +11,7 @@ use stackline::tile::AnyTile; use stackline::tile::FullTile as SLFullTile; use stackline::utils::Direction; use stackline::world::World as SLWorld; +use stackline::text::TextSurface; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. @@ -33,9 +34,10 @@ pub fn set_panic() { #[wasm_bindgen] pub fn available_tiles() -> Vec { - AnyTile::available().iter().map(|name| { - JsValue::from_str(name) - }).collect() + AnyTile::available() + .iter() + .map(|name| JsValue::from_str(name)) + .collect() } #[wasm_bindgen] @@ -66,9 +68,11 @@ impl World { self.0.get((x, y)).map(|tile| FullTile((*tile).clone())) } - pub fn set(&mut self, x: i32, y: i32, tile: &FullTile) { + pub fn set(&mut self, x: i32, y: i32, tile: FullTile) { if let Some(tile_ref) = self.0.get_mut((x, y)) { - *tile_ref = tile.0.clone(); + *tile_ref = tile.0; + } else if cfg!(debug_assertions) { + err!("Index out of bound: {}:{}", x, y); } } @@ -79,6 +83,37 @@ impl World { pub fn set_pane(&mut self, name: String, pane: Pane) { self.0.set_pane(name, pane.0); } + + pub fn panes(&self) -> Vec { + self.0.panes().keys().map(|key| { + JsValue::from_str(key) + }).collect() + } + + pub fn draw(&self, x: i32, y: i32, width: usize, height: usize) -> Vec { + let mut surface = TextSurface::new(width, height); + + self.0.draw(x, y, &mut surface); + + #[derive(Serialize)] + struct Char { + ch: char, + fg: (u8, u8, u8), + bg: Option<(u8, u8, u8)>, + } + + fn to_u32(red: u8, green: u8, blue: u8) -> u32 { + 0xff000000 | (red as u32).checked_shl(16).unwrap() | (green as u32).checked_shl(8).unwrap() | (blue as u32) + } + + surface.iter().map(|ch| { + vec![ + ch.ch as u32, + to_u32(ch.fg.red, ch.fg.green, ch.fg.blue), + ch.bg.map(|bg| to_u32(bg.red, bg.green, bg.blue)).unwrap_or(0) + ].into_iter() + }).flatten().collect::>() + } } #[wasm_bindgen] @@ -111,6 +146,16 @@ impl Pane { vec![x, y] } + #[wasm_bindgen(getter)] + pub fn x(&self) -> i32 { + self.0.position().0 + } + + #[wasm_bindgen(getter)] + pub fn y(&self) -> i32 { + self.0.position().1 + } + #[wasm_bindgen(setter)] pub fn set_position(&mut self, position: &[i32]) { if let [x, y] = position[..] { @@ -151,11 +196,17 @@ impl FullTile { #[wasm_bindgen(getter)] pub fn tile(&self) -> JsValue { - self.0.get().map(|tile| { - JsValue::from_serde(tile).map_err(|err| { - err!("Error while serializing AnyTile: {}", err); - }).ok() - }).flatten().unwrap_or(JsValue::UNDEFINED) + self.0 + .get() + .map(|tile| { + JsValue::from_serde(tile) + .map_err(|err| { + err!("Error while serializing AnyTile: {}", err); + }) + .ok() + }) + .flatten() + .unwrap_or(JsValue::UNDEFINED) } #[wasm_bindgen(setter)] @@ -170,8 +221,36 @@ impl FullTile { } } + pub fn schema(&self) -> JsValue { + use serde_json::Value; + use stackline::tile::{Tile, TileSchema}; + + fn construct_value(schema: TileSchema) -> Value { + match schema { + TileSchema::Tuple(arr) => { + Value::Array(arr.into_iter().map(construct_value).collect()) + } + TileSchema::Map(map) => Value::Object( + map.into_iter() + .map(|(key, value)| (key, construct_value(value))) + .collect(), + ), + TileSchema::Value(string) => Value::String(string), + } + } + + if let Some(tile) = self.0.get() { + JsValue::from_serde(&construct_value(tile.schema())) + .expect("Error while serializing TileSchema") + } else { + JsValue::UNDEFINED + } + } + pub fn map_tile(&mut self, callback: &Function) { - let res = callback.call1(&JsValue::NULL, &self.tile()).expect("Error while calling javascript callback"); + let res = callback + .call1(&JsValue::NULL, &self.tile()) + .expect("Error while calling javascript callback"); self.set_tile(res); } }