diff --git a/Cargo.lock b/Cargo.lock index 1187ae00..745649f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,6 +379,7 @@ dependencies = [ "emigui 0.1.0", "emigui_wasm 0.1.0", "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/docs/index.html b/docs/index.html index f886b101..b540c829 100644 --- a/docs/index.html +++ b/docs/index.html @@ -55,11 +55,19 @@ // ---------------------------------------------------------------------------- var g_wasm_app = null; - function paint_gui(canvas, input) { + function paint_gui(canvas) { if (g_wasm_app === null) { g_wasm_app = wasm_bindgen.new_webgl_gui("canvas", pixels_per_point()); } + let input = { + emigui: get_emigui_input(canvas), + web: { + location: window.location.toString(), + location_hash: window.location.hash.toString(), // i.e. #fragment + }, + } + let output = JSON.parse(wasm_bindgen.run_gui(g_wasm_app, JSON.stringify(input))); // console.log(`output: ${JSON.stringify(output)}`); document.body.style.cursor = from_emigui_cursor(output.cursor_icon); @@ -103,7 +111,7 @@ canvas.height = window.innerHeight * pixels_per_point(); } - function get_input(canvas) { + function get_emigui_input(canvas) { var input = { mouse_down: g_mouse_down, mouse_pos: g_mouse_pos, @@ -113,11 +121,6 @@ time: window.performance.now() / 1000.0, seconds_since_midnight: seconds_since_midnight(), events: g_events, - - web: { - location: window.location.toString(), - location_hash: window.location.hash.toString(), // i.e. #fragment - }, }; g_scroll_delta_x = 0; g_scroll_delta_y = 0; @@ -146,7 +149,7 @@ function paint() { var canvas = document.getElementById("canvas"); auto_resize_canvas(canvas); - paint_gui(canvas, get_input(canvas)); + paint_gui(canvas); } function paint_and_schedule() { diff --git a/emigui/benches/benchmark.rs b/emigui/benches/benchmark.rs index 124d656b..02b87791 100644 --- a/emigui/benches/benchmark.rs +++ b/emigui/benches/benchmark.rs @@ -13,7 +13,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { b.iter(|| { ctx.begin_frame(raw_input.clone()); let mut ui = ctx.fullscreen_ui(); - example_app.ui(&mut ui); + example_app.ui(&mut ui, ""); ctx.end_frame() }) }); diff --git a/emigui/src/examples/app.rs b/emigui/src/examples/app.rs index e1101e80..691057a3 100644 --- a/emigui/src/examples/app.rs +++ b/emigui/src/examples/app.rs @@ -10,6 +10,8 @@ use crate::{color::*, containers::*, examples::FractalClock, widgets::*, *}; #[derive(Default, Deserialize, Serialize)] #[serde(default)] pub struct ExampleApp { + previous_web_location_hash: String, + open_windows: OpenWindows, // TODO: group the following together as ExampleWindows example_window: ExampleWindow, @@ -17,7 +19,20 @@ pub struct ExampleApp { } impl ExampleApp { - pub fn ui(&mut self, ui: &mut Ui) { + /// `web_location_hash`: for web demo only. e.g. "#fragmet". + pub fn ui(&mut self, ui: &mut Ui, web_location_hash: &str) { + if self.previous_web_location_hash != web_location_hash { + // #fragment end of URL: + if web_location_hash == "#clock" { + self.open_windows = OpenWindows { + fractal_clock: true, + ..OpenWindows::none() + }; + } + + self.previous_web_location_hash = web_location_hash.to_owned(); + } + show_menu_bar(ui, &mut self.open_windows); self.windows(ui.ctx()); } @@ -31,24 +46,9 @@ impl ExampleApp { open_windows, example_window, fractal_clock, + .. } = self; - if ctx.previus_input().web != ctx.input().web { - let location_hash = ctx - .input() - .web - .as_ref() - .map(|web| web.location_hash.as_str()); - - // #fragment end of URL: - if location_hash == Some("#clock") { - *open_windows = OpenWindows { - fractal_clock: true, - ..OpenWindows::none() - }; - } - } - Window::new("Examples") .open(&mut open_windows.examples) .default_pos(pos2(32.0, 100.0)) diff --git a/emigui/src/input.rs b/emigui/src/input.rs index d9ab8470..def9b0ff 100644 --- a/emigui/src/input.rs +++ b/emigui/src/input.rs @@ -31,9 +31,6 @@ pub struct RawInput { /// In-order events received this frame pub events: Vec, - - /// Web-only input - pub web: Option, } /// What emigui maintains @@ -61,9 +58,6 @@ pub struct GuiInput { /// In-order events received this frame pub events: Vec, - - /// Web-only input - pub web: Option, } /// What emigui maintains @@ -91,14 +85,6 @@ pub struct MouseInput { pub velocity: Vec2, } -#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)] -#[serde(default)] -pub struct Web { - pub location: String, - /// i.e. "#fragment" - pub location_hash: String, -} - #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Event { @@ -149,27 +135,32 @@ impl GuiInput { dt, seconds_since_midnight: new.seconds_since_midnight, events: new.events.clone(), - web: new.web.clone(), } } } impl MouseInput { - pub fn from_last_and_new(last: &RawInput, new: &RawInput) -> MouseInput { + pub fn from_last_and_new(last: &GuiInput, new: &RawInput) -> MouseInput { let delta = new .mouse_pos - .and_then(|new| last.mouse_pos.map(|last| new - last)) + .and_then(|new| last.mouse.pos.map(|last| new - last)) .unwrap_or_default(); let dt = (new.time - last.time) as f32; let mut velocity = delta / dt; if !velocity.is_finite() { velocity = Vec2::zero(); } + let pressed = !last.mouse.down && new.mouse_down; + let mut press_origin = last.mouse.press_origin; + if pressed { + press_origin = new.mouse_pos; + } MouseInput { down: new.mouse_down && new.mouse_pos.is_some(), - pressed: !last.mouse_down && new.mouse_down, - released: last.mouse_down && !new.mouse_down, + pressed, + released: last.mouse.down && !new.mouse_down, pos: new.mouse_pos, + press_origin, delta, velocity, } @@ -188,9 +179,6 @@ impl RawInput { ui.add(label!("pixels_per_point: {:?}", self.pixels_per_point)); ui.add(label!("time: {:.3} s", self.time)); ui.add(label!("events: {:?}", self.events)); - if let Some(web) = &self.web { - web.ui(ui); - } } } @@ -207,9 +195,6 @@ impl GuiInput { ui.add(label!("pixels_per_point: {}", self.pixels_per_point)); ui.add(label!("time: {:.3} s", self.time)); ui.add(label!("events: {:?}", self.events)); - if let Some(web) = &self.web { - web.ui(ui); - } } } @@ -228,11 +213,3 @@ impl MouseInput { )); } } - -impl Web { - pub fn ui(&self, ui: &mut crate::Ui) { - use crate::label; - ui.add(label!("location: '{}'", self.location)); - ui.add(label!("location_hash: '{}'", self.location_hash)); - } -} diff --git a/example_glium/src/main.rs b/example_glium/src/main.rs index b5996c8f..925e0894 100644 --- a/example_glium/src/main.rs +++ b/example_glium/src/main.rs @@ -109,7 +109,7 @@ fn main() { let emigui_start = Instant::now(); ctx.begin_frame(raw_input.clone()); // TODO: avoid clone let mut ui = ctx.fullscreen_ui(); - example_app.ui(&mut ui); + example_app.ui(&mut ui, ""); let mut ui = ui.centered_column(ui.available().width().min(480.0)); ui.set_layout(Layout::vertical(Align::Min)); ui.add(label!("Emigui running inside of Glium").text_style(TextStyle::Heading)); diff --git a/example_wasm/Cargo.toml b/example_wasm/Cargo.toml index 5ef361cd..6bfc554f 100644 --- a/example_wasm/Cargo.toml +++ b/example_wasm/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] serde = "1" +serde_derive = "1" serde_json = "1" wasm-bindgen = "0.2" diff --git a/example_wasm/src/lib.rs b/example_wasm/src/lib.rs index dc086358..9069f7f4 100644 --- a/example_wasm/src/lib.rs +++ b/example_wasm/src/lib.rs @@ -13,6 +13,21 @@ use { use wasm_bindgen::prelude::*; +#[derive(Clone, Debug, Default, serde_derive::Deserialize)] +#[serde(default)] +struct WebInput { + emigui: RawInput, + web: Web, +} + +#[derive(Clone, Debug, Default, serde_derive::Deserialize)] +#[serde(default)] +pub struct Web { + pub location: String, + /// i.e. "#fragment" + pub location_hash: String, +} + #[wasm_bindgen] pub struct State { example_app: ExampleApp, @@ -34,13 +49,13 @@ impl State { }) } - fn run(&mut self, raw_input: RawInput) -> Result { + fn run(&mut self, web_input: WebInput) -> Result { let everything_start = now_sec(); - self.ctx.begin_frame(raw_input); + self.ctx.begin_frame(web_input.emigui); let mut ui = self.ctx.fullscreen_ui(); - self.example_app.ui(&mut ui); + self.example_app.ui(&mut ui, &web_input.web.location_hash); let mut ui = ui.centered_column(ui.available().width().min(480.0)); ui.set_layout(Layout::vertical(Align::Min)); ui.add(label!("Emigui!").text_style(TextStyle::Heading)); @@ -101,9 +116,9 @@ pub fn new_webgl_gui(canvas_id: &str, pixels_per_point: f32) -> Result Result { +pub fn run_gui(state: &mut State, web_input_json: &str) -> Result { // TODO: nicer interface than JSON - let raw_input: RawInput = serde_json::from_str(raw_input_json).unwrap(); - let output = state.run(raw_input)?; + let web_input: WebInput = serde_json::from_str(web_input_json).unwrap(); + let output = state.run(web_input)?; Ok(serde_json::to_string(&output).unwrap()) }