No typescript. Just one index.html + wasm.

This commit is contained in:
Emil Ernerfeldt 2019-01-05 22:55:09 +01:00
parent fafc802ffd
commit aa63303892
12 changed files with 146 additions and 336 deletions

1
.gitignore vendored
View File

@ -1,3 +1,2 @@
*.sublime*
/docs/*.d.ts
/target

View File

@ -7,16 +7,10 @@ if ! [[ $(wasm-bindgen --version) ]]; then
cargo install -f wasm-bindgen-cli
fi
if ! [[ -f docs/webassembly.d.ts ]]; then
curl https://raw.githubusercontent.com/01alchemist/webassembly-types/master/webassembly.d.ts > docs/webassembly.d.ts
fi
BUILD=debug
# BUILD=release
# Clear output from old stuff:
# rm -rf docs/*.d.ts
rm -rf docs/*.js
rm -rf docs/*.wasm
function build_rust
@ -28,15 +22,8 @@ function build_rust
FOLDER_NAME=${PWD##*/}
TARGET_NAME="emgui_wasm.wasm"
wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \
--out-dir docs --no-modules
--out-dir docs --no-modules --no-typescript
# --no-modules-global hoboho
}
build_rust
echo "Compile typescript:"
tsc
# wait || exit $?
# 3.4 s

Binary file not shown.

View File

@ -1,86 +0,0 @@
// 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("./emgui_wasm_bg.wasm")
.then(wasm_loaded)["catch"](console.error);
// ----------------------------------------------------------------------------
var g_webgl_painter = null;
function paint_gui(canvas, input) {
if (g_webgl_painter === null) {
g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas");
}
wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input));
}
// ----------------------------------------------------------------------------
var g_mouse_pos = { x: -1000.0, y: -1000.0 };
var g_mouse_down = false;
function auto_resize_canvas(canvas) {
if (true) {
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);
}
else {
// TODO: this stuff
var pixels_per_point = window.devicePixelRatio || 1;
var ctx = canvas.getContext("2d");
ctx.scale(pixels_per_point, pixels_per_point);
canvas.setAttribute("width", window.innerWidth * pixels_per_point);
canvas.setAttribute("height", window.innerHeight * pixels_per_point);
}
}
function get_input(canvas) {
return {
mouse_down: g_mouse_down,
mouse_pos: g_mouse_pos,
screen_size: { x: canvas.width, y: canvas.height }
};
}
function mouse_pos_from_event(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
function initialize() {
console.log("window.devicePixelRatio: " + window.devicePixelRatio);
var canvas = document.getElementById("canvas");
auto_resize_canvas(canvas);
var repaint = function () { return paint_gui(canvas, get_input(canvas)); };
canvas.addEventListener("mousemove", function (event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseleave", function (event) {
g_mouse_pos = { x: -1000.0, y: -1000.0 };
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mousedown", function (event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = true;
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseup", function (event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = false;
repaint();
event.stopPropagation();
event.preventDefault();
});
window.addEventListener("load", repaint);
window.addEventListener("pagehide", repaint);
window.addEventListener("pageshow", repaint);
window.addEventListener("resize", repaint);
// setInterval(repaint, 16);
repaint();
}

View File

@ -1,128 +0,0 @@
interface Vec2 {
x: number;
y: number;
}
/// What the integration gives to the gui.
interface RawInput {
/// Is the button currently down?
mouse_down: boolean;
/// Current position of the mouse in points.
mouse_pos: Vec2;
/// Size of the screen in points.
screen_size: Vec2;
}
// ----------------------------------------------------------------------------
// the `wasm_bindgen` global is set to the exports of the Rust module. Override with wasm-bindgen --no-modules-global
declare var wasm_bindgen: any;
// 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("./emgui_wasm_bg.wasm")
.then(wasm_loaded)
.catch(console.error);
// ----------------------------------------------------------------------------
let g_webgl_painter = null;
function paint_gui(canvas, input: RawInput) {
if (g_webgl_painter === null) {
g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas");
}
wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input));
}
// ----------------------------------------------------------------------------
let g_mouse_pos = { x: -1000.0, y: -1000.0 };
let g_mouse_down = false;
function auto_resize_canvas(canvas) {
if (true) {
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);
} else {
// TODO: this stuff
const pixels_per_point = window.devicePixelRatio || 1;
const ctx = canvas.getContext("2d");
ctx.scale(pixels_per_point, pixels_per_point);
canvas.setAttribute("width", window.innerWidth * pixels_per_point);
canvas.setAttribute("height", window.innerHeight * pixels_per_point);
}
}
function get_input(canvas): RawInput {
return {
mouse_down: g_mouse_down,
mouse_pos: g_mouse_pos,
screen_size: { x: canvas.width, y: canvas.height },
};
}
function mouse_pos_from_event(canvas, event): Vec2 {
const rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
};
}
function initialize() {
console.log(`window.devicePixelRatio: ${window.devicePixelRatio}`);
const canvas = document.getElementById("canvas");
auto_resize_canvas(canvas);
const repaint = () => paint_gui(canvas, get_input(canvas));
canvas.addEventListener("mousemove", event => {
g_mouse_pos = mouse_pos_from_event(canvas, event);
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseleave", event => {
g_mouse_pos = { x: -1000.0, y: -1000.0 };
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mousedown", event => {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = true;
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseup", event => {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = false;
repaint();
event.stopPropagation();
event.preventDefault();
});
window.addEventListener("load", repaint);
window.addEventListener("pagehide", repaint);
window.addEventListener("pageshow", repaint);
window.addEventListener("resize", repaint);
// setInterval(repaint, 16);
repaint();
}

