|
|
|
@ -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<JsValue> {
|
|
|
|
|
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<JsValue> {
|
|
|
|
|
self.0.panes().keys().map(|key| {
|
|
|
|
|
JsValue::from_str(key)
|
|
|
|
|
}).collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn draw(&self, x: i32, y: i32, width: usize, height: usize) -> Vec<u32> {
|
|
|
|
|
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::<Vec<_>>()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|