WIP: rust WebGL rendering
This commit is contained in:
parent
bfa20be28e
commit
a1ddef742d
22 changed files with 1346 additions and 202 deletions
|
@ -24,3 +24,7 @@ Everything else is written in Rust, compiled to WASM.
|
||||||
|
|
||||||
Make an "any" editor. Store text files, make a VERY SIMPLE text editor, in the web.
|
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).
|
Supports MARKDEEP. A place for you ideas. Stored on your computer (local storage).
|
||||||
|
|
||||||
|
# Credits / Licenses
|
||||||
|
|
||||||
|
ProggyClean.ttf, Copyright (c) 2004, 2005 Tristan Grimmer. MIT License. http://www.proggyfonts.net/
|
||||||
|
|
2
build.sh
2
build.sh
|
@ -26,7 +26,7 @@ function build_rust
|
||||||
|
|
||||||
echo "Generate JS bindings for wasm:"
|
echo "Generate JS bindings for wasm:"
|
||||||
FOLDER_NAME=${PWD##*/}
|
FOLDER_NAME=${PWD##*/}
|
||||||
TARGET_NAME="$FOLDER_NAME.wasm"
|
TARGET_NAME="emgui_wasm.wasm"
|
||||||
wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \
|
wasm-bindgen "target/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \
|
||||||
--out-dir docs --no-modules
|
--out-dir docs --no-modules
|
||||||
# --no-modules-global hoboho
|
# --no-modules-global hoboho
|
||||||
|
|
3
docs/emgui.d.ts
vendored
3
docs/emgui.d.ts
vendored
|
@ -1,3 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
export function show_gui(arg0: string): string;
|
|
||||||
|
|
102
docs/emgui.js
102
docs/emgui.js
|
@ -1,102 +0,0 @@
|
||||||
(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
let WASM_VECTOR_LEN = 0;
|
|
||||||
|
|
||||||
function passStringToWasm(arg) {
|
|
||||||
|
|
||||||
const buf = cachedTextEncoder.encode(arg);
|
|
||||||
const ptr = wasm.__wbindgen_malloc(buf.length);
|
|
||||||
getUint8Memory().set(buf, ptr);
|
|
||||||
WASM_VECTOR_LEN = buf.length;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = passStringToWasm(arg0);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
__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: path_or_module }
|
|
||||||
});
|
|
||||||
} 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;
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
self.wasm_bindgen = Object.assign(init, __exports);
|
|
||||||
})();
|
|
Binary file not shown.
561
docs/emgui_wasm.js
Normal file
561
docs/emgui_wasm.js
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
|
function passStringToWasm(arg) {
|
||||||
|
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
const ptr = wasm.__wbindgen_malloc(buf.length);
|
||||||
|
getUint8Memory().set(buf, ptr);
|
||||||
|
WASM_VECTOR_LEN = buf.length;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = passStringToWasm(arg0);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} arg0
|
||||||
|
* @returns {Painter}
|
||||||
|
*/
|
||||||
|
__exports.new_webgl_painter = function(arg0) {
|
||||||
|
const ptr0 = passStringToWasm(arg0);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
try {
|
||||||
|
return Painter.__wrap(wasm.new_webgl_painter(ptr0, len0));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_free(ptr0, len0 * 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Painter} arg0
|
||||||
|
* @param {string} arg1
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
__exports.paint_webgl = function(arg0, arg1) {
|
||||||
|
const ptr1 = passStringToWasm(arg1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
try {
|
||||||
|
return wasm.paint_webgl(arg0.ptr, ptr1, len1);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_free(ptr1, len1 * 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const heap = new Array(32);
|
||||||
|
|
||||||
|
heap.fill(undefined);
|
||||||
|
|
||||||
|
heap.push(undefined, null, true, false);
|
||||||
|
|
||||||
|
function getObject(idx) { return heap[idx]; }
|
||||||
|
|
||||||
|
let heap_next = heap.length;
|
||||||
|
|
||||||
|
function addHeapObject(obj) {
|
||||||
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||||
|
const idx = heap_next;
|
||||||
|
heap_next = heap[idx];
|
||||||
|
|
||||||
|
heap[idx] = obj;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikeNone(x) {
|
||||||
|
return x === undefined || x === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const __widl_f_get_element_by_id_Document_target = typeof Document === 'undefined' ? null : Document.prototype.getElementById || function() {
|
||||||
|
throw new Error(`wasm-bindgen: Document.getElementById does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_element_by_id_Document = function(arg0, arg1, arg2) {
|
||||||
|
let varg1 = getStringFromWasm(arg1, arg2);
|
||||||
|
|
||||||
|
const val = __widl_f_get_element_by_id_Document_target.call(getObject(arg0), varg1);
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_instanceof_HTMLCanvasElement = function(idx) {
|
||||||
|
return getObject(idx) instanceof HTMLCanvasElement ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_context_HTMLCanvasElement_target = typeof HTMLCanvasElement === 'undefined' ? null : HTMLCanvasElement.prototype.getContext || function() {
|
||||||
|
throw new Error(`wasm-bindgen: HTMLCanvasElement.getContext does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_context_HTMLCanvasElement = function(arg0, arg1, arg2, exnptr) {
|
||||||
|
let varg1 = getStringFromWasm(arg1, arg2);
|
||||||
|
try {
|
||||||
|
|
||||||
|
const val = __widl_f_get_context_HTMLCanvasElement_target.call(getObject(arg0), varg1);
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
const view = getUint32Memory();
|
||||||
|
view[exnptr / 4] = 1;
|
||||||
|
view[exnptr / 4 + 1] = addHeapObject(e);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function GetOwnOrInheritedPropertyDescriptor(obj, id) {
|
||||||
|
while (obj) {
|
||||||
|
let desc = Object.getOwnPropertyDescriptor(obj, id);
|
||||||
|
if (desc) return desc;
|
||||||
|
obj = Object.getPrototypeOf(obj);
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const __widl_f_width_HTMLCanvasElement_target = GetOwnOrInheritedPropertyDescriptor(typeof HTMLCanvasElement === 'undefined' ? null : HTMLCanvasElement.prototype, 'width').get || function() {
|
||||||
|
throw new Error(`wasm-bindgen: HTMLCanvasElement.width does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_width_HTMLCanvasElement = function(arg0) {
|
||||||
|
return __widl_f_width_HTMLCanvasElement_target.call(getObject(arg0));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_height_HTMLCanvasElement_target = GetOwnOrInheritedPropertyDescriptor(typeof HTMLCanvasElement === 'undefined' ? null : HTMLCanvasElement.prototype, 'height').get || function() {
|
||||||
|
throw new Error(`wasm-bindgen: HTMLCanvasElement.height does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_height_HTMLCanvasElement = function(arg0) {
|
||||||
|
return __widl_f_height_HTMLCanvasElement_target.call(getObject(arg0));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_instanceof_WebGLRenderingContext = function(idx) {
|
||||||
|
return getObject(idx) instanceof WebGLRenderingContext ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_buffer_data_with_array_buffer_view_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.bufferData || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.bufferData does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_buffer_data_with_array_buffer_view_WebGLRenderingContext = function(arg0, arg1, arg2, arg3) {
|
||||||
|
__widl_f_buffer_data_with_array_buffer_view_WebGLRenderingContext_target.call(getObject(arg0), arg1, getObject(arg2), arg3);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_attach_shader_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.attachShader || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.attachShader does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_attach_shader_WebGLRenderingContext = function(arg0, arg1, arg2) {
|
||||||
|
__widl_f_attach_shader_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), getObject(arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_bind_buffer_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.bindBuffer || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.bindBuffer does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_bind_buffer_WebGLRenderingContext = function(arg0, arg1, arg2) {
|
||||||
|
__widl_f_bind_buffer_WebGLRenderingContext_target.call(getObject(arg0), arg1, getObject(arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_blend_func_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.blendFunc || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.blendFunc does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_blend_func_WebGLRenderingContext = function(arg0, arg1, arg2) {
|
||||||
|
__widl_f_blend_func_WebGLRenderingContext_target.call(getObject(arg0), arg1, arg2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_clear_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.clear || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.clear does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_clear_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_clear_WebGLRenderingContext_target.call(getObject(arg0), arg1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_clear_color_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.clearColor || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.clearColor does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_clear_color_WebGLRenderingContext = function(arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
__widl_f_clear_color_WebGLRenderingContext_target.call(getObject(arg0), arg1, arg2, arg3, arg4);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_compile_shader_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.compileShader || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.compileShader does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_compile_shader_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_compile_shader_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_create_buffer_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.createBuffer || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.createBuffer does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_create_buffer_WebGLRenderingContext = function(arg0) {
|
||||||
|
|
||||||
|
const val = __widl_f_create_buffer_WebGLRenderingContext_target.call(getObject(arg0));
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_create_program_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.createProgram || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.createProgram does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_create_program_WebGLRenderingContext = function(arg0) {
|
||||||
|
|
||||||
|
const val = __widl_f_create_program_WebGLRenderingContext_target.call(getObject(arg0));
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_create_shader_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.createShader || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.createShader does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_create_shader_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
|
||||||
|
const val = __widl_f_create_shader_WebGLRenderingContext_target.call(getObject(arg0), arg1);
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_draw_elements_with_i32_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.drawElements || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.drawElements does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_draw_elements_with_i32_WebGLRenderingContext = function(arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
__widl_f_draw_elements_with_i32_WebGLRenderingContext_target.call(getObject(arg0), arg1, arg2, arg3, arg4);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_enable_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.enable || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.enable does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_enable_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_enable_WebGLRenderingContext_target.call(getObject(arg0), arg1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_enable_vertex_attrib_array_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.enableVertexAttribArray || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.enableVertexAttribArray does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_enable_vertex_attrib_array_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_enable_vertex_attrib_array_WebGLRenderingContext_target.call(getObject(arg0), arg1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_attrib_location_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getAttribLocation || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getAttribLocation does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_attrib_location_WebGLRenderingContext = function(arg0, arg1, arg2, arg3) {
|
||||||
|
let varg2 = getStringFromWasm(arg2, arg3);
|
||||||
|
return __widl_f_get_attrib_location_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), varg2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_program_info_log_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getProgramInfoLog || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getProgramInfoLog does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_program_info_log_WebGLRenderingContext = function(ret, arg0, arg1) {
|
||||||
|
const val = __widl_f_get_program_info_log_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1));
|
||||||
|
const retptr = isLikeNone(val) ? [0, 0] : passStringToWasm(val);
|
||||||
|
const retlen = WASM_VECTOR_LEN;
|
||||||
|
const mem = getUint32Memory();
|
||||||
|
mem[ret / 4] = retptr;
|
||||||
|
mem[ret / 4 + 1] = retlen;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_program_parameter_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getProgramParameter || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getProgramParameter does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_program_parameter_WebGLRenderingContext = function(arg0, arg1, arg2) {
|
||||||
|
return addHeapObject(__widl_f_get_program_parameter_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_shader_info_log_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getShaderInfoLog || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getShaderInfoLog does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_shader_info_log_WebGLRenderingContext = function(ret, arg0, arg1) {
|
||||||
|
const val = __widl_f_get_shader_info_log_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1));
|
||||||
|
const retptr = isLikeNone(val) ? [0, 0] : passStringToWasm(val);
|
||||||
|
const retlen = WASM_VECTOR_LEN;
|
||||||
|
const mem = getUint32Memory();
|
||||||
|
mem[ret / 4] = retptr;
|
||||||
|
mem[ret / 4 + 1] = retlen;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_shader_parameter_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getShaderParameter || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getShaderParameter does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_shader_parameter_WebGLRenderingContext = function(arg0, arg1, arg2) {
|
||||||
|
return addHeapObject(__widl_f_get_shader_parameter_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_get_uniform_location_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.getUniformLocation || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.getUniformLocation does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_get_uniform_location_WebGLRenderingContext = function(arg0, arg1, arg2, arg3) {
|
||||||
|
let varg2 = getStringFromWasm(arg2, arg3);
|
||||||
|
|
||||||
|
const val = __widl_f_get_uniform_location_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), varg2);
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_link_program_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.linkProgram || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.linkProgram does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_link_program_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_link_program_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_shader_source_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.shaderSource || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.shaderSource does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_shader_source_WebGLRenderingContext = function(arg0, arg1, arg2, arg3) {
|
||||||
|
let varg2 = getStringFromWasm(arg2, arg3);
|
||||||
|
__widl_f_shader_source_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), varg2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_uniform2f_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.uniform2f || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.uniform2f does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_uniform2f_WebGLRenderingContext = function(arg0, arg1, arg2, arg3) {
|
||||||
|
__widl_f_uniform2f_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1), arg2, arg3);
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_use_program_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.useProgram || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.useProgram does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_use_program_WebGLRenderingContext = function(arg0, arg1) {
|
||||||
|
__widl_f_use_program_WebGLRenderingContext_target.call(getObject(arg0), getObject(arg1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const __widl_f_vertex_attrib_pointer_with_i32_WebGLRenderingContext_target = typeof WebGLRenderingContext === 'undefined' ? null : WebGLRenderingContext.prototype.vertexAttribPointer || function() {
|
||||||
|
throw new Error(`wasm-bindgen: WebGLRenderingContext.vertexAttribPointer does not exist`);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_vertex_attrib_pointer_with_i32_WebGLRenderingContext = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
|
||||||
|
__widl_f_vertex_attrib_pointer_with_i32_WebGLRenderingContext_target.call(getObject(arg0), arg1, arg2, arg3, arg4 !== 0, arg5, arg6);
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_instanceof_Window = function(idx) {
|
||||||
|
return getObject(idx) instanceof Window ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__widl_f_document_Window = function(arg0) {
|
||||||
|
|
||||||
|
const val = getObject(arg0).document;
|
||||||
|
return isLikeNone(val) ? 0 : addHeapObject(val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_new_c1b585153cd441ad = function(arg0) {
|
||||||
|
return addHeapObject(new Float32Array(getObject(arg0)));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_subarray_6bef35518c0617bd = function(arg0, arg1, arg2) {
|
||||||
|
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_newnoargs_6a80f84471205fc8 = function(arg0, arg1) {
|
||||||
|
let varg0 = getStringFromWasm(arg0, arg1);
|
||||||
|
return addHeapObject(new Function(varg0));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_call_582b20dfcad7fee4 = function(arg0, arg1, exnptr) {
|
||||||
|
try {
|
||||||
|
return addHeapObject(getObject(arg0).call(getObject(arg1)));
|
||||||
|
} catch (e) {
|
||||||
|
const view = getUint32Memory();
|
||||||
|
view[exnptr / 4] = 1;
|
||||||
|
view[exnptr / 4 + 1] = addHeapObject(e);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_new_b192e0932f97e870 = function(arg0) {
|
||||||
|
return addHeapObject(new Int16Array(getObject(arg0)));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_subarray_46088290ce2ce733 = function(arg0, arg1, arg2) {
|
||||||
|
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_new_bc68e7aae4d4f791 = function(arg0) {
|
||||||
|
return addHeapObject(new Uint8Array(getObject(arg0)));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_subarray_705096b76e15e94e = function(arg0, arg1, arg2) {
|
||||||
|
return addHeapObject(getObject(arg0).subarray(arg1, arg2));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_instanceof_Memory_d223615e29613829 = function(idx) {
|
||||||
|
return getObject(idx) instanceof WebAssembly.Memory ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbg_buffer_0413d5edaa0ff323 = function(arg0) {
|
||||||
|
return addHeapObject(getObject(arg0).buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
function freePainter(ptr) {
|
||||||
|
|
||||||
|
wasm.__wbg_painter_free(ptr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class Painter {
|
||||||
|
|
||||||
|
static __wrap(ptr) {
|
||||||
|
const obj = Object.create(Painter.prototype);
|
||||||
|
obj.ptr = ptr;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
free() {
|
||||||
|
const ptr = this.ptr;
|
||||||
|
this.ptr = 0;
|
||||||
|
freePainter(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
__exports.Painter = Painter;
|
||||||
|
|
||||||
|
__exports.__wbindgen_object_clone_ref = function(idx) {
|
||||||
|
return addHeapObject(getObject(idx));
|
||||||
|
};
|
||||||
|
|
||||||
|
function dropObject(idx) {
|
||||||
|
if (idx < 36) return;
|
||||||
|
heap[idx] = heap_next;
|
||||||
|
heap_next = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
__exports.__wbindgen_object_drop_ref = function(i) { dropObject(i); };
|
||||||
|
|
||||||
|
__exports.__wbindgen_string_new = function(p, l) {
|
||||||
|
return addHeapObject(getStringFromWasm(p, l));
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbindgen_boolean_get = function(i) {
|
||||||
|
let v = getObject(i);
|
||||||
|
if (typeof(v) === 'boolean') {
|
||||||
|
return v ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
__exports.__wbindgen_memory = function() { return addHeapObject(wasm.memory); };
|
||||||
|
|
||||||
|
function takeObject(idx) {
|
||||||
|
const ret = getObject(idx);
|
||||||
|
dropObject(idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
__exports.__wbindgen_rethrow = function(idx) { throw takeObject(idx); };
|
||||||
|
|
||||||
|
__exports.__wbindgen_throw = function(ptr, len) {
|
||||||
|
throw new Error(getStringFromWasm(ptr, len));
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(path_or_module) {
|
||||||
|
let instantiation;
|
||||||
|
const imports = { './emgui_wasm': __exports };
|
||||||
|
if (path_or_module instanceof WebAssembly.Module) {
|
||||||
|
instantiation = WebAssembly.instantiate(path_or_module, imports)
|
||||||
|
.then(instance => {
|
||||||
|
return { instance, module: path_or_module }
|
||||||
|
});
|
||||||
|
} 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;
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
self.wasm_bindgen = Object.assign(init, __exports);
|
||||||
|
})();
|
BIN
docs/emgui_wasm_bg.wasm
Normal file
BIN
docs/emgui_wasm_bg.wasm
Normal file
Binary file not shown.
|
@ -1,4 +1,6 @@
|
||||||
function styleFromColor(color) {
|
// ----------------------------------------------------------------------------
|
||||||
|
// Canvas painting:
|
||||||
|
function style_from_color(color) {
|
||||||
return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + color.a / 255.0 + ")";
|
return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + color.a / 255.0 + ")";
|
||||||
}
|
}
|
||||||
function paint_command(canvas, cmd) {
|
function paint_command(canvas, cmd) {
|
||||||
|
@ -9,17 +11,17 @@ function paint_command(canvas, cmd) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false);
|
ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false);
|
||||||
if (cmd.fill_color) {
|
if (cmd.fill_color) {
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
if (cmd.outline) {
|
if (cmd.outline) {
|
||||||
ctx.lineWidth = cmd.outline.width;
|
ctx.lineWidth = cmd.outline.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.outline.color);
|
ctx.strokeStyle = style_from_color(cmd.outline.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "clear":
|
case "clear":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
return;
|
return;
|
||||||
case "line":
|
case "line":
|
||||||
|
@ -30,7 +32,7 @@ function paint_command(canvas, cmd) {
|
||||||
ctx.lineTo(point.x, point.y);
|
ctx.lineTo(point.x, point.y);
|
||||||
}
|
}
|
||||||
ctx.lineWidth = cmd.width;
|
ctx.lineWidth = cmd.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.color);
|
ctx.strokeStyle = style_from_color(cmd.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
return;
|
return;
|
||||||
case "rect":
|
case "rect":
|
||||||
|
@ -51,17 +53,17 @@ function paint_command(canvas, cmd) {
|
||||||
ctx.quadraticCurveTo(x, y, x + r, y);
|
ctx.quadraticCurveTo(x, y, x + r, y);
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
if (cmd.fill_color) {
|
if (cmd.fill_color) {
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
if (cmd.outline) {
|
if (cmd.outline) {
|
||||||
ctx.lineWidth = cmd.outline.width;
|
ctx.lineWidth = cmd.outline.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.outline.color);
|
ctx.strokeStyle = style_from_color(cmd.outline.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "text":
|
case "text":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.font = cmd.font_size + "px " + cmd.font_name;
|
ctx.font = cmd.font_size + "px " + cmd.font_name;
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
||||||
|
@ -75,7 +77,7 @@ function wasm_loaded() {
|
||||||
}
|
}
|
||||||
// here we tell bindgen the path to the wasm file so it can start
|
// 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
|
// initialization and return to us a promise when it's done
|
||||||
wasm_bindgen("./emgui_bg.wasm")
|
wasm_bindgen("./emgui_wasm_bg.wasm")
|
||||||
.then(wasm_loaded)["catch"](console.error);
|
.then(wasm_loaded)["catch"](console.error);
|
||||||
function rust_gui(input) {
|
function rust_gui(input) {
|
||||||
return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input)));
|
return JSON.parse(wasm_bindgen.show_gui(JSON.stringify(input)));
|
||||||
|
@ -96,27 +98,45 @@ function js_gui(input) {
|
||||||
});
|
});
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
var WEB_GL = true;
|
||||||
|
var g_webgl_painter = null;
|
||||||
function paint_gui(canvas, input) {
|
function paint_gui(canvas, input) {
|
||||||
var commands = rust_gui(input);
|
if (WEB_GL) {
|
||||||
commands.unshift({
|
if (g_webgl_painter === null) {
|
||||||
fill_color: { r: 0, g: 0, b: 0, a: 0 },
|
g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas");
|
||||||
kind: "clear"
|
}
|
||||||
});
|
wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input));
|
||||||
for (var _i = 0, commands_1 = commands; _i < commands_1.length; _i++) {
|
}
|
||||||
var cmd = commands_1[_i];
|
else {
|
||||||
paint_command(canvas, cmd);
|
var commands = rust_gui(input);
|
||||||
|
for (var _i = 0, commands_1 = commands; _i < commands_1.length; _i++) {
|
||||||
|
var cmd = commands_1[_i];
|
||||||
|
var commands_2 = rust_gui(input);
|
||||||
|
commands_2.unshift({
|
||||||
|
fill_color: { r: 0, g: 0, b: 0, a: 0 },
|
||||||
|
kind: "clear"
|
||||||
|
});
|
||||||
|
paint_command(canvas, cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
var g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
var g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
||||||
var g_mouse_down = false;
|
var g_mouse_down = false;
|
||||||
|
function auto_resize_canvas(canvas) {
|
||||||
|
if (WEB_GL) {
|
||||||
|
canvas.setAttribute("width", window.innerWidth);
|
||||||
|
canvas.setAttribute("height", window.innerHeight);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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) {
|
function get_input(canvas) {
|
||||||
var pixels_per_point = window.devicePixelRatio || 1;
|
|
||||||
var ctx = canvas.getContext("2d");
|
|
||||||
ctx.scale(pixels_per_point, pixels_per_point);
|
|
||||||
// Resize based on screen size:
|
|
||||||
canvas.setAttribute("width", window.innerWidth * pixels_per_point);
|
|
||||||
canvas.setAttribute("height", window.innerHeight * pixels_per_point);
|
|
||||||
return {
|
return {
|
||||||
mouse_down: g_mouse_down,
|
mouse_down: g_mouse_down,
|
||||||
mouse_pos: g_mouse_pos,
|
mouse_pos: g_mouse_pos,
|
||||||
|
@ -133,6 +153,7 @@ function mouse_pos_from_event(canvas, event) {
|
||||||
function initialize() {
|
function initialize() {
|
||||||
console.log("window.devicePixelRatio: " + window.devicePixelRatio);
|
console.log("window.devicePixelRatio: " + window.devicePixelRatio);
|
||||||
var canvas = document.getElementById("canvas");
|
var canvas = document.getElementById("canvas");
|
||||||
|
auto_resize_canvas(canvas);
|
||||||
var repaint = function () { return paint_gui(canvas, get_input(canvas)); };
|
var repaint = function () { return paint_gui(canvas, get_input(canvas)); };
|
||||||
canvas.addEventListener("mousemove", function (event) {
|
canvas.addEventListener("mousemove", function (event) {
|
||||||
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
||||||
|
|
137
docs/frontend.ts
137
docs/frontend.ts
|
@ -60,7 +60,10 @@ interface Text {
|
||||||
|
|
||||||
type PaintCmd = Circle | Clear | Line | Rect | Text;
|
type PaintCmd = Circle | Clear | Line | Rect | Text;
|
||||||
|
|
||||||
function styleFromColor(color: Color): string {
|
// ----------------------------------------------------------------------------
|
||||||
|
// Canvas painting:
|
||||||
|
|
||||||
|
function style_from_color(color: Color): string {
|
||||||
return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a / 255.0})`;
|
return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a / 255.0})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,18 +77,18 @@ function paint_command(canvas, cmd: PaintCmd) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false);
|
ctx.arc(cmd.center.x, cmd.center.y, cmd.radius, 0, 2 * Math.PI, false);
|
||||||
if (cmd.fill_color) {
|
if (cmd.fill_color) {
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
if (cmd.outline) {
|
if (cmd.outline) {
|
||||||
ctx.lineWidth = cmd.outline.width;
|
ctx.lineWidth = cmd.outline.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.outline.color);
|
ctx.strokeStyle = style_from_color(cmd.outline.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "clear":
|
case "clear":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -96,7 +99,7 @@ function paint_command(canvas, cmd: PaintCmd) {
|
||||||
ctx.lineTo(point.x, point.y);
|
ctx.lineTo(point.x, point.y);
|
||||||
}
|
}
|
||||||
ctx.lineWidth = cmd.width;
|
ctx.lineWidth = cmd.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.color);
|
ctx.strokeStyle = style_from_color(cmd.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -118,18 +121,18 @@ function paint_command(canvas, cmd: PaintCmd) {
|
||||||
ctx.quadraticCurveTo(x, y, x + r, y);
|
ctx.quadraticCurveTo(x, y, x + r, y);
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
if (cmd.fill_color) {
|
if (cmd.fill_color) {
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
if (cmd.outline) {
|
if (cmd.outline) {
|
||||||
ctx.lineWidth = cmd.outline.width;
|
ctx.lineWidth = cmd.outline.width;
|
||||||
ctx.strokeStyle = styleFromColor(cmd.outline.color);
|
ctx.strokeStyle = style_from_color(cmd.outline.color);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case "text":
|
case "text":
|
||||||
ctx.fillStyle = styleFromColor(cmd.fill_color);
|
ctx.fillStyle = style_from_color(cmd.fill_color);
|
||||||
ctx.font = `${cmd.font_size}px ${cmd.font_name}`;
|
ctx.font = `${cmd.font_size}px ${cmd.font_name}`;
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
ctx.fillText(cmd.text, cmd.pos.x, cmd.pos.y);
|
||||||
|
@ -164,7 +167,7 @@ function wasm_loaded() {
|
||||||
|
|
||||||
// here we tell bindgen the path to the wasm file so it can start
|
// 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
|
// initialization and return to us a promise when it's done
|
||||||
wasm_bindgen("./emgui_bg.wasm")
|
wasm_bindgen("./emgui_wasm_bg.wasm")
|
||||||
.then(wasm_loaded)
|
.then(wasm_loaded)
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
|
|
||||||
|
@ -193,15 +196,26 @@ function js_gui(input: RawInput): PaintCmd[] {
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
function paint_gui(canvas, input: RawInput) {
|
const WEB_GL = true;
|
||||||
const commands = rust_gui(input);
|
let g_webgl_painter = null;
|
||||||
commands.unshift({
|
|
||||||
fill_color: {r: 0, g: 0, b: 0, a: 0},
|
|
||||||
kind: "clear",
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const cmd of commands) {
|
function paint_gui(canvas, input: RawInput) {
|
||||||
paint_command(canvas, cmd);
|
if (WEB_GL) {
|
||||||
|
if (g_webgl_painter === null) {
|
||||||
|
g_webgl_painter = wasm_bindgen.new_webgl_painter("canvas");
|
||||||
|
}
|
||||||
|
wasm_bindgen.paint_webgl(g_webgl_painter, JSON.stringify(input));
|
||||||
|
} else {
|
||||||
|
let commands = rust_gui(input);
|
||||||
|
for (const cmd of commands) {
|
||||||
|
const commands = rust_gui(input);
|
||||||
|
commands.unshift({
|
||||||
|
fill_color: { r: 0, g: 0, b: 0, a: 0 },
|
||||||
|
kind: "clear",
|
||||||
|
});
|
||||||
|
|
||||||
|
paint_command(canvas, cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,16 +224,22 @@ function paint_gui(canvas, input: RawInput) {
|
||||||
let g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
let g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
||||||
let g_mouse_down = false;
|
let g_mouse_down = false;
|
||||||
|
|
||||||
|
function auto_resize_canvas(canvas) {
|
||||||
|
if (WEB_GL) {
|
||||||
|
canvas.setAttribute("width", window.innerWidth);
|
||||||
|
canvas.setAttribute("height", window.innerHeight);
|
||||||
|
} else {
|
||||||
|
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 {
|
function get_input(canvas): RawInput {
|
||||||
const pixels_per_point = window.devicePixelRatio || 1;
|
|
||||||
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
ctx.scale(pixels_per_point, pixels_per_point);
|
|
||||||
|
|
||||||
// Resize based on screen size:
|
|
||||||
canvas.setAttribute("width", window.innerWidth * pixels_per_point);
|
|
||||||
canvas.setAttribute("height", window.innerHeight * pixels_per_point);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mouse_down: g_mouse_down,
|
mouse_down: g_mouse_down,
|
||||||
mouse_pos: g_mouse_pos,
|
mouse_pos: g_mouse_pos,
|
||||||
|
@ -239,49 +259,38 @@ function initialize() {
|
||||||
console.log(`window.devicePixelRatio: ${window.devicePixelRatio}`);
|
console.log(`window.devicePixelRatio: ${window.devicePixelRatio}`);
|
||||||
|
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
|
auto_resize_canvas(canvas);
|
||||||
const repaint = () => paint_gui(canvas, get_input(canvas));
|
const repaint = () => paint_gui(canvas, get_input(canvas));
|
||||||
|
|
||||||
canvas.addEventListener(
|
canvas.addEventListener("mousemove", event => {
|
||||||
"mousemove",
|
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
||||||
(event) => {
|
repaint();
|
||||||
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
event.stopPropagation();
|
||||||
repaint();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
});
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
canvas.addEventListener(
|
canvas.addEventListener("mouseleave", event => {
|
||||||
"mouseleave",
|
g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
||||||
(event) => {
|
repaint();
|
||||||
g_mouse_pos = { x: -1000.0, y: -1000.0 };
|
event.stopPropagation();
|
||||||
repaint();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
});
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
canvas.addEventListener(
|
canvas.addEventListener("mousedown", event => {
|
||||||
"mousedown",
|
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
||||||
(event) => {
|
g_mouse_down = true;
|
||||||
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
repaint();
|
||||||
g_mouse_down = true;
|
event.stopPropagation();
|
||||||
repaint();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
});
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
canvas.addEventListener(
|
canvas.addEventListener("mouseup", event => {
|
||||||
"mouseup",
|
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
||||||
(event) => {
|
g_mouse_down = false;
|
||||||
g_mouse_pos = mouse_pos_from_event(canvas, event);
|
repaint();
|
||||||
g_mouse_down = false;
|
event.stopPropagation();
|
||||||
repaint();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
});
|
||||||
event.preventDefault();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
window.addEventListener("load", repaint);
|
window.addEventListener("load", repaint);
|
||||||
window.addEventListener("pagehide", repaint);
|
window.addEventListener("pagehide", repaint);
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
|
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
|
||||||
<script src="emgui.js"></script>
|
<script src="emgui_wasm.js"></script>
|
||||||
|
|
||||||
<script src="frontend.js" type="module"></script>
|
<script src="frontend.js" type="module"></script>
|
||||||
|
|
||||||
|
|
|
@ -8,5 +8,6 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# palette = "0.4"
|
# palette = "0.4"
|
||||||
|
rusttype = "0.7"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_derive = "1"
|
serde_derive = "1"
|
||||||
|
|
BIN
emgui/fonts/DejaVuSansMono.ttf
Normal file
BIN
emgui/fonts/DejaVuSansMono.ttf
Normal file
Binary file not shown.
BIN
emgui/fonts/ProggyClean.ttf
Normal file
BIN
emgui/fonts/ProggyClean.ttf
Normal file
Binary file not shown.
BIN
emgui/fonts/Roboto-Regular.ttf
Normal file
BIN
emgui/fonts/Roboto-Regular.ttf
Normal file
Binary file not shown.
218
emgui/src/font.rs
Normal file
218
emgui/src/font.rs
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
#![allow(unused)] // TODO
|
||||||
|
|
||||||
|
use rusttype::{point, Scale};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct GlyphInfo {
|
||||||
|
/// X offset for nice rendering
|
||||||
|
offset_x: u16,
|
||||||
|
|
||||||
|
/// Y offset for nice rendering
|
||||||
|
offset_y: u16,
|
||||||
|
|
||||||
|
min_x: u16,
|
||||||
|
min_y: u16,
|
||||||
|
|
||||||
|
/// Inclusive.
|
||||||
|
max_x: u16,
|
||||||
|
|
||||||
|
/// Inclusive
|
||||||
|
max_y: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Printable ascii characters [33, 126], which excludes 32 (space) and 127 (DEL)
|
||||||
|
const NUM_CHARS: usize = 94;
|
||||||
|
const FIRST_ASCII: usize = 33;
|
||||||
|
/// Inclusive
|
||||||
|
const LAST_ASCII: usize = 126;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Font {
|
||||||
|
/// Maximum character height
|
||||||
|
scale: usize,
|
||||||
|
/// NUM_CHARS big
|
||||||
|
char_rects: Vec<GlyphInfo>,
|
||||||
|
atlas_width: usize,
|
||||||
|
atlas_height: usize,
|
||||||
|
atlas: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Font {
|
||||||
|
pub fn new(scale: usize) -> Font {
|
||||||
|
let font_data = include_bytes!("../fonts/ProggyClean.ttf");
|
||||||
|
let font = rusttype::Font::from_bytes(font_data as &[u8]).expect("Error constructing Font");
|
||||||
|
|
||||||
|
// println!(
|
||||||
|
// "font.v_metrics: {:?}",
|
||||||
|
// font.v_metrics(Scale::uniform(scale as f32))
|
||||||
|
// );
|
||||||
|
|
||||||
|
let glyphs: Vec<_> = Self::supported_characters()
|
||||||
|
.map(|c| {
|
||||||
|
let glyph = font.glyph(c);
|
||||||
|
assert_ne!(
|
||||||
|
glyph.id().0,
|
||||||
|
0,
|
||||||
|
"Failed to find a glyph for the character '{}'",
|
||||||
|
c
|
||||||
|
);
|
||||||
|
let glyph = glyph.scaled(Scale::uniform(scale as f32));
|
||||||
|
glyph.positioned(point(0.0, 0.0))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// TODO: decide dynamically?
|
||||||
|
let atlas_width = 128;
|
||||||
|
|
||||||
|
let mut atlas_height = 8;
|
||||||
|
let mut atlas = vec![0; atlas_width * atlas_height];
|
||||||
|
|
||||||
|
// Make one white pixel for use for various stuff:
|
||||||
|
atlas[0] = 255;
|
||||||
|
|
||||||
|
let mut cursor_x = 1;
|
||||||
|
let mut cursor_y = 0;
|
||||||
|
let mut row_height = 1;
|
||||||
|
|
||||||
|
let mut char_rects = vec![];
|
||||||
|
|
||||||
|
for glyph in glyphs {
|
||||||
|
let bb = glyph
|
||||||
|
.pixel_bounding_box()
|
||||||
|
.expect("Failed to get pixel bounding box");
|
||||||
|
let glyph_width = bb.width() as usize;
|
||||||
|
let glyph_height = bb.height() as usize;
|
||||||
|
assert!(glyph_width >= 1);
|
||||||
|
assert!(glyph_height >= 1);
|
||||||
|
assert!(glyph_width <= atlas_width);
|
||||||
|
if cursor_x + glyph_width > atlas_width {
|
||||||
|
// New row:
|
||||||
|
cursor_x = 0;
|
||||||
|
cursor_y += row_height;
|
||||||
|
row_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
row_height = row_height.max(glyph_height);
|
||||||
|
while cursor_y + row_height >= atlas_height {
|
||||||
|
atlas_height *= 2;
|
||||||
|
}
|
||||||
|
if atlas_width * atlas_height > atlas.len() {
|
||||||
|
atlas.resize(atlas_width * atlas_height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glyph.draw(|x, y, v| {
|
||||||
|
if v > 0.0 {
|
||||||
|
let x = x as usize;
|
||||||
|
let y = y as usize;
|
||||||
|
let px = cursor_x + x as usize;
|
||||||
|
let py = cursor_y + y as usize;
|
||||||
|
atlas[py * atlas_width + px] = (v * 255.0).round() as u8;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let offset_y = scale as i32 + bb.min.y - 3; // TODO: use font.v_metrics
|
||||||
|
assert!(0 <= bb.min.x);
|
||||||
|
assert!(0 <= offset_y && offset_y < scale as i32);
|
||||||
|
char_rects.push(GlyphInfo {
|
||||||
|
offset_x: bb.min.x as u16,
|
||||||
|
offset_y: offset_y as u16,
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
cursor_x += glyph_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font {
|
||||||
|
scale,
|
||||||
|
char_rects,
|
||||||
|
atlas_width,
|
||||||
|
atlas_height,
|
||||||
|
atlas,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn supported_characters() -> impl Iterator<Item = char> {
|
||||||
|
(FIRST_ASCII..=LAST_ASCII).map(|c| c as u8 as char)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture(&self) -> (usize, usize, &[u8]) {
|
||||||
|
(self.atlas_width, self.atlas_height, &self.atlas)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pixel(&self, x: u16, y: u16) -> u8 {
|
||||||
|
let x = x as usize;
|
||||||
|
let y = y as usize;
|
||||||
|
assert!(x < self.atlas_width);
|
||||||
|
assert!(y < self.atlas_height);
|
||||||
|
self.atlas[y * self.atlas_width + x]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glyph_info(&self, c: char) -> Option<GlyphInfo> {
|
||||||
|
let c = c as usize;
|
||||||
|
if FIRST_ASCII <= c && c <= LAST_ASCII {
|
||||||
|
Some(self.char_rects[c - FIRST_ASCII])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug_print_atlas_ascii_art(&self) {
|
||||||
|
for y in 0..self.atlas_height {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
as_ascii(&self.atlas[y * self.atlas_width..(y + 1) * self.atlas_width])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug_print_all_chars(&self) {
|
||||||
|
let max_width = 160;
|
||||||
|
let mut pixel_rows = vec![vec![0; max_width]; self.scale];
|
||||||
|
let mut cursor_x = 0;
|
||||||
|
let mut cursor_y = 0;
|
||||||
|
for c in Self::supported_characters() {
|
||||||
|
if let Some(glyph_info) = self.glyph_info(c) {
|
||||||
|
for x in glyph_info.min_x..=glyph_info.max_x {
|
||||||
|
for y in glyph_info.min_y..=glyph_info.max_y {
|
||||||
|
let pixel = self.pixel(x, y);
|
||||||
|
let rx = glyph_info.offset_x + x - glyph_info.min_x;
|
||||||
|
let ry = glyph_info.offset_y + y - glyph_info.min_y;
|
||||||
|
pixel_rows[cursor_y + ry as usize][cursor_x + rx as usize] = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor_x += 7; // TODO
|
||||||
|
if cursor_x + 7 >= max_width {
|
||||||
|
println!("{}", (0..max_width).map(|_| "X").collect::<String>());
|
||||||
|
for row in pixel_rows {
|
||||||
|
println!("{}", as_ascii(&row));
|
||||||
|
}
|
||||||
|
pixel_rows = vec![vec![0; max_width]; self.scale];
|
||||||
|
cursor_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}", (0..max_width).map(|_| "X").collect::<String>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ascii(pixels: &[u8]) -> String {
|
||||||
|
pixels
|
||||||
|
.iter()
|
||||||
|
.map(|pixel| if *pixel == 0 { ' ' } else { 'X' })
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn font_test() {
|
||||||
|
let font = Font::new(13);
|
||||||
|
font.debug_print_atlas_ascii_art();
|
||||||
|
font.debug_print_all_chars();
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,24 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
|
extern crate rusttype;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
#[macro_use] // TODO: get rid of this
|
#[macro_use] // TODO: get rid of this
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
mod emgui;
|
mod emgui;
|
||||||
|
mod font;
|
||||||
mod layout;
|
mod layout;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
mod painter;
|
||||||
mod style;
|
mod style;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
emgui::Emgui, layout::Layout, layout::LayoutOptions, style::Style, types::RawInput,
|
emgui::Emgui,
|
||||||
|
layout::Layout,
|
||||||
|
layout::LayoutOptions,
|
||||||
|
painter::{Frame, Painter, Vertex},
|
||||||
|
style::Style,
|
||||||
|
types::RawInput,
|
||||||
};
|
};
|
||||||
|
|
88
emgui/src/painter.rs
Normal file
88
emgui/src/painter.rs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/// Outputs render info in a format suitable for e.g. OpenGL.
|
||||||
|
use crate::{
|
||||||
|
font::Font,
|
||||||
|
types::{Color, PaintCmd},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct Vertex {
|
||||||
|
/// Pixel coordinated
|
||||||
|
pub x: f32,
|
||||||
|
/// Pixel coordinated
|
||||||
|
pub y: f32,
|
||||||
|
/// Texel indices into the texture
|
||||||
|
pub u: u16,
|
||||||
|
/// Texel indices into the texture
|
||||||
|
pub v: u16,
|
||||||
|
/// sRGBA
|
||||||
|
pub color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct Frame {
|
||||||
|
pub clear_color: Option<Color>,
|
||||||
|
/// One big triangle strip
|
||||||
|
pub indices: Vec<u32>,
|
||||||
|
pub vertices: Vec<Vertex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Painter {
|
||||||
|
font: Font,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Painter {
|
||||||
|
pub fn new() -> Painter {
|
||||||
|
Painter {
|
||||||
|
font: Font::new(13),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 8-bit row-major font atlas texture, (width, height, pixels).
|
||||||
|
pub fn texture(&self) -> (usize, usize, &[u8]) {
|
||||||
|
self.font.texture()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paint(&self, commands: &[PaintCmd]) -> Frame {
|
||||||
|
let mut frame = Frame::default();
|
||||||
|
for cmd in commands {
|
||||||
|
match cmd {
|
||||||
|
PaintCmd::Circle { .. } => {} // TODO
|
||||||
|
PaintCmd::Clear { fill_color } => {
|
||||||
|
frame.clear_color = Some(*fill_color);
|
||||||
|
}
|
||||||
|
PaintCmd::Line { .. } => {} // TODO
|
||||||
|
PaintCmd::Rect {
|
||||||
|
pos,
|
||||||
|
size,
|
||||||
|
fill_color,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// TODO: rounded corners, colors etc.
|
||||||
|
let idx = frame.vertices.len() as u32;
|
||||||
|
frame.indices.push(idx + 0);
|
||||||
|
frame.indices.push(idx + 0);
|
||||||
|
frame.indices.push(idx + 1);
|
||||||
|
frame.indices.push(idx + 2);
|
||||||
|
frame.indices.push(idx + 3);
|
||||||
|
frame.indices.push(idx + 3);
|
||||||
|
|
||||||
|
let vert = |x, y| Vertex {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
u: 0,
|
||||||
|
v: 0,
|
||||||
|
color: fill_color.unwrap_or(Color::WHITE),
|
||||||
|
};
|
||||||
|
|
||||||
|
frame.vertices.push(vert(pos.x, pos.y));
|
||||||
|
frame.vertices.push(vert(pos.x + size.x, pos.y));
|
||||||
|
frame.vertices.push(vert(pos.x, pos.y + size.y));
|
||||||
|
frame.vertices.push(vert(pos.x + size.x, pos.y + size.y));
|
||||||
|
}
|
||||||
|
PaintCmd::Text { .. } => {} // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,7 +57,11 @@ pub struct Color {
|
||||||
pub a: u8,
|
pub a: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn srgba(r: u8, g: u8, b: u8, a: u8) -> Color {
|
impl Color {
|
||||||
|
pub const WHITE: Color = srgba(255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn srgba(r: u8, g: u8, b: u8, a: u8) -> Color {
|
||||||
Color { r, g, b, a }
|
Color { r, g, b, a }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,24 @@ edition = "2018"
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
js-sys = "0.3"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
# web-sys = { version = "0.3.5", features = ['console', 'Performance', 'Window'] }
|
|
||||||
|
|
||||||
emgui = { path = "../emgui" }
|
emgui = { path = "../emgui" }
|
||||||
|
|
||||||
|
[dependencies.web-sys]
|
||||||
|
version = "0.3"
|
||||||
|
features = [
|
||||||
|
'Document',
|
||||||
|
'Element',
|
||||||
|
'HtmlCanvasElement',
|
||||||
|
'WebGlBuffer',
|
||||||
|
'WebGlProgram',
|
||||||
|
'WebGlRenderingContext',
|
||||||
|
'WebGlShader',
|
||||||
|
'WebGlUniformLocation',
|
||||||
|
'Window',
|
||||||
|
]
|
||||||
|
|
|
@ -9,11 +9,12 @@ extern crate emgui;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use emgui::{Emgui, RawInput};
|
use emgui::{Emgui, Frame, RawInput};
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
pub mod app;
|
mod app;
|
||||||
|
mod webgl;
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn show_gui(raw_input_json: &str) -> String {
|
pub fn show_gui(raw_input_json: &str) -> String {
|
||||||
|
@ -40,3 +41,57 @@ pub fn show_gui(raw_input_json: &str) -> String {
|
||||||
let commands = emgui.paint();
|
let commands = emgui.paint();
|
||||||
serde_json::to_string(&commands).unwrap()
|
serde_json::to_string(&commands).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn new_webgl_painter(canvas_id: &str) -> Result<webgl::Painter, JsValue> {
|
||||||
|
webgl::Painter::new(canvas_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
app: app::App,
|
||||||
|
emgui: Emgui,
|
||||||
|
emgui_painter: emgui::Painter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn new() -> State {
|
||||||
|
State {
|
||||||
|
app: Default::default(),
|
||||||
|
emgui: Default::default(),
|
||||||
|
emgui_painter: emgui::Painter::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, raw_input: RawInput) -> Frame {
|
||||||
|
self.emgui.new_frame(raw_input);
|
||||||
|
|
||||||
|
use crate::app::GuiSettings;
|
||||||
|
self.app.show_gui(&mut self.emgui.layout);
|
||||||
|
|
||||||
|
let mut style = self.emgui.style.clone();
|
||||||
|
self.emgui.layout.foldable("Style", |gui| {
|
||||||
|
style.show_gui(gui);
|
||||||
|
});
|
||||||
|
self.emgui.style = style;
|
||||||
|
|
||||||
|
let commands = self.emgui.paint();
|
||||||
|
self.emgui_painter.paint(&commands)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn paint_webgl(webgl_painter: &webgl::Painter, raw_input_json: &str) -> Result<(), JsValue> {
|
||||||
|
// TODO: nicer interface than JSON
|
||||||
|
let raw_input: RawInput = serde_json::from_str(raw_input_json).unwrap();
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref STATE: Mutex<Option<State>> = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = STATE.lock().unwrap();
|
||||||
|
if state.is_none() {
|
||||||
|
*state = Some(State::new());
|
||||||
|
}
|
||||||
|
let frame = state.as_mut().unwrap().frame(raw_input);
|
||||||
|
webgl_painter.paint(&frame)
|
||||||
|
}
|
||||||
|
|
267
emgui_wasm/src/webgl.rs
Normal file
267
emgui_wasm/src/webgl.rs
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
use {
|
||||||
|
js_sys::WebAssembly,
|
||||||
|
wasm_bindgen::{prelude::*, JsCast},
|
||||||
|
web_sys::{WebGlBuffer, WebGlProgram, WebGlRenderingContext, WebGlShader},
|
||||||
|
};
|
||||||
|
|
||||||
|
use emgui::Frame;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct Painter {
|
||||||
|
canvas: web_sys::HtmlCanvasElement,
|
||||||
|
gl: WebGlRenderingContext,
|
||||||
|
program: WebGlProgram,
|
||||||
|
index_buffer: WebGlBuffer,
|
||||||
|
pos_buffer: WebGlBuffer,
|
||||||
|
color_buffer: WebGlBuffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Painter {
|
||||||
|
pub fn new(canvas_id: &str) -> Result<Painter, JsValue> {
|
||||||
|
let document = web_sys::window().unwrap().document().unwrap();
|
||||||
|
let canvas = document.get_element_by_id(canvas_id).unwrap();
|
||||||
|
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::<web_sys::HtmlCanvasElement>()?;
|
||||||
|
|
||||||
|
let gl = canvas
|
||||||
|
.get_context("webgl")?
|
||||||
|
.unwrap()
|
||||||
|
.dyn_into::<WebGlRenderingContext>()?;
|
||||||
|
|
||||||
|
gl.enable(WebGlRenderingContext::BLEND);
|
||||||
|
gl.blend_func(
|
||||||
|
WebGlRenderingContext::SRC_ALPHA,
|
||||||
|
WebGlRenderingContext::ONE_MINUS_SRC_ALPHA,
|
||||||
|
);
|
||||||
|
|
||||||
|
let vert_shader = compile_shader(
|
||||||
|
&gl,
|
||||||
|
WebGlRenderingContext::VERTEX_SHADER,
|
||||||
|
r#"
|
||||||
|
uniform vec2 u_screen_size;
|
||||||
|
attribute vec2 a_pos;
|
||||||
|
attribute vec4 a_color;
|
||||||
|
varying vec4 v_color;
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(
|
||||||
|
2.0 * a_pos.x / u_screen_size.x - 1.0,
|
||||||
|
1.0 - 2.0 * a_pos.y / u_screen_size.y,
|
||||||
|
0.0,
|
||||||
|
1.0);
|
||||||
|
// v_color = vec4(1.0, 0.0, 0.0, 0.5);
|
||||||
|
v_color = a_color;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
let frag_shader = compile_shader(
|
||||||
|
&gl,
|
||||||
|
WebGlRenderingContext::FRAGMENT_SHADER,
|
||||||
|
r#"
|
||||||
|
precision highp float;
|
||||||
|
varying vec4 v_color;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = v_color;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
let program = link_program(&gl, [vert_shader, frag_shader].iter())?;
|
||||||
|
let index_buffer = gl.create_buffer().ok_or("failed to create index_buffer")?;
|
||||||
|
let pos_buffer = gl.create_buffer().ok_or("failed to create pos_buffer")?;
|
||||||
|
let color_buffer = gl.create_buffer().ok_or("failed to create color_buffer")?;
|
||||||
|
|
||||||
|
Ok(Painter {
|
||||||
|
canvas,
|
||||||
|
gl,
|
||||||
|
program,
|
||||||
|
index_buffer,
|
||||||
|
pos_buffer,
|
||||||
|
color_buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paint(&self, frame: &Frame) -> Result<(), JsValue> {
|
||||||
|
let gl = &self.gl;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
gl.use_program(Some(&self.program));
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
let indices: Vec<u16> = frame.indices.iter().map(|idx| *idx as u16).collect();
|
||||||
|
|
||||||
|
let mut positions = Vec::with_capacity(2 * frame.vertices.len());
|
||||||
|
for v in &frame.vertices {
|
||||||
|
positions.push(v.x);
|
||||||
|
positions.push(v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut colors = Vec::with_capacity(4 * frame.vertices.len());
|
||||||
|
for v in &frame.vertices {
|
||||||
|
colors.push(v.color.r);
|
||||||
|
colors.push(v.color.g);
|
||||||
|
colors.push(v.color.b);
|
||||||
|
colors.push(v.color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
let indices_memory_buffer = wasm_bindgen::memory()
|
||||||
|
.dyn_into::<WebAssembly::Memory>()?
|
||||||
|
.buffer();
|
||||||
|
let indices_ptr = indices.as_ptr() as u32 / 2;
|
||||||
|
let indices_array = js_sys::Int16Array::new(&indices_memory_buffer)
|
||||||
|
.subarray(indices_ptr, indices_ptr + indices.len() as u32);
|
||||||
|
|
||||||
|
gl.bind_buffer(
|
||||||
|
WebGlRenderingContext::ELEMENT_ARRAY_BUFFER,
|
||||||
|
Some(&self.index_buffer),
|
||||||
|
);
|
||||||
|
gl.buffer_data_with_array_buffer_view(
|
||||||
|
WebGlRenderingContext::ELEMENT_ARRAY_BUFFER,
|
||||||
|
&indices_array,
|
||||||
|
WebGlRenderingContext::STATIC_DRAW, // TODO: STREAM ?
|
||||||
|
);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
let pos_memory_buffer = wasm_bindgen::memory()
|
||||||
|
.dyn_into::<WebAssembly::Memory>()?
|
||||||
|
.buffer();
|
||||||
|
let pos_ptr = positions.as_ptr() as u32 / 4;
|
||||||
|
let pos_array = js_sys::Float32Array::new(&pos_memory_buffer)
|
||||||
|
.subarray(pos_ptr, pos_ptr + positions.len() as u32);
|
||||||
|
|
||||||
|
gl.bind_buffer(WebGlRenderingContext::ARRAY_BUFFER, Some(&self.pos_buffer));
|
||||||
|
gl.buffer_data_with_array_buffer_view(
|
||||||
|
WebGlRenderingContext::ARRAY_BUFFER,
|
||||||
|
&pos_array,
|
||||||
|
WebGlRenderingContext::STATIC_DRAW, // TODO: STREAM ?
|
||||||
|
);
|
||||||
|
|
||||||
|
let a_pos_loc = gl.get_attrib_location(&self.program, "a_pos");
|
||||||
|
assert!(a_pos_loc >= 0);
|
||||||
|
let a_pos_loc = a_pos_loc as u32;
|
||||||
|
|
||||||
|
let normalize = false;
|
||||||
|
let stride = 0;
|
||||||
|
let offset = 0;
|
||||||
|
gl.vertex_attrib_pointer_with_i32(
|
||||||
|
a_pos_loc,
|
||||||
|
2,
|
||||||
|
WebGlRenderingContext::FLOAT,
|
||||||
|
normalize,
|
||||||
|
stride,
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
gl.enable_vertex_attrib_array(a_pos_loc);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
let colors_memory_buffer = wasm_bindgen::memory()
|
||||||
|
.dyn_into::<WebAssembly::Memory>()?
|
||||||
|
.buffer();
|
||||||
|
let colors_ptr = colors.as_ptr() as u32;
|
||||||
|
let colors_array = js_sys::Uint8Array::new(&colors_memory_buffer)
|
||||||
|
.subarray(colors_ptr, colors_ptr + colors.len() as u32);
|
||||||
|
|
||||||
|
gl.bind_buffer(
|
||||||
|
WebGlRenderingContext::ARRAY_BUFFER,
|
||||||
|
Some(&self.color_buffer),
|
||||||
|
);
|
||||||
|
gl.buffer_data_with_array_buffer_view(
|
||||||
|
WebGlRenderingContext::ARRAY_BUFFER,
|
||||||
|
&colors_array,
|
||||||
|
WebGlRenderingContext::STATIC_DRAW, // TODO: STREAM ?
|
||||||
|
);
|
||||||
|
|
||||||
|
let a_color_loc = gl.get_attrib_location(&self.program, "a_color");
|
||||||
|
assert!(a_color_loc >= 0);
|
||||||
|
let a_color_loc = a_color_loc as u32;
|
||||||
|
|
||||||
|
let normalize = true;
|
||||||
|
let stride = 0;
|
||||||
|
let offset = 0;
|
||||||
|
gl.vertex_attrib_pointer_with_i32(
|
||||||
|
a_color_loc,
|
||||||
|
4,
|
||||||
|
WebGlRenderingContext::UNSIGNED_BYTE,
|
||||||
|
normalize,
|
||||||
|
stride,
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
gl.enable_vertex_attrib_array(a_color_loc);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
let u_screen_size_loc = gl
|
||||||
|
.get_uniform_location(&self.program, "u_screen_size")
|
||||||
|
.unwrap();
|
||||||
|
gl.uniform2f(
|
||||||
|
Some(&u_screen_size_loc),
|
||||||
|
self.canvas.width() as f32,
|
||||||
|
self.canvas.height() as f32,
|
||||||
|
);
|
||||||
|
// gl.uniform2f(Some(&u_screen_size_loc), 4.0, 1.0);
|
||||||
|
|
||||||
|
gl.clear_color(0.05, 0.05, 0.05, 1.0);
|
||||||
|
gl.clear(WebGlRenderingContext::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
gl.draw_elements_with_i32(
|
||||||
|
WebGlRenderingContext::TRIANGLE_STRIP,
|
||||||
|
indices.len() as i32,
|
||||||
|
WebGlRenderingContext::UNSIGNED_SHORT,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_shader(
|
||||||
|
gl: &WebGlRenderingContext,
|
||||||
|
shader_type: u32,
|
||||||
|
source: &str,
|
||||||
|
) -> Result<WebGlShader, String> {
|
||||||
|
let shader = gl
|
||||||
|
.create_shader(shader_type)
|
||||||
|
.ok_or_else(|| String::from("Unable to create shader object"))?;
|
||||||
|
gl.shader_source(&shader, source);
|
||||||
|
gl.compile_shader(&shader);
|
||||||
|
|
||||||
|
if gl
|
||||||
|
.get_shader_parameter(&shader, WebGlRenderingContext::COMPILE_STATUS)
|
||||||
|
.as_bool()
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
Ok(shader)
|
||||||
|
} else {
|
||||||
|
Err(gl
|
||||||
|
.get_shader_info_log(&shader)
|
||||||
|
.unwrap_or_else(|| "Unknown error creating shader".into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
|
||||||
|
gl: &WebGlRenderingContext,
|
||||||
|
shaders: T,
|
||||||
|
) -> Result<WebGlProgram, String> {
|
||||||
|
let program = gl
|
||||||
|
.create_program()
|
||||||
|
.ok_or_else(|| String::from("Unable to create shader object"))?;
|
||||||
|
for shader in shaders {
|
||||||
|
gl.attach_shader(&program, shader)
|
||||||
|
}
|
||||||
|
gl.link_program(&program);
|
||||||
|
|
||||||
|
if gl
|
||||||
|
.get_program_parameter(&program, WebGlRenderingContext::LINK_STATUS)
|
||||||
|
.as_bool()
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
Ok(program)
|
||||||
|
} else {
|
||||||
|
Err(gl
|
||||||
|
.get_program_info_log(&program)
|
||||||
|
.unwrap_or_else(|| "Unknown error creating program object".into()))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
{
|
{
|
||||||
"defaultSeverity": "error",
|
"defaultSeverity": "error",
|
||||||
"extends": [
|
"extends": ["tslint:recommended"],
|
||||||
"tslint:recommended"
|
|
||||||
],
|
|
||||||
"jsRules": {},
|
"jsRules": {},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||||
"interface-name": [true, "never-prefix"],
|
"interface-name": [true, "never-prefix"],
|
||||||
"max-classes-per-file": [false],
|
"max-classes-per-file": [false],
|
||||||
"no-bitwise": false,
|
"no-bitwise": false,
|
||||||
|
|
Loading…
Reference in a new issue