1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Initial commit: Closed loop of TS->Rust->TS

This commit is contained in:
Emil Ernerfeldt
2018-12-23 19:42:30 +01:00
commit 856bbf4dae
14 changed files with 701 additions and 0 deletions

11
docs/emgui.d.ts vendored Normal file
View File

@@ -0,0 +1,11 @@
/* tslint:disable */
export function show_gui(arg0: string): string;
export class Input {
free(): void;
screen_width: number
screen_height: number
mouse_x: number
mouse_y: number
}

151
docs/emgui.js Normal file
View File

@@ -0,0 +1,151 @@
(function() {
var wasm;
const __exports = {};
let cachedTextEncoder = new TextEncoder('utf-8');
let cachegetUint8Memory = null;
function getUint8Memory() {
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory;
}
function passStringToWasm(arg) {
const buf = cachedTextEncoder.encode(arg);
const ptr = wasm.__wbindgen_malloc(buf.length);
getUint8Memory().set(buf, ptr);
return [ptr, buf.length];
}
let cachedTextDecoder = new TextDecoder('utf-8');
function getStringFromWasm(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
}
let cachedGlobalArgumentPtr = null;
function globalArgumentPtr() {
if (cachedGlobalArgumentPtr === null) {
cachedGlobalArgumentPtr = wasm.__wbindgen_global_argument_ptr();
}
return cachedGlobalArgumentPtr;
}
let cachegetUint32Memory = null;
function getUint32Memory() {
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory;
}
/**
* @param {string} arg0
* @returns {string}
*/
__exports.show_gui = function(arg0) {
const [ptr0, len0] = passStringToWasm(arg0);
const retptr = globalArgumentPtr();
try {
wasm.show_gui(retptr, ptr0, len0);
const mem = getUint32Memory();
const rustptr = mem[retptr / 4];
const rustlen = mem[retptr / 4 + 1];
const realRet = getStringFromWasm(rustptr, rustlen).slice();
wasm.__wbindgen_free(rustptr, rustlen * 1);
return realRet;
} finally {
wasm.__wbindgen_free(ptr0, len0 * 1);
}
};
function freeInput(ptr) {
wasm.__wbg_input_free(ptr);
}
/**
*/
class Input {
free() {
const ptr = this.ptr;
this.ptr = 0;
freeInput(ptr);
}
/**
* @returns {number}
*/
get screen_width() {
return wasm.__wbg_get_input_screen_width(this.ptr);
}
set screen_width(arg0) {
return wasm.__wbg_set_input_screen_width(this.ptr, arg0);
}
/**
* @returns {number}
*/
get screen_height() {
return wasm.__wbg_get_input_screen_height(this.ptr);
}
set screen_height(arg0) {
return wasm.__wbg_set_input_screen_height(this.ptr, arg0);
}
/**
* @returns {number}
*/
get mouse_x() {
return wasm.__wbg_get_input_mouse_x(this.ptr);
}
set mouse_x(arg0) {
return wasm.__wbg_set_input_mouse_x(this.ptr, arg0);
}
/**
* @returns {number}
*/
get mouse_y() {
return wasm.__wbg_get_input_mouse_y(this.ptr);
}
set mouse_y(arg0) {
return wasm.__wbg_set_input_mouse_y(this.ptr, arg0);
}
}
__exports.Input = Input;
__exports.__wbindgen_throw = function(ptr, len) {
throw new Error(getStringFromWasm(ptr, len));
};
function init(path_or_module) {
let instantiation;
const imports = { './emgui': __exports };
if (path_or_module instanceof WebAssembly.Module) {
instantiation = WebAssembly.instantiate(path_or_module, imports)
.then(instance => {
return { instance, module: module_or_path }
});
} else {
const data = fetch(path_or_module);
if (typeof WebAssembly.instantiateStreaming === 'function') {
instantiation = WebAssembly.instantiateStreaming(data, imports);
} else {
instantiation = data
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.instantiate(buffer, imports));
}
}
return instantiation.then(({instance}) => {
wasm = init.wasm = instance.exports;
return;
});
};
self.wasm_bindgen = Object.assign(init, __exports);
})();

BIN
docs/emgui_bg.wasm Normal file

Binary file not shown.

112
docs/frontend.js Normal file
View File

