Split example app from emigui_wasm
This commit is contained in:
parent
7dcda029ec
commit
1beed16053
11 changed files with 223 additions and 124 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -107,6 +107,19 @@ dependencies = [
|
|||
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"emigui 0.1.0",
|
||||
"emigui_wasm 0.1.0",
|
||||
"js-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasm-bindgen 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"web-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.5"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
members = [
|
||||
"emigui",
|
||||
"emigui_wasm",
|
||||
"example",
|
||||
]
|
||||
|
||||
# Optimize for small code size:
|
||||
|
|
2
build.sh
2
build.sh
|
@ -22,7 +22,7 @@ function build_rust
|
|||
|
||||
echo "Generate JS bindings for wasm:"
|
||||
FOLDER_NAME=${PWD##*/}
|
||||
TARGET_NAME="emigui_wasm.wasm"
|
||||
TARGET_NAME="example.wasm"
|
||||
wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \
|
||||
--out-dir docs --no-modules --no-typescript
|
||||
# --no-modules-global hoboho
|
||||
|
|
Binary file not shown.
|
@ -331,20 +331,20 @@ __exports.__widl_f_performance_Window = function(arg0) {
|
|||
|
||||
};
|
||||
|
||||
__exports.__wbg_new_12b9ae8fdb332911 = function(arg0) {
|
||||
__exports.__wbg_new_f49b071a6847bcff = function(arg0) {
|
||||
return addHeapObject(new Float32Array(getObject(arg0)));
|
||||
};
|
||||
|
||||
__exports.__wbg_subarray_1c02edccacdc6b96 = function(arg0, arg1, arg2) {
|
||||
__exports.__wbg_subarray_f8934b42fec7ca7c = function(arg0, arg1, arg2) {
|
||||
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||
};
|
||||
|
||||
__exports.__wbg_newnoargs_970ffcd96c15d34e = function(arg0, arg1) {
|
||||
__exports.__wbg_newnoargs_43c5f57b77232284 = function(arg0, arg1) {
|
||||
let varg0 = getStringFromWasm(arg0, arg1);
|
||||
return addHeapObject(new Function(varg0));
|
||||
};
|
||||
|
||||
__exports.__wbg_call_6ecd167e59b01396 = function(arg0, arg1, exnptr) {
|
||||
__exports.__wbg_call_7ac13208e630ddeb = function(arg0, arg1, exnptr) {
|
||||
try {
|
||||
return addHeapObject(getObject(arg0).call(getObject(arg1)));
|
||||
} catch (e) {
|
||||
|
@ -355,35 +355,35 @@ __exports.__wbg_call_6ecd167e59b01396 = function(arg0, arg1, exnptr) {
|
|||
}
|
||||
};
|
||||
|
||||
__exports.__wbg_new_24372bdd16e7ac17 = function(arg0) {
|
||||
__exports.__wbg_new_efed94c530925533 = function(arg0) {
|
||||
return addHeapObject(new Int16Array(getObject(arg0)));
|
||||
};
|
||||
|
||||
__exports.__wbg_subarray_333aec38f24ecc8c = function(arg0, arg1, arg2) {
|
||||
__exports.__wbg_subarray_b6e319a511351c70 = function(arg0, arg1, arg2) {
|
||||
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||
};
|
||||
|
||||
__exports.__wbg_new_4e991c7c717b13c1 = function(arg0) {
|
||||
__exports.__wbg_new_a999fd72f5304154 = function(arg0) {
|
||||
return addHeapObject(new Uint8Array(getObject(arg0)));
|
||||
};
|
||||
|
||||
__exports.__wbg_subarray_0de502469162fe71 = function(arg0, arg1, arg2) {
|
||||
__exports.__wbg_subarray_1cd21da1682e7d1e = function(arg0, arg1, arg2) {
|
||||
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||
};
|
||||
|
||||
__exports.__wbg_new_ebb3136fdb1b1152 = function(arg0) {
|
||||
__exports.__wbg_new_12076896685e5e56 = function(arg0) {
|
||||
return addHeapObject(new Uint16Array(getObject(arg0)));
|
||||
};
|
||||
|
||||
__exports.__wbg_subarray_acb28098200224ff = function(arg0, arg1, arg2) {
|
||||
__exports.__wbg_subarray_a860cdd7b04efc31 = function(arg0, arg1, arg2) {
|
||||
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||
};
|
||||
|
||||
__exports.__wbg_instanceof_Memory_48643a8591466d1a = function(idx) {
|
||||
__exports.__wbg_instanceof_Memory_ed5a1f7b9a0e05a3 = function(idx) {
|
||||
return getObject(idx) instanceof WebAssembly.Memory ? 1 : 0;
|
||||
};
|
||||
|
||||
__exports.__wbg_buffer_74e21c76ddf2eb17 = function(arg0) {
|
||||
__exports.__wbg_buffer_efdca35786c3eb75 = function(arg0) {
|
||||
return addHeapObject(getObject(arg0).buffer);
|
||||
};
|
||||
|
||||
|
@ -403,21 +403,6 @@ __exports.__wbindgen_string_new = function(p, l) {
|
|||
return addHeapObject(getStringFromWasm(p, l));
|
||||
};
|
||||
|
||||
__exports.__wbindgen_number_get = function(n, invalid) {
|
||||
let obj = getObject(n);
|
||||
if (typeof(obj) === 'number') return obj;
|
||||
getUint8Memory()[invalid] = 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
__exports.__wbindgen_is_null = function(idx) {
|
||||
return getObject(idx) === null ? 1 : 0;
|
||||
};
|
||||
|
||||
__exports.__wbindgen_is_undefined = function(idx) {
|
||||
return getObject(idx) === undefined ? 1 : 0;
|
||||
};
|
||||
|
||||
__exports.__wbindgen_boolean_get = function(i) {
|
||||
let v = getObject(i);
|
||||
if (typeof(v) === 'boolean') {
|
||||
|
@ -427,16 +412,78 @@ __exports.__wbindgen_boolean_get = function(i) {
|
|||
}
|
||||
};
|
||||
|
||||
__exports.__wbindgen_is_symbol = function(i) {
|
||||
return typeof(getObject(i)) === 'symbol' ? 1 : 0;
|
||||
__exports.__wbindgen_debug_string = function(i, len_ptr) {
|
||||
const toString = Object.prototype.toString;
|
||||
const debug_str = val => {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
if (type == 'number' || type == 'boolean' || val == null) {
|
||||
return `${val}`;
|
||||
}
|
||||
if (type == 'string') {
|
||||
return `"${val}"`;
|
||||
}
|
||||
if (type == 'symbol') {
|
||||
const description = val.description;
|
||||
if (description == null) {
|
||||
return 'Symbol';
|
||||
} else {
|
||||
return `Symbol(${description})`;
|
||||
}
|
||||
}
|
||||
if (type == 'function') {
|
||||
const name = val.name;
|
||||
if (typeof name == 'string' && name.length > 0) {
|
||||
return `Function(${name})`;
|
||||
} else {
|
||||
return 'Function';
|
||||
}
|
||||
}
|
||||
// objects
|
||||
if (Array.isArray(val)) {
|
||||
const length = val.length;
|
||||
let debug = '[';
|
||||
if (length > 0) {
|
||||
debug += debug_str(val[0]);
|
||||
}
|
||||
for(let i = 1; i < length; i++) {
|
||||
debug += ', ' + debug_str(val[i]);
|
||||
}
|
||||
debug += ']';
|
||||
return debug;
|
||||
}
|
||||
// Test for built-in
|
||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||
let className;
|
||||
if (builtInMatches.length > 1) {
|
||||
className = builtInMatches[1];
|
||||
} else {
|
||||
// Failed to match the standard '[object ClassName]'
|
||||
return toString.call(val);
|
||||
}
|
||||
if (className == 'Object') {
|
||||
// we're a user defined class or Object
|
||||
// JSON.stringify avoids problems with cycles, and is generally much
|
||||
// easier than looping through ownProperties of `val`.
|
||||
try {
|
||||
return 'Object(' + JSON.stringify(val) + ')';
|
||||
} catch (_) {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
// errors
|
||||
if (val instanceof Error) {
|
||||
return `${val.name}: ${val.message}
|
||||
${val.stack}`;
|
||||
}
|
||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||
return className;
|
||||
};
|
||||
|
||||
__exports.__wbindgen_string_get = function(i, len_ptr) {
|
||||
let obj = getObject(i);
|
||||
if (typeof(obj) !== 'string') return 0;
|
||||
const ptr = passStringToWasm(obj);
|
||||
getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;
|
||||
return ptr;
|
||||
const val = getObject(i);
|
||||
const debug = debug_str(val);
|
||||
const ptr = passStringToWasm(debug);
|
||||
getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;
|
||||
return ptr;
|
||||
};
|
||||
|
||||
__exports.__wbindgen_memory = function() { return addHeapObject(wasm.memory); };
|
||||
|
@ -479,7 +526,7 @@ __exports.__wbindgen_throw = function(ptr, len) {
|
|||
|
||||
function init(path_or_module) {
|
||||
let instantiation;
|
||||
const imports = { './emigui_wasm': __exports };
|
||||
const imports = { './example': __exports };
|
||||
if (path_or_module instanceof WebAssembly.Module) {
|
||||
instantiation = WebAssembly.instantiate(path_or_module, imports)
|
||||
.then(instance => {
|
BIN
docs/example_bg.wasm
Normal file
BIN
docs/example_bg.wasm
Normal file
Binary file not shown.
|
@ -39,26 +39,24 @@
|
|||
// hack when deploying over HTTP.
|
||||
delete WebAssembly.instantiateStreaming;
|
||||
</script>
|
||||
|
||||
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
|
||||
<script src="emigui_wasm.js"></script>
|
||||
<script src="example.js"></script>
|
||||
|
||||
<script>
|
||||
// we'll defer our execution until the wasm is ready to go
|
||||
function wasm_loaded() {
|
||||
console.log("wasm loaded");
|
||||
initialize();
|
||||
}
|
||||
// here we tell bindgen the path to the wasm file so it can start
|
||||
// initialization and return to us a promise when it's done
|
||||
wasm_bindgen("./emigui_wasm_bg.wasm")
|
||||
.then(wasm_loaded)["catch"](console.error);
|
||||
wasm_bindgen("./example_bg.wasm")
|
||||
.then(on_wasm_loaded)["catch"](console.error);
|
||||
// ----------------------------------------------------------------------------
|
||||
var g_webgl_painter = null;
|
||||
var g_wasm_app = null;
|
||||
|
||||
function paint_gui(canvas, input) {
|
||||
if (g_webgl_painter === null) {
|
||||
g_webgl_painter = wasm_bindgen.new_webgl_gui("canvas", pixels_per_point());
|
||||
if (g_wasm_app === null) {
|
||||
g_wasm_app = wasm_bindgen.new_webgl_gui("canvas", pixels_per_point());
|
||||
}
|
||||
wasm_bindgen.run_gui(g_webgl_painter, JSON.stringify(input));
|
||||
wasm_bindgen.run_gui(g_wasm_app, JSON.stringify(input));
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
var g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
||||
|
@ -93,7 +91,7 @@
|
|||
};
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
function on_wasm_loaded() {
|
||||
console.log("window.devicePixelRatio: " + window.devicePixelRatio);
|
||||
var canvas = document.getElementById("canvas");
|
||||
var repaint = function() {
|
||||
|
|
|
@ -1,79 +1,7 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
extern crate serde_json;
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
extern crate emigui;
|
||||
|
||||
use emigui::{label, widgets::Label, Align, Emigui, RawInput};
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod app;
|
||||
mod webgl;
|
||||
|
||||
fn now_ms() -> f64 {
|
||||
web_sys::window()
|
||||
.expect("should have a Window")
|
||||
.performance()
|
||||
.expect("should have a Performance")
|
||||
.now()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct State {
|
||||
app: app::App,
|
||||
emigui: Emigui,
|
||||
webgl_painter: webgl::Painter,
|
||||
everything_ms: f64,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new(canvas_id: &str, pixels_per_point: f32) -> Result<State, JsValue> {
|
||||
Ok(State {
|
||||
app: Default::default(),
|
||||
emigui: Emigui::new(pixels_per_point),
|
||||
webgl_painter: webgl::Painter::new(canvas_id)?,
|
||||
everything_ms: 0.0,
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&mut self, raw_input: RawInput) -> Result<(), JsValue> {
|
||||
let everything_start = now_ms();
|
||||
|
||||
self.emigui.new_frame(raw_input);
|
||||
|
||||
let mut region = self.emigui.whole_screen_region();
|
||||
let mut region = region.centered_column(region.width().min(480.0), Align::Min);
|
||||
self.app.show_gui(&mut region);
|
||||
self.emigui.example(&mut region);
|
||||
|
||||
region.add(label!("WebGl painter info:"));
|
||||
region.indent(|region| {
|
||||
region.add(label!(self.webgl_painter.debug_info()));
|
||||
});
|
||||
|
||||
region.add(label!("Everything: {:.1} ms", self.everything_ms));
|
||||
|
||||
let frame = self.emigui.paint();
|
||||
let result =
|
||||
self.webgl_painter
|
||||
.paint(&frame, self.emigui.texture(), raw_input.pixels_per_point);
|
||||
|
||||
self.everything_ms = now_ms() - everything_start;
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn new_webgl_gui(canvas_id: &str, pixels_per_point: f32) -> Result<State, JsValue> {
|
||||
State::new(canvas_id, pixels_per_point)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn run_gui(state: &mut State, raw_input_json: &str) -> Result<(), JsValue> {
|
||||
// TODO: nicer interface than JSON
|
||||
let raw_input: RawInput = serde_json::from_str(raw_input_json).unwrap();
|
||||
state.run(raw_input)
|
||||
}
|
||||
pub mod webgl;
|
||||
|
|
33
example/Cargo.toml
Normal file
33
example/Cargo.toml
Normal file
|
@ -0,0 +1,33 @@
|
|||
[package]
|
||||
name = "example"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emilernerfeldt@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3"
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
emigui = { path = "../emigui" }
|
||||
emigui_wasm = { path = "../emigui_wasm" }
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
'Document',
|
||||
'Element',
|
||||
'HtmlCanvasElement',
|
||||
'Performance',
|
||||
'WebGlBuffer',
|
||||
'WebGlProgram',
|
||||
'WebGlRenderingContext',
|
||||
'WebGlShader',
|
||||
'WebGlTexture',
|
||||
'WebGlUniformLocation',
|
||||
'Window',
|
||||
]
|
|
@ -25,7 +25,7 @@ impl Default for App {
|
|||
|
||||
impl App {
|
||||
pub fn show_gui(&mut self, gui: &mut Region) {
|
||||
gui.add(label!("Emigui").text_style(TextStyle::Heading));
|
||||
gui.add(label!("Emigui!").text_style(TextStyle::Heading));
|
||||
gui.add(label!("Emigui is an Immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."));
|
||||
gui.add(Separator::new());
|
||||
|
79
example/src/lib.rs
Normal file
79
example/src/lib.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
extern crate serde_json;
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
extern crate emigui;
|
||||
extern crate emigui_wasm;
|
||||
|
||||
use emigui::{label, widgets::Label, Align, Emigui, RawInput};
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod app;
|
||||
|
||||
fn now_ms() -> f64 {
|
||||
web_sys::window()
|
||||
.expect("should have a Window")
|
||||
.performance()
|
||||
.expect("should have a Performance")
|
||||
.now()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct State {
|
||||
app: app::App,
|
||||
emigui: Emigui,
|
||||
webgl_painter: emigui_wasm::webgl::Painter,
|
||||
everything_ms: f64,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new(canvas_id: &str, pixels_per_point: f32) -> Result<State, JsValue> {
|
||||
Ok(State {
|
||||
app: Default::default(),
|
||||
emigui: Emigui::new(pixels_per_point),
|
||||
webgl_painter: emigui_wasm::webgl::Painter::new(canvas_id)?,
|
||||
everything_ms: 0.0,
|
||||
})
|
||||
}
|
||||
|
||||
fn run(&mut self, raw_input: RawInput) -> Result<(), JsValue> {
|
||||
let everything_start = now_ms();
|
||||
|
||||
self.emigui.new_frame(raw_input);
|
||||
|
||||
let mut region = self.emigui.whole_screen_region();
|
||||
let mut region = region.centered_column(region.width().min(480.0), Align::Min);
|
||||
self.app.show_gui(&mut region);
|
||||
self.emigui.example(&mut region);
|
||||
|
||||
region.add(label!("WebGl painter info:"));
|
||||
region.indent(|region| {
|
||||
region.add(label!(self.webgl_painter.debug_info()));
|
||||
});
|
||||
|
||||
region.add(label!("Everything: {:.1} ms", self.everything_ms));
|
||||
|
||||
let frame = self.emigui.paint();
|
||||
let result =
|
||||
self.webgl_painter
|
||||
.paint(&frame, self.emigui.texture(), raw_input.pixels_per_point);
|
||||
|
||||
self.everything_ms = now_ms() - everything_start;
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn new_webgl_gui(canvas_id: &str, pixels_per_point: f32) -> Result<State, JsValue> {
|
||||
State::new(canvas_id, pixels_per_point)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn run_gui(state: &mut State, raw_input_json: &str) -> Result<(), JsValue> {
|
||||
// TODO: nicer interface than JSON
|
||||
let raw_input: RawInput = serde_json::from_str(raw_input_json).unwrap();
|
||||
state.run(raw_input)
|
||||
}
|
Loading…
Reference in a new issue