Run the simulation

main
Shad Amethyst 2 years ago
parent be94e01bad
commit c01ae784a8
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -19,25 +19,43 @@ await Promise.all(promises);
font = await font.loaded; font = await font.loaded;
document.fonts.add(font); document.fonts.add(font);
let world = World.new(); let world = World.deserialize(await (await fetch("/stackline/tests/other/prime.json")).json());
world.init();
// let world = World.new();
let cx = 0; let cx = 0;
let cy = 0; let cy = 0;
let zoom = 1; let zoom = 1;
let grid = true;
let pane = Pane.empty(5, 5); let click_x = 0, click_y = 0;
world.set_pane("main", pane); let mouse_x = 0, mouse_y = 0;
let mouse_down = false;
let hovered = false;
let selected = null;
let available = available_tiles(); let running = null;
console.log(available);
for (let n = 0; n < available.length; n++) { let tile = world.get(4, 0);
world.set( tile.signal = new Signal();
n % 5, tile.state = "Active";
~~(n / 5), world.set(4, 0, tile);
new FullTile(available[n])
); // let pane = Pane.empty(5, 5);
} // world.set_pane("main", pane);
// let available = available_tiles();
// console.log(available);
// for (let n = 0; n < available.length; n++) {
// world.set(
// n % 5,
// ~~(n / 5),
// new FullTile(available[n])
// );
// }
console.log(world.toString()); console.log(world.toString());
console.log(world.serialize());
resize(); resize();
window.addEventListener("resize", resize); window.addEventListener("resize", resize);
@ -49,14 +67,30 @@ function draw() {
ctx.fillStyle = "#202027"; ctx.fillStyle = "#202027";
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
function stroke_rect(x, y, width, height) {
ctx.lineWidth = zoom_factor;
ctx.strokeRect(
Math.round(x * tile_size + cx + canvas.width / 2) - zoom_factor * 1.5,
Math.round(y * tile_size + cy + canvas.height / 2) - zoom_factor * 1.5,
Math.round(width * tile_size) + zoom_factor * 2,
Math.round(height * tile_size) + zoom_factor * 2,
);
}
function fill_rect(x, y, width, height) {
ctx.fillRect(
Math.round(x * tile_size + cx + canvas.width / 2) - zoom_factor * 1,
Math.round(y * tile_size + cy + canvas.height / 2) - zoom_factor * 1,
Math.round(width * tile_size) + zoom_factor * 1,
Math.round(height * tile_size) + zoom_factor * 1,
);
}
let panes = []; let panes = [];
for (let name of world.panes()) { for (let name of world.panes()) {
let pane = world.get_pane(name); let pane = world.get_pane(name);
ctx.strokeStyle = "rgba(128, 128, 128, 0.5)";
ctx.lineWidth = zoom_factor;
panes.push({ panes.push({
x: pane.x, x: pane.x,
y: pane.y, y: pane.y,
@ -64,11 +98,12 @@ function draw() {
height: pane.height height: pane.height
}); });
ctx.strokeRect( ctx.strokeStyle = "rgba(128, 128, 128, 0.5)";
Math.round(pane.x * tile_size + cx + canvas.width / 2) - zoom_factor * 1.5, stroke_rect(
Math.round(pane.y * tile_size + cy + canvas.height / 2) - zoom_factor * 1.5, pane.x,
Math.round(pane.width * tile_size) + zoom_factor * 3, pane.y,
Math.round(pane.height * tile_size) + zoom_factor * 3, pane.width,
pane.height,
); );
pane.free(); pane.free();
@ -115,7 +150,7 @@ function draw() {
Math.round(x2), Math.round(x2),
Math.round(y2), Math.round(y2),
); );
} else { } else if (grid) {
// Draw grid // Draw grid
let inside = false; let inside = false;
@ -127,7 +162,7 @@ function draw() {
} }
if (inside || width < 100 && height < 100) { if (inside || width < 100 && height < 100) {
ctx.fillStyle = inside ? "#505050" : "#303030"; ctx.fillStyle = inside ? "#404040" : "#303030";
ctx.fillRect( ctx.fillRect(
Math.round(x2 + tile_size / 2) - zoom_factor, Math.round(x2 + tile_size / 2) - zoom_factor,
@ -139,6 +174,15 @@ function draw() {
} }
} }
} }
if (hovered) {
let [x, y] = get_hovered();
ctx.strokeStyle = "rgba(230, 255, 230, 0.2)";
ctx.fillStyle = "rgba(230, 255, 230, 0.07)";
stroke_rect(x, y, 1, 1);
fill_rect(x, y, 1, 1);
}
} }
function resize() { function resize() {
@ -153,40 +197,85 @@ function loop() {
window.requestAnimationFrame(loop); window.requestAnimationFrame(loop);
} }
let mouse_x = 0, mouse_y = 0;
let mouse_down = false;
canvas.addEventListener("mousedown", (evt) => { canvas.addEventListener("mousedown", (evt) => {
mouse_x = evt.clientX; click_x = mouse_x = evt.clientX;
mouse_y = evt.clientY; click_y = mouse_y = evt.clientY;
mouse_down = true; mouse_down = true;
}); });
canvas.addEventListener("mousemove", (evt) => { canvas.addEventListener("mousemove", (evt) => {
hovered = true;
if (mouse_down) { if (mouse_down) {
// TODO: numerically stable solution // TODO: numerically stable solution
cx += evt.clientX - mouse_x; cx += evt.clientX - mouse_x;
cy += evt.clientY - mouse_y; cy += evt.clientY - mouse_y;
}
mouse_x = evt.clientX; mouse_x = evt.clientX;
mouse_y = evt.clientY; mouse_y = evt.clientY;
}
}); });
canvas.addEventListener("mouseup", (evt) => { canvas.addEventListener("mouseup", (evt) => {
mouse_down = false; mouse_down = false;
let dist = Math.sqrt((mouse_x - click_x) ** 2 + (mouse_y - click_y) ** 2);
if (dist < 10) {
selected = get_hovered();
}
});
canvas.addEventListener("mouseenter", (evt) => {
hovered = true;
}); });
canvas.addEventListener("mouseleave", (evt) => { canvas.addEventListener("mouseleave", (evt) => {
mouse_down = false; mouse_down = false;
hovered = false;
}); });
canvas.addEventListener("wheel", (event) => { canvas.addEventListener("wheel", (event) => {
const ZOOM_STRENGTH = -0.005; const ZOOM_STRENGTH = -0.005;
let old_zoom = zoom;
zoom += event.deltaY * ZOOM_STRENGTH; zoom += event.deltaY * ZOOM_STRENGTH;
zoom = Math.min(Math.max(zoom, 0.0), 4.0); zoom = Math.min(Math.max(zoom, 0.0), 4.0);
let delta = Math.ceil(Math.pow(2, zoom)) / Math.ceil(Math.pow(2, old_zoom));
cx *= delta;
cy *= delta;
}); });
window.addEventListener("keydown", (event) => {
if (hovered) {
if (event.code === "Space") {
if (running !== null) {
clearInterval(running);
running = null;
} else if (event.shiftKey) {
world.init();
running = setInterval(() => {
world.step();
}, 100);
} else {
world.init();
world.step();
}
} else if (event.code === "KeyG") {
grid = !grid;
}
}
});
function get_hovered() {
let zoom_factor = Math.ceil(Math.pow(2, zoom));
let tile_size = 10 * zoom_factor;
let x = Math.floor((mouse_x - canvas.width / 2 - cx) / tile_size);
let y = Math.floor((mouse_y - canvas.height / 2 - cy) / tile_size);
return [x, y];
}
function to_color(num) { function to_color(num) {
let alpha = (num >> 24) & 0xff; let alpha = (num >> 24) & 0xff;
let red = (num >> 16) & 0xff; let red = (num >> 16) & 0xff;

@ -47,11 +47,34 @@ impl World {
Self(SLWorld::new()) Self(SLWorld::new())
} }
pub fn deserialize(serialized: &JsValue) -> Option<World> {
serialized.into_serde().map_err(|err| {
err!("Error while deserializing World: {:?}", err);
}).ok().map(|world| World(world))
}
pub fn serialize(&self) -> JsValue {
JsValue::from_serde(&self.0).map_err(|err| {
err!("Error while serializing World: {:?}", err);
}).unwrap_or(JsValue::NULL)
}
/// Initializes the World, making it ready to run /// Initializes the World, making it ready to run
pub fn init(&mut self) { pub fn init(&mut self) {
self.0.init(); self.0.init();
} }
#[inline]
pub fn step(&mut self) {
self.0.step();
}
pub fn run(&mut self, steps: usize) {
for _ in 0..steps {
self.step();
}
}
pub fn set_blink_duration(&mut self, blink_duration: f64) { pub fn set_blink_duration(&mut self, blink_duration: f64) {
use std::time::Duration; use std::time::Duration;
self.0 self.0
@ -221,6 +244,18 @@ impl FullTile {
} }
} }
#[wasm_bindgen(getter)]
pub fn state(&self) -> JsValue {
JsValue::from_serde(&self.0.state()).expect("Error while serializing State")
}
#[wasm_bindgen(setter)]
pub fn set_state(&mut self, state: &JsValue) {
if let Ok(state) = state.into_serde() {
self.0.set_state(state);
}
}
pub fn schema(&self) -> JsValue { pub fn schema(&self) -> JsValue {
use serde_json::Value; use serde_json::Value;
use stackline::tile::{Tile, TileSchema}; use stackline::tile::{Tile, TileSchema};

Loading…
Cancel
Save