@@ -0,0 +1,112 @@
// ----------------------------------------------------------------------------
// Paint module:
function paintCommand(canvas, cmd) {
var ctx = canvas.getContext("2d");
switch (cmd.kind) {
case "clear":
ctx.fillStyle = cmd.fill_style;
ctx.clearRect(0, 0, canvas.width, canvas.height);
return;
case "line":
ctx.beginPath();
ctx.lineWidth = cmd.line_width;
ctx.strokeStyle = cmd.stroke_style;
ctx.moveTo(cmd.from[0], cmd.from[1]);
ctx.lineTo(cmd.to[0], cmd.to[1]);
ctx.stroke();
return;
case "circle":
ctx.fillStyle = cmd.fill_style;
ctx.beginPath();
ctx.arc(cmd.center[0], cmd.center[1], cmd.radius, 0, 2 * Math.PI, false);
ctx.fill();
return;
case "rounded_rect":
ctx.fillStyle = cmd.fill_style;
var x = cmd.pos[0];
var y = cmd.pos[1];
var width = cmd.size[0];
var height = cmd.size[1];
var radius = cmd.radius;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
return;
case "text":
ctx.font = cmd.font;
ctx.fillStyle = cmd.fill_style;
ctx.textAlign = cmd.text_align;
ctx.fillText(cmd.text, cmd.pos[0], cmd.pos[1]);
return;
}
}
// 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_bg.wasm")
.then(wasm_loaded)["catch"](console.error);
function rust_gui(input) {
return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input)));
}
// ----------------------------------------------------------------------------
function js_gui(input) {
var commands = [];
commands.push({
fillStyle: "#111111",
kind: "clear"
});
commands.push({
fillStyle: "#ff1111",
kind: "rounded_rect",
pos: [100, 100],
radius: 20,
size: [200, 100]
});
return commands;
}
function paint_gui(canvas, mouse_pos) {
var input = {
mouse_x: mouse_pos.x,
mouse_y: mouse_pos.y,
screen_height: canvas.height,
screen_width: canvas.width
};
var commands = rust_gui(input);
for (var _i = 0, commands_1 = commands; _i < commands_1.length; _i++) {
var cmd = commands_1[_i];
paintCommand(canvas, cmd);
}
}
// ----------------------------------------------------------------------------
function mouse_pos_from_event(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function initialize() {
var canvas = document.getElementById("canvas");
canvas.addEventListener("mousemove", function (evt) {
var mouse_pos = mouse_pos_from_event(canvas, evt);
paint_gui(canvas, mouse_pos);
}, false);
canvas.addEventListener("mousedown", function (evt) {
var mouse_pos = mouse_pos_from_event(canvas, evt);
paint_gui(canvas, mouse_pos);
}, false);
paint_gui(canvas, { x: 0, y: 0 });
}

206
docs/frontend.ts Normal file
View File

@@ -0,0 +1,206 @@
// ----------------------------------------------------------------------------
// Paint module:
interface Clear {
kind: "clear";
fill_style: string;
}
interface Line {
kind: "line";
from: [number, number];
line_width: number;
stroke_style: string;
to: [number, number];
}
interface Circle {
kind: "circle";
center: [number, number];
fill_style: string;
radius: number;
}
interface RoundedRect {
kind: "rounded_rect";
fill_style: string;
pos: [number, number];
radius: number;
size: [number, number];
}
interface Text {
kind: "text";
fill_style: string;
font: string;
pos: [number, number];
text: string;
text_align: "start" | "center" | "end";
}
type PaintCmd = Clear | Line | Circle | RoundedRect | Text;
function paintCommand(canvas, cmd: PaintCmd) {
const ctx = canvas.getContext("2d");
switch (cmd.kind) {
case "clear":
ctx.fillStyle = cmd.fill_style;
ctx.clearRect(0, 0, canvas.width, canvas.height);
return;
case "line":
ctx.beginPath();
ctx.lineWidth = cmd.line_width;
ctx.strokeStyle = cmd.stroke_style;
ctx.moveTo(cmd.from[0], cmd.from[1]);
ctx.lineTo(cmd.to[0], cmd.to[1]);
ctx.stroke();
return;
case "circle":
ctx.fillStyle = cmd.fill_style;
ctx.beginPath();
ctx.arc(cmd.center[0], cmd.center[1], cmd.radius, 0, 2 * Math.PI, false);
ctx.fill();
return;
case "rounded_rect":
ctx.fillStyle = cmd.fill_style;
const x = cmd.pos[0];
const y = cmd.pos[1];
const width = cmd.size[0];
const height = cmd.size[1];
const radius = cmd.radius;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(
x + width,
y + height,
x + width - radius,
y + height,
);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
return;
case "text":
ctx.font = cmd.font;
ctx.fillStyle = cmd.fill_style;
ctx.textAlign = cmd.text_align;
ctx.fillText(cmd.text, cmd.pos[0], cmd.pos[1]);
return;
}
}
// ----------------------------------------------------------------------------
interface Coord {
x: number;
y: number;
}
interface Input {
mouse_x: number;
mouse_y: number;
screen_height: number;
screen_width: number;
// TODO: mouse down etc
}
// ----------------------------------------------------------------------------
// 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_bg.wasm")
.then(wasm_loaded)
.catch(console.error);
function rust_gui(input: Input): PaintCmd[] {
return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input)));
}
// ----------------------------------------------------------------------------
function js_gui(input: Input): PaintCmd[] {
const commands = [];
commands.push({
fillStyle: "#111111",
kind: "clear",
});
commands.push({
fillStyle: "#ff1111",
kind: "rounded_rect",
pos: [100, 100],
radius: 20,
size: [200, 100],
});
return commands;
}
function paint_gui(canvas, mouse_pos) {
const input = {
mouse_x: mouse_pos.x,
mouse_y: mouse_pos.y,
screen_height: canvas.height,
screen_width: canvas.width,
};
const commands = rust_gui(input);
for (const cmd of commands) {
paintCommand(canvas, cmd);
}
}
// ----------------------------------------------------------------------------
function mouse_pos_from_event(canvas, evt): Coord {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top,
};
}
function initialize() {
const canvas = document.getElementById("canvas");
canvas.addEventListener(
"mousemove",
(evt) => {
const mouse_pos = mouse_pos_from_event(canvas, evt);
paint_gui(canvas, mouse_pos);
},
false,
);
canvas.addEventListener(
"mousedown",
(evt) => {
const mouse_pos = mouse_pos_from_event(canvas, evt);
paint_gui(canvas, mouse_pos);
},
false,
);
paint_gui(canvas, { x: 0, y: 0 });
}

44
docs/index.html Normal file
View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<title>Gui Experiment</title>
<style>
html {
/* Remove touch delay: */
touch-action: manipulation;
}
body {
background: #111111;
color: #bbbbbb;
max-width: 480px;
margin: auto;
}
</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.js"></script>
<script src="frontend.js" type="module"></script>
<!-- TODO: make this cover the entire screen, with resize and all -->
<canvas id="canvas" width="480" height="800"></canvas>
</body>
</html>