View File

@ -1,42 +1,136 @@
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<title>Emgui A experiment in an Immediate Mode GUI written in Rust</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<title>Emgui A experiment in an Immediate Mode GUI written in Rust</title>
<style>
html {
html {
/* Remove touch delay: */
touch-action: manipulation;
}
body {
background: #000000;
}
html, body {
overflow: hidden;
}
</style>
</head>
<body>
<script>
// The `--no-modules`-generated JS from `wasm-bindgen` attempts to use
// `WebAssembly.instantiateStreaming` to instantiate the wasm module,
// but this doesn't work with `file://` urls. This example is frequently
// viewed by simply opening `index.html` in a browser (with a `file://`
// url), so it would fail if we were to call this function!
//
// Work around this for now by deleting the function to ensure that the
// `no_modules.js` script doesn't have access to it. You won't need this
// hack when deploying over HTTP.
delete WebAssembly.instantiateStreaming;
</script>
}
body {
background: #000000;
}
html,
body {
overflow: hidden;
}
</style>
</head>
<body>
<script>
// The `--no-modules`-generated JS from `wasm-bindgen` attempts to use
// `WebAssembly.instantiateStreaming` to instantiate the wasm module,
// but this doesn't work with `file://` urls. This example is frequently
// viewed by simply opening `index.html` in a browser (with a `file://`
// url), so it would fail if we were to call this function!
//
// Work around this for now by deleting the function to ensure that the
// `no_modules.js` script doesn't have access to it. You won't need this
// hack when deploying over HTTP.
delete WebAssembly.instantiateStreaming;
</script>
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
<script src="emgui_wasm.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("./emgui_wasm_bg.wasm")
.then(wasm_loaded)["catch"](console.error);
// ----------------------------------------------------------------------------
var g_webgl_painter = null;
<script src="frontend.js" type="module"></script>
function paint_gui(canvas, input) {
if (g_webgl_painter === null) {
g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas");
}
wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input));
}
// ----------------------------------------------------------------------------
var g_mouse_pos = { x: -1000.0, y: -1000.0 };
var g_mouse_down = false;
function auto_resize_canvas(canvas) {
// TODO: figure out why this isn't quite working.
if (true) {
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);
} else {
// TODO: this stuff
var pixels_per_point = window.devicePixelRatio || 1;
canvas.setAttribute("width", window.innerWidth * pixels_per_point);
canvas.setAttribute("height", window.innerHeight * pixels_per_point);
}
}
function get_input(canvas) {
return {
mouse_down: g_mouse_down,
mouse_pos: g_mouse_pos,
screen_size: { x: canvas.width, y: canvas.height }
};
}
function mouse_pos_from_event(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
function initialize() {
console.log("window.devicePixelRatio: " + window.devicePixelRatio);
var canvas = document.getElementById("canvas");
var repaint = function() {
auto_resize_canvas(canvas);
paint_gui(canvas, get_input(canvas));
};
canvas.addEventListener("mousemove", function(event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseleave", function(event) {
g_mouse_pos = { x: -1000.0, y: -1000.0 };
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mousedown", function(event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = true;
repaint();
event.stopPropagation();
event.preventDefault();
});
canvas.addEventListener("mouseup", function(event) {
g_mouse_pos = mouse_pos_from_event(canvas, event);
g_mouse_down = false;
repaint();
event.stopPropagation();
event.preventDefault();
});
window.addEventListener("load", repaint);
window.addEventListener("pagehide", repaint);
window.addEventListener("pageshow", repaint);
window.addEventListener("resize", repaint);
// setInterval(repaint, 16);
repaint();
}
</script>
<!-- TODO: make this cover the entire screen, with resize and all -->
<canvas id="canvas" width="1024" height="1024"></canvas>
</body>
</body>
</html>

View File

@ -5,19 +5,13 @@ use rusttype::{point, Scale};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct UvRect {
/// X/Y offset for nice rendering
pub offset_x: i16,
pub offset: (i16, i16),
/// Y offset for nice rendering
pub offset_y: i16,
pub min_x: u16,
pub min_y: u16,
/// Inclusive.
pub max_x: u16,
/// Top left corner.
pub min: (u16, u16),
/// Inclusive
pub max_y: u16,
pub max: (u16, u16),
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -50,8 +44,10 @@ pub struct Font {
impl Font {
pub fn new(scale: usize) -> Font {
// TODO: figure out a way to make the wasm smaller despite including a font.
// let font_data = include_bytes!("../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
let font_data = include_bytes!("../fonts/DejaVuSans.ttf"); // 20 works nicely for this.
// let font_data = include_bytes!("../fonts/DejaVuSans.ttf");
let font_data = include_bytes!("../fonts/Roboto-Regular.ttf");
let font = rusttype::Font::from_bytes(font_data as &[u8]).expect("Error constructing Font");
// println!(
@ -125,12 +121,12 @@ impl Font {
id: glyph.id(),
advance_width: glyph.unpositioned().h_metrics().advance_width,
uv: Some(UvRect {
offset_x: bb.min.x as i16,
offset_y: offset_y as i16,
min_x: cursor_x as u16,
min_y: cursor_y as u16,
max_x: (cursor_x + glyph_width - 1) as u16,
max_y: (cursor_y + glyph_height - 1) as u16,
offset: (bb.min.x as i16, offset_y as i16),
min: (cursor_x as u16, cursor_y as u16),
max: (
(cursor_x + glyph_width - 1) as u16,
(cursor_y + glyph_height - 1) as u16,
),
}),
});
@ -250,11 +246,11 @@ impl Font {
cursor_x = 0.0;
}
if let Some(uv) = glyph.uv {
for x in uv.min_x..=uv.max_x {
for y in uv.min_y..=uv.max_y {
for x in uv.min.0..=uv.max.0 {
for y in uv.min.1..=uv.max.1 {
let pixel = self.pixel(x as u16, y as u16);
let rx = uv.offset_x + x as i16 - uv.min_x as i16;
let ry = uv.offset_y + y as i16 - uv.min_y as i16;
let rx = uv.offset.0 + x as i16 - uv.min.0 as i16;
let ry = uv.offset.1 + y as i16 - uv.min.1 as i16;
let px = (cursor_x + rx as f32).round();
let py = cursor_y + ry;
if 0.0 <= px && 0 <= py {

View File

@ -349,10 +349,10 @@ impl Painter {
let mut top_left = Vertex {
pos: *pos
+ vec2(
x_offset + (glyph.offset_x as f32),
glyph.offset_y as f32,
x_offset + (glyph.offset.0 as f32),
glyph.offset.1 as f32,
),
uv: (glyph.min_x, glyph.min_y),
uv: (glyph.min.0, glyph.min.1),
color: *color,
};
top_left.pos.x = top_left.pos.x.round(); // Pixel-perfection.
@ -360,10 +360,10 @@ impl Painter {
let bottom_right = Vertex {
pos: top_left.pos
+ vec2(
(1 + glyph.max_x - glyph.min_x) as f32,
(1 + glyph.max_y - glyph.min_y) as f32,
(1 + glyph.max.0 - glyph.min.0) as f32,
(1 + glyph.max.1 - glyph.min.1) as f32,
),
uv: (glyph.max_x + 1, glyph.max_y + 1),
uv: (glyph.max.0 + 1, glyph.max.1 + 1),
color: *color,
};
frame.add_rect(top_left, bottom_right);

View File

@ -3,7 +3,6 @@
extern crate lazy_static;
extern crate serde_json;
extern crate wasm_bindgen;
// extern crate web_sys;
extern crate emgui;
@ -16,32 +15,6 @@ use wasm_bindgen::prelude::*;
mod app;
mod webgl;
// #[wasm_bindgen]
// pub fn show_gui(raw_input_json: &str) -> String {
// // TODO: faster interface than JSON
// let raw_input: RawInput = serde_json::from_str(raw_input_json).unwrap();
// lazy_static::lazy_static! {
// static ref APP: Mutex<app::App> = Default::default();
// static ref EMGUI: Mutex<Emgui> = Default::default();
// }
// let mut emgui = EMGUI.lock().unwrap();
// emgui.new_frame(raw_input);
// use crate::app::GuiSettings;
// APP.lock().unwrap().show_gui(&mut emgui.layout);
// let mut style = emgui.style.clone();
// emgui.layout.foldable("Style", |gui| {
// style.show_gui(gui);
// });
// emgui.style = style;
// let commands = emgui.paint();
// serde_json::to_string(&commands).unwrap()
// }
fn font() -> Font {
Font::new(20) // TODO: don't create this multiple times
}

View File

@ -1,8 +1,5 @@
#!/bin/bash
set -eu
echo "Lint and clean up typescript:"
tslint --fix docs/*.ts
echo "Cargo clippy"
cargo clippy

View File

@ -1,8 +0,0 @@
{
"compilerOptions": {
"module": "es2015",
},
"include": [
"docs/**/*"
]
}

View File

@ -1,14 +0,0 @@
{
"defaultSeverity": "error",
"extends": ["tslint:recommended"],
"jsRules": {},
"rules": {
"arrow-parens": [true, "ban-single-arg-parens"],
"interface-name": [true, "never-prefix"],
"max-classes-per-file": [false],
"no-bitwise": false,
"no-console": false,
"variable-name": false
},
"rulesDirectory": []
}