diff --git a/README.md b/README.md index 6d134d20..2f99f5a6 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,8 @@ This is similar to Dear ImGui but separates the layout from the rendering, and a Input is gathered in TypeScript. PaintCommands rendered to a HTML canvas. Everything else is written in Rust, compiled to WASM. + +# Test goal: + +Make an "any" editor. Store text files, make a VERY SIMPLE text editor, in the web. +Supports MARKDEEP. A place for you ideas. Stored on your computer (local storage). diff --git a/build.sh b/build.sh index 828efa0a..cb1d75c0 100755 --- a/build.sh +++ b/build.sh @@ -15,19 +15,23 @@ rm -rf docs/*.d.ts rm -rf docs/*.js rm -rf docs/*.wasm -echo "Build rust:" -cargo build --target wasm32-unknown-unknown +function build_rust +{ + echo "Build rust:" + cargo build --target wasm32-unknown-unknown -echo "Lint and clean up typescript:" -tslint --fix docs/*.ts + echo "Generate JS bindings for wasm:" + FOLDER_NAME=${PWD##*/} + TARGET_NAME="$FOLDER_NAME.wasm" + wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \ + --out-dir docs --no-modules + # --no-modules-global hoboho +} echo "Compile typescript:" +build_rust tsc -echo "Generate JS bindings for wasm:" +# wait || exit $? -FOLDER_NAME=${PWD##*/} -TARGET_NAME="$FOLDER_NAME.wasm" -wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \ - --out-dir docs --no-modules - # --no-modules-global hoboho +# 3.4 s diff --git a/docs/emgui_bg.wasm b/docs/emgui_bg.wasm index 980c22b2..3856f3f0 100644 Binary files a/docs/emgui_bg.wasm and b/docs/emgui_bg.wasm differ diff --git a/docs/index.html b/docs/index.html index 89e65903..13f8a303 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,7 +2,7 @@ - Gui Experiment + Emgui – A experiment in an Immediate Mode GUI written in Rust @@ -38,7 +38,7 @@ - + diff --git a/lint.sh b/lint.sh new file mode 100755 index 00000000..d6c8f3a4 --- /dev/null +++ b/lint.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -eu + +echo "Lint and clean up typescript:" +tslint --fix docs/*.ts diff --git a/src/lib.rs b/src/lib.rs index 84909ad7..00d3383f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,76 @@ mod types; use types::*; +/* + +// Fast compilation, slow code: +fn foo(x: &dyn Trait); + + +// Fast code, slow compilation: +fn foo(x: &dyn T); + + +// Compiles quickly in debug, fast in release: +#[dynimp(Trait)] +fn foo(x: &Trait); +*/ + +#[derive(Default)] +pub struct InteractInfo { + pub is_hovering: bool, +} + +// TODO: implement Gui on this so we can add children to a widget +// pub struct Widget {} + +pub struct Gui { + commands: Vec, + input: Input, +} + +impl Gui { + pub fn new(input: Input) -> Self { + Gui { + commands: vec![PaintCmd::Clear { + fill_style: "#44444400".to_string(), + }], + input, + } + } + + pub fn input(&self) -> &Input { + &self.input + } + + pub fn into_commands(self) -> Vec { + self.commands + } + + pub fn rect(&mut self, rect: Rect) -> InteractInfo { + let ii = InteractInfo { + is_hovering: rect.contains(&self.input.mouse_pos), + }; + self.commands.push(PaintCmd::RoundedRect { + fill_style: "#ffffff10".to_string(), + pos: rect.pos, + corner_radius: 40.0, + size: rect.size, + }); + ii + } + + pub fn text(&mut self, pos: Vec2, text: String) { + self.commands.push(PaintCmd::Text { + fill_style: "#11ff00".to_string(), + font: "14px Palatino".to_string(), + pos, + text, + text_align: TextAlign::Start, + }); + } +} + struct App { count: i32, } @@ -24,42 +94,55 @@ impl App { App { count: 0 } } - fn show_gui(&mut self, input: &Input) -> Vec { - let rect = Rect { - pos: Vec2 { x: 100.0, y: 100.0 }, - size: Vec2 { x: 200.0, y: 200.0 }, - }; + fn show_gui(&mut self, gui: &mut Gui, input: &Input) { + gui.rect(Rect { + pos: Vec2 { x: 0.0, y: 0.0 }, + size: input.screen_size, + }); - let is_hovering = rect.contains(&input.mouse_pos); + gui.rect(Rect { + pos: Vec2 { x: 50.0, y: 50.0 }, + size: Vec2 { + x: (input.screen_size.x - 100.0) / 3.0, + y: (input.screen_size.y - 100.0), + }, + }); - vec![ - PaintCmd::Clear { - fill_style: "#44444400".to_string(), + let is_hovering = gui + .rect(Rect { + pos: Vec2 { x: 100.0, y: 100.0 }, + size: Vec2 { x: 200.0, y: 200.0 }, + }).is_hovering; + + if is_hovering { + self.count += 1; + } + + gui.text( + Vec2 { x: 100.0, y: 350.0 }, + format!( + "Mouse pos: {} {}, is_hovering: {}", + input.mouse_pos.x, input.mouse_pos.y, is_hovering + ), + ); + + let m = input.mouse_pos; + let hw = 32.0; + gui.rect(Rect { + pos: Vec2 { + x: m.x - hw, + y: m.y - hw, }, - PaintCmd::Text { - fill_style: "#11ff00".to_string(), - font: "14px Palatino".to_string(), - pos: Vec2 { x: 200.0, y: 32.0 }, - text: format!( - "Mouse pos: {} {}, is_hovering: {}", - input.mouse_pos.x, input.mouse_pos.y, is_hovering - ), - text_align: TextAlign::Center, + size: Vec2 { + x: 2.0 * hw, + y: 2.0 * hw, }, - PaintCmd::Text { - fill_style: "#11ff00".to_string(), - font: "14px Palatino".to_string(), - pos: Vec2 { x: 200.0, y: 64.0 }, - text: format!("Count: {}", self.count), - text_align: TextAlign::Center, - }, - PaintCmd::RoundedRect { - fill_style: "#1111ff".to_string(), - pos: rect.pos, - corner_radius: 40.0, - size: rect.size, - }, - ] + }); + + gui.text( + Vec2 { x: 100.0, y: 400.0 }, + format!("Count: {}", self.count), + ); } } @@ -71,6 +154,9 @@ pub fn show_gui(input_json: &str) -> String { // TODO: faster interface than JSON let input: Input = serde_json::from_str(input_json).unwrap(); - let commands = APP.lock().unwrap().show_gui(&input); + + let mut gui = Gui::new(input); + APP.lock().unwrap().show_gui(&mut gui, &input); + let commands = gui.into_commands(); serde_json::to_string(&commands).unwrap() } diff --git a/src/types.rs b/src/types.rs index 498ca99b..c66535fb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,10 +1,10 @@ -#[derive(Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub struct Vec2 { pub x: f32, pub y: f32, } -#[derive(Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub struct Rect { pub pos: Vec2, pub size: Vec2, @@ -19,21 +19,21 @@ impl Rect { } } -#[derive(Deserialize)] +#[derive(Clone, Copy, Debug, Deserialize)] pub struct Input { pub screen_size: Vec2, pub mouse_pos: Vec2, } -#[derive(Serialize)] +#[derive(Clone, Copy, Debug, Serialize)] #[serde(rename_all = "snake_case")] pub enum TextAlign { - Start, + Start, // Test with arabic text Center, End, } -#[derive(Serialize)] +#[derive(Clone, Debug, Serialize)] // TODOcopy #[serde(rename_all = "snake_case", tag = "kind")] pub enum PaintCmd { Clear {