diff --git a/editor-solidjs/src/Properties.jsx b/editor-solidjs/src/Properties.jsx index b8afdd5..d072112 100644 --- a/editor-solidjs/src/Properties.jsx +++ b/editor-solidjs/src/Properties.jsx @@ -35,11 +35,18 @@ export default function RightPane(props) { setWorld((world) => { let [x, y] = settings.selected; let full_tile = world.get(x, y); + let had_signal = !!full_tile.signal; + if (typeof new_signal === "function") { full_tile.signal = new_signal(full_tile.signal); } else { full_tile.signal = new_signal; } + + if (full_tile.signal && !had_signal) { + full_tile.state = "Active"; + } + world.set(x, y, full_tile); return world; }); diff --git a/editor-solidjs/src/Signal.jsx b/editor-solidjs/src/Signal.jsx index f74d569..bd0c3d4 100644 --- a/editor-solidjs/src/Signal.jsx +++ b/editor-solidjs/src/Signal.jsx @@ -5,7 +5,7 @@ import Value from "./input/Value.jsx"; import styles from "./RightPane.module.css"; import input_styles from "./input/input.module.css"; - +import * as stackline from "../stackline-wasm/stackline_wasm.js"; export const DIRECTIONS = [ "Up", @@ -17,7 +17,21 @@ export const DIRECTIONS = [ export default function Signal(props) { let {signal, setSignal} = props; - return (No signal}> + return ( + No signal{" "} + + + + }>

Direction:

diff --git a/editor-solidjs/src/Tile.jsx b/editor-solidjs/src/Tile.jsx index cba1619..574f88d 100644 --- a/editor-solidjs/src/Tile.jsx +++ b/editor-solidjs/src/Tile.jsx @@ -8,6 +8,7 @@ import Orientation from "./input/Orientation.jsx"; import Number from "./input/Number.jsx"; import Value from "./input/Value.jsx"; import Bool from "./input/Bool.jsx"; +import String from "./input/String.jsx"; import CmpOp from "./input/CmpOp.jsx"; import ArithOp from "./input/ArithOp.jsx"; @@ -22,6 +23,8 @@ COMPONENTS.set("Int", Number); COMPONENTS.set("Value", Value); COMPONENTS.set("CmpOp", CmpOp); COMPONENTS.set("ArithOp", ArithOp); +COMPONENTS.set("Bool", Bool); +COMPONENTS.set("String", String); export default function Tile(props) { let {full_tile, set_full_tile} = props; diff --git a/font/StacklineClassic-Medium.otf b/font/StacklineClassic-Medium.otf index 629de70..5c9cff9 100644 Binary files a/font/StacklineClassic-Medium.otf and b/font/StacklineClassic-Medium.otf differ diff --git a/stackline-wasm/src/lib.rs b/stackline-wasm/src/lib.rs index cd7807d..3d9c365 100644 --- a/stackline-wasm/src/lib.rs +++ b/stackline-wasm/src/lib.rs @@ -13,17 +13,17 @@ use stackline::utils::Direction; use stackline::world::World as SLWorld; use stackline::text::TextSurface; +// TODO: refactor: +// - make everything camelCase +// - clearly separate serialized properties/functions from non-serialized +// - add javascript code to the classes? + // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. #[cfg(feature = "wee_alloc")] #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; -#[wasm_bindgen] -extern "C" { - fn alert(s: &str); -} - #[wasm_bindgen] pub struct World(SLWorld); @@ -459,6 +459,12 @@ impl Signal { } } + pub fn serialize(&self) -> JsValue { + JsValue::from_serde(&self.0).map_err(|err| { + err!("Error while serializing Signal: {:?}", err); + }).unwrap_or(JsValue::NULL) + } + pub fn push(&mut self, value: JsValue) { if let Some(num) = value.as_f64() { self.0.push(Value::Number(num)); diff --git a/stackline/src/text.rs b/stackline/src/text.rs index ce9ed7b..5f5c003 100644 --- a/stackline/src/text.rs +++ b/stackline/src/text.rs @@ -11,15 +11,14 @@ pub struct TextChar { impl TextChar { #[inline] - pub fn new(ch: char, fg: C1, bg: Option) -> Self + pub fn new(ch: char, fg: C, bg: Option) -> Self where - Srgb: FromColor, - Srgb: FromColor, + Srgb: From, { Self { ch, - fg: Srgb::from_color(fg), - bg: bg.map(|x| Srgb::from_color(x)), + fg: Srgb::from(fg), + bg: bg.map(|x| Srgb::from(x)), } } diff --git a/stackline/tiles/arithmetic.rs b/stackline/tiles/arithmetic.rs index 5977298..9db0a1d 100644 --- a/stackline/tiles/arithmetic.rs +++ b/stackline/tiles/arithmetic.rs @@ -17,7 +17,7 @@ macro_rules! binary_op { } if let Some(coords) = context.offset(signal.direction().into_offset()) { - context.send(coords, signal.direction(), signal).unwrap_or_else(|_| unreachable!()); + let _ = context.send(coords, signal.direction(), signal); } } diff --git a/stackline/tiles/storage.rs b/stackline/tiles/storage.rs index 0a0e5de..1d084fb 100644 --- a/stackline/tiles/storage.rs +++ b/stackline/tiles/storage.rs @@ -145,10 +145,10 @@ impl Tile for StorageCount { if let Some(target_position) = context.offset(signal.direction().into_offset()) { let _ = context.send(target_position, signal.direction(), signal); } + } - if context.state() != State::Idle { - context.next_state(); - } + if context.state() != State::Idle { + context.next_state(); } } @@ -231,6 +231,56 @@ impl Tile for Stacker { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Debug { + value: Value, +} + +impl Default for Debug { + fn default() -> Self { + Self { + value: Value::Number(0.0) + } + } +} + +impl Tile for Debug { + fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) { + if let Some(mut signal) = context.take_signal() { + if let Some(value) = signal.pop() { + self.value = value; + } + } + + if context.state() != State::Idle { + context.next_state(); + } + } + + fn draw(&self, surface: &mut TextSurface, ctx: DrawContext<'_>) { + use palette::Srgb; + let text = format!("\"{}", self.value); + + let y = ctx.surface_coords.1; + for (index, c) in text.chars().enumerate() { + let x = ctx.surface_coords.0 + index as i32; + if let (Ok(x), Ok(y)) = (x.try_into(), y.try_into()) { + let textchar = if index == 0 { + TextChar::from_state(c, ctx.state) + } else { + TextChar::new(c, Srgb::new(100, 100, 100), None) + }; + surface.set(x, y, textchar); + } + } + } + + fn schema(&self) -> TileSchema { + TileSchema::map() + .add("value", TileSchema::value("Stored value", "Value")) + } +} + /// Tries to convert a [`FullTile`] to a [`Store`] fn get_store<'a>(full: VecRef<'a, FullTile>) -> Option> { VecRef::try_map(full, |tile| { diff --git a/stackline/tiles/wire.rs b/stackline/tiles/wire.rs index 50d643b..6e590ff 100644 --- a/stackline/tiles/wire.rs +++ b/stackline/tiles/wire.rs @@ -151,6 +151,63 @@ impl Tile for Resistor { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Fuse { + blown: bool, + orientation: Orientation, +} + +impl Default for Fuse { + fn default() -> Self { + Self { + blown: false, + orientation: Orientation::Horizontal, + } + } +} + +impl Tile for Fuse { + fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) { + if let Some(signal) = context.take_signal() { + if self.orientation.contains(signal.direction()) { + if !self.blown { + self.blown = true; + if let Some(pos) = context.offset(signal.direction().into_offset()) { + let _ = context.send(pos, signal.direction(), signal); + } + } else { + context.set_state(State::Idle); + } + } else { + self.blown = false; + context.set_state(State::Idle); + } + } + + if context.state() != State::Idle { + context.next_state(); + } + } + + fn draw_simple(&self, ctx: DrawContext) -> TextChar { + let ch = match (self.blown, self.orientation) { + (true, Orientation::Vertical) => '\u{254e}', // Light double dash vertical + (true, Orientation::Horizontal) => '\u{254c}', // Light double dash horizontal + (false, Orientation::Vertical) => '\u{2506}', // Light triple dash vertical + (false, Orientation::Horizontal) => '\u{2504}', // Light triple dash horizontal + _ => ' ', + }; + + TextChar::from_state(ch, ctx.state) + } + + fn schema(&self) -> TileSchema { + TileSchema::map() + .add("blown", TileSchema::value("Is blown", "Bool")) + .add("orientation", TileSchema::value("Orientation", "Orientation|NotAny")) + } +} + #[cfg(test)] mod test { use super::